ASP.Net MVC在回发之间保留动作参数

时间:2020-03-06 14:36:32  来源:igfitidea点击:

假设我有一个显示搜索结果的页面。我搜索stackoverflow,它返回5000个结果,每页10个。现在,我发现自己在该页面上构建链接时正在执行此操作:

<%=Html.ActionLink("Page 1", "Search", new { query=ViewData["query"], page etc..%>
<%=Html.ActionLink("Page 2", "Search", new { query=ViewData["query"], page etc..%>
<%=Html.ActionLink("Page 3", "Search", new { query=ViewData["query"], page etc..%>
<%=Html.ActionLink("Next", "Search", new { query=ViewData["query"], page etc..%>

我不喜欢这样,我必须仔细考虑以前发布的内容等来建立我的链接。

我想做的是

<%=Html.BuildActionLinkUsingCurrentActionPostData
        ("Next", "Search", new { Page = 1});

其中匿名字典会覆盖当前由上一个操作设置的所有内容。

本质上,我关心先前的动作参数是什么,因为我想重用,它听起来很简单,但是开始添加排序和大量高级搜索选项,并且开始变得混乱。

我可能缺少明显的东西

解决方案

每当我们发现自己在视图中编写多余的代码时,请编写一个帮助程序。就像我们现在正在做的那样,帮助程序可以显式复制参数,也可以迭代整个集合并自动复制。如果是我,我可能会选择前者。然后,我们可以仅调用新的帮助程序,而不必每次建立链接时都重新构建参数。

对于我们实际上在这里尝试做什么,我有些怀疑。我认为我们正在尝试使创建链接列表的过程自动化,而仅在它们之间进行很小的更改。显然,情况是ID为" Page"。

一种实现方法,尽管可能不是最好的(例如,我的代码利用了基本的人为产品列表,而ViewPage和PartialViewPage都使用了强类型模型):

在ViewPage上,我们将添加如下代码:

<div id="product_list">
        <% foreach (TestMVC.Product product in ViewData.Model)
           { %>
            <% Html.RenderPartial("ProductEntry", product); %>
        <% } %>
</div>

部分视图(在我的情况下为" ProductEntry")将如下所示:

<div class="product">
    <div class="product-name">
        <%= Html.ActionLink(ViewData.Model.ProductName, "Detail", new { id = ViewData.Model.id })%>
    </div> 
    <div class="product-desc">
        <%= ViewData.Model.ProductDescription %>
    </div>       
</div>

我在Partial View中所做的所有工作都是使用通过调用Html.RenderPartial从父视图传递的模型/视图数据。

在父视图中,可以在调用Html.RenderPartial之前修改模型对象上的参数,以便设置我们感兴趣的特定值。

希望这可以帮助。

我在HtmlHelper中遇到了类似的问题;我想生成链接回当前页面的链接,并在参数上进行少量调整(请考虑增加页码)。因此,如果我有URL / Item /?sort = Name&page = 0,我希望能够创建指向同一页面的链接,但是只需更改page参数,并自动包含sort参数(即/ Item /?sort =名称和页面= 1)。

我的解决方案是这样的(用于HtmlHelper扩展方法中,但是由于我们几乎可以在MVC中的任何位置访问相同的数据,因此可以轻松地使其适应使用):

private static RouteValueDictionary CreateRouteToCurrentPage(HtmlHelper html)
{
    RouteValueDictionary routeValues 
         = new RouteValueDictionary(html.ViewContext.RouteData.Values);

    NameValueCollection queryString 
         = html.ViewContext.HttpContext.Request.QueryString;

    foreach (string key in queryString.Cast<string>())
    {
        routeValues[key] = queryString[key];
    }

    return routeValues;
}

该方法的作用是为当前请求获取RouteValueDictionary并创建它的副本。然后,它将在查询字符串中找到的每个查询参数添加到此路由。这样做是因为出于某种原因,当前请求的RouteValueDictionary不包含它们(我们认为会包含,但不包含)。

然后,我们可以使用结果字典,仅对其一部分进行修改,例如:

routeValues["page"] = 2;

然后将该字典提供给现成的HtmlHelper方法,以使它们为我们生成一个URL / etc。

以下帮助程序方法可以做到这一点:

public static string EnhancedActionLink(this HtmlHelper helper, string linkText, string actionName, string controllerName, bool keepQueryStrings)
    {
        ViewContext context = helper.ViewContext;
        IDictionary<string, object> htmlAttributes = null;
        RouteValueDictionary routeValues = null;
        string actionLink = string.Empty;
        if (keepQueryStrings && context.RequestContext.HttpContext.Request.QueryString.Keys.Count > 0)
        {
            routeValues = new RouteValueDictionary(context.RouteData.Values);
            foreach (string key in context.RequestContext.HttpContext.Request.QueryString.Keys)
            {
                routeValues[key] = context.RequestContext.HttpContext.Request.QueryString[key];
            }
        }            
        actionLink = helper.ActionLink(linkText, actionName, controllerName, routeValues, htmlAttributes);
        return actionLink;
    }

看看这个,这是一个很好的例子:
http://nerddinnerbook.s3.amazonaws.com/Part8.htm