代码之家  ›  专栏  ›  技术社区  ›  Matt

NET MVC在回发之间保留操作参数

  •  8
  • Matt  · 技术社区  · 16 年前

    假设我有一个显示搜索结果的页面。我搜索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 回复  |  直到 12 年前
        1
  •  12
  •   Robert Harvey    15 年前

    我在htmlhelper中也遇到了类似的问题;我想生成链接到当前页面的链接,只需在参数上稍作调整(考虑增加页面号)。如果我有url/item/?sort=name&page=0,我希望能够创建指向同一页面的链接,但只需更改页面参数,并自动包含sort参数(ie/item/?sort=name&page=1)。

    我的解决方案是这个(用于HTMLHelpExtRead方法,但是因为您可以在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。

        2
  •  1
  •   Craig Stuntz    16 年前

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

        3
  •  1
  •   Switters    16 年前

    我有点怀疑你到底想干什么。我认为您正在尝试自动化创建链接列表的过程,它们之间只有很小的更改。显然你的身份证号码是“第页”。

    有一种方法是这样做的,尽管可能不是最好的(我的代码使用了一个基本的、人工设计的产品列表,viewpage和partialviewpage都使用强类型模型):

    在您的视图页上,您可以添加如下代码:

    <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从父视图传递的model/viewdata

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

    希望这有帮助。

        4
  •  1
  •   Jalal El-Shaer    15 年前

    下面的helper方法就是这样做的:

        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;
        }
    
        5
  •  0
  •   Florin Gugui    14 年前

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

        6
  •  0
  •   Community CDub    8 年前

    在花了数小时尝试不同的解决方案后,只有这一个对我有效: MVC ActionLink add all (optional) parameters from current url

        7
  •  0
  •   h3n    12 年前

    这是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);
            }
    
        }
    
    
        8
  •  0
  •   Mr Jones    12 年前

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

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