【问题标题】:Is this a 'hack', and if so is there a better way to determine which ActionResult to return?这是一个“黑客”吗?如果是,有没有更好的方法来确定要返回哪个 ActionResult?
【发布时间】:2010-09-04 12:22:13
【问题描述】:

我在每个页面上都有一个 A - Z 目录“小部件”。如果用户在主页上并且他们单击目录中的某些内容,我想加载目录页面并加载相应的结果。但是如果用户在目录页面上并且他们点击了某些东西,我想异步加载结果而不进行页面刷新。

目录小部件具有指向 GroupController 上的 DirectoryResult 操作方法的链接,如果它们位于目录页面上,通常会返回 PartialView。但如果它们不在目录页面上,我会重定向到主目录操作方法,该方法返回一个视图并加载整个页面。

这是有问题的代码:

    public ActionResult DirectoryResult(string search)
    {
        if (Request.IsAjaxRequest())
        {
            var groups = _groupService.GetGroupsBySearchExpression(search);
            var premiumGroups = _groupService.FilterPremiumGroups(groups);

            return PartialView(new FundDirectoryViewModel
            {
                Groups = groups,
                PremiumGroups = premiumGroups
            });
        }
        else
        {
            TempData[UIMessageDataKeys.FundDirectorySearch] = search;
            return RedirectToAction("Directory", "Group");
        }
    }

我把这个给办公室里的一个人看,他的第一反应是“那是黑客行为!”。我不知道是否同意他的观点,因为我不知道有什么更好的方法。

作为参考,这是每个页面上存在的小部件的定义:

<div id="DirectoryList" class="directory-list">
    <span>Fund Directory</span>

    <% var letters = new [] { "A", "B", "C", "D", "E", "F", "G", "H", "I", ... }; %>
    <% var current = (Model.Search.IsNotNullOrEmpty()) ? Model.Search : "A"; %>
    <% foreach (var letter in letters) { %>

        <span>
            // use HtmlHelper extension to generate links as our system needs them
            <%= Html.RouteActionLink("funddirectory", "DirectoryResult"
                , letter
                , (letter.ToLower() == current) ? new { @class = "active" } : new { @class = "" })%>

        </span>

    <%} %>
</div>

是否有更好的方法让我根据请求来自的页面来确定我应该返回 PartialView 还是 View?

【问题讨论】:

    标签: c# asp.net-mvc redirect routing actionmethod


    【解决方案1】:

    虽然您的视图绝对可以改进以避免所有这些意大利面条式代码(使用编辑器/显示模板和 HTML 帮助程序并避免在视图中硬编码字母表:-)),但操作方法对我来说似乎很好。使用Request.IsAjaxRequest 来确定该操作是否已通过 AJAX 请求并返回部分视图,如果没有则重定向完全没问题。

    可以认为是 hack 是使用 TempData 而不是使用查询字符串,因为如果用户在重定向页面上按 F5,他将失去上下文,但如果这是你期望的行为就可以了。

    虽然我不熟悉上下文,但我会对你办公室的人用来支持他们认为这是黑客的反应的论点感兴趣。

    【讨论】:

    • @SimpleCoder,这是我得到 +1 的最有趣的原因 :-)
    • :) 我很高兴。我以前从未见过这里使用过的标签。
    • 我认为支持他认为这是一个 hack 的理由是我没有直接调用 Directory 方法。我听取了您对使用 TempData 的建议,并将代码更改为使用 return RedirectToAction("Directory", "Group", new RouteValueDictionary{{"search", search}});。有趣的是,我使用了 TempData,因为这是 Sanderson 的 Pro ASP.NET MVC 书中所建议的。他说 TempData 在进行重定向时是有效的,因为该值仅存储到下一个请求完成为止。我会研究你关于改善观点的建议。谢谢
    • TempData 非常有用,例如,当您想要存储一些在重定向后显示给用户的消息时,但不适合持久化模型。
    【解决方案2】:

    虽然 Darin 是 100% 正确的并且您的代码不是 hack,但我通常更喜欢使用不同名称和签名的两个动作。如果您使用 AjaxOnly 操作过滤器,这尤其容易,例如: http://helios.ca/2009/05/27/aspnet-mvc-action-filter-ajax-only-attribute/

    public ActionResult DirectoryResult(string search)
    {        
            var groups = _groupService.GetGroupsBySearchExpression(search);
            var premiumGroups = _groupService.FilterPremiumGroups(groups);
    
            return PartialView(new FundDirectoryViewModel
            {
                Groups = groups,
                PremiumGroups = premiumGroups
            });        
    }
    
    //optional [AjaxOnly]
    public ActionResult DirectoryAjaxResult( string search )
    {
            TempData[UIMessageDataKeys.FundDirectorySearch] = search;
            return RedirectToAction("Directory", "Group");
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-20
      • 1970-01-01
      相关资源
      最近更新 更多