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

时间:2008-09-23 16:26:16

标签: asp.net-mvc asp.net-mvc-routing

假设我有一个显示搜索结果的页面。我搜索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});

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

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

我可能错过了一些明显的东西

8 个答案:

答案 0 :(得分:12)

我在HtmlHelper中遇到了类似的问题;我希望生成链接到当前页面的链接,并对参数进行少量调整(想想增加页码)。因此,如果我有URL / Item /?sort = Name&amp; page = 0,我希望能够创建指向同一页面的链接,但只需更改页面参数,并自动包含sort参数(即/ Item /?排序=名称&安培;页= 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 /等。

答案 1 :(得分:1)

每当您发现自己在视图中编写冗余代码时write a helper。帮助程序可以显式复制参数,就像您现在正在执行的那样,或者它可以迭代整个集合并自动复制。如果是我,我可能会选择前者。然后你可以调用你的新助手,而不是每次建立链接时重建参数。

答案 2 :(得分:1)

对于你在这里尝试做什么,我有点不确定。我认为您正在尝试自动创建链接列表的过程,它们之间只有很小的变化。显然,在您的情况下,“页面”的ID号。

一种方法,虽然可能不是最好的(我的代码使用基本和设计的产品列表,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>

我在该局部视图中所做的全部是使用通过调用Html.RenderPartial从父视图传递的模型/视图数据

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

希望这有帮助。

答案 3 :(得分:1)

以下辅助方法可以做到:

    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;
    }

答案 4 :(得分:0)

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

答案 5 :(得分:0)

花了几个小时尝试不同的解决方案只有这个适合我: MVC ActionLink add all (optional) parameters from current url

答案 6 :(得分:0)

这是actionlink扩展


  public static class ActionLinkExtension
    {
        public static MvcHtmlString ActionLinkWithQueryString(this HtmlHelper helper, string linkText, string action, string controller, object routeValues)
        {
            var context = helper.ViewContext;

            var currentRouteValues = new RouteValueDictionary(context.RouteData.Values);
            foreach (string key in context.HttpContext.Request.QueryString.Keys)
            {
                currentRouteValues[key] = context.HttpContext.Request.QueryString[key];
            }

            var newRouteValues = new RouteValueDictionary(routeValues);

            foreach (var route in newRouteValues)
            {
                if (!currentRouteValues.ContainsKey(route.Key))
                {
                    currentRouteValues.Add(route.Key, route.Value);
                }
                else
                {
                    currentRouteValues[route.Key] = route.Value;
                }
            }

            return helper.ActionLink(linkText, action, controller, currentRouteValues, null);
        }

    }

答案 7 :(得分:0)

不完全是答案,但值得指出:如果你想要分页功能,请使用PagedList Nuget包(无需重新发明轮子)。以下链接提供了如何使用它的一个非常好的示例:ASP.NET Tutorial

这对您特别有用,因为在页面之间切换时,查询字符串会保存在URL中。