ASP.NET MVC,Querystring,路由和默认绑定器,我该如何组合呢?

我有一个使用强类型视图的ASP.NET MVC站点。在我的例子中,控制器动作可能如下所示:
public ActionResult List(MyStrongType data)
提交页面(视图)时,响应将生成一个类似于此的URL(是的,我知道路由可以生成更好的URL):
http://localhost/Ad/List?F.ShowF=0&ALS.CP=30&ALS.L=0&ALS.OB=0&ALS.ST=0&S=&LS.L1=&LS.L2=&CS.C1=32&CS.C2=34&CS.C3=&ALS.ST=0
如果我再次提交页面,我可以看到操作中的数据对象设置正确(根据URL)(默认活页夹)。 问题是:假设我要为我的网页上的列表添加页面按钮(更改页面),列表将由过滤器,排序顺序,每页页面数等设置控制(由查询字符串控制) )。首先,我需要在URL中包含所有当前查询参数,然后我需要更新页面参数而不篡改其他查询参数。如何从视图/“HTML帮助器”中生成此URL? 我当然可以手动操作URL字符串,但是这将涉及大量工作,如果路由发生变化,很难保持最新状态,必须有更简单的方法吗?就像某种可以在服务端更改的查询字符串集合(如ASP.NET Request.QueryString)? 我希望不涉及这条路线,但我发布了迄今为止我得到的路线:
    routes.MapRoute(
        "Default",
        "{controller}/{action}/{id}",
        new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );

    routes.MapRoute(
        "TreeEditing",
        "{controller}/{action}/{name}/{id}",
        new { controller = "MyCategory", action = "Add", name = string.Empty, id = -1 }
    );
最好的祝福 编辑1:可以像这样设置查询参数(在视图中):
<%= url.Action(new {controller="search", action="result", query="Beverages", Page=2})%>
但这只会生成这样的URL(使用默认路由):
/search/result?query=Beverages&page=2
您可以看到其余参数将丢失。 我当然可以在此URL操作中添加每个已知参数,但是如果添加或更改任何查询参数,将会有很多工作来保持所有内容都是最新的。 我已经阅读了ASP.NET MVC框架(第2部分)文章:URL路由,但我如何找到问题的答案?     
已邀请:
对我来说,问题就是你希望能够轻松地从当前请求中保存查询字符串值并将它们呈现到视图中链接的URL中。一种解决方案是创建一个HtmlHelper方法,该方法返回现有的查询字符串并进行一些更改。我为HtmlHelper类创建了一个扩展方法,它接受一个对象并将其属性名称和值与当前请求中的查询字符串合并,并返回修改后的查询字符串。它看起来像这样:
public static class StackOverflowExtensions
{
    public static string UpdateCurrentQueryString(this HtmlHelper helper, object parameters)
    {
        var newQueryStringNameValueCollection = new NameValueCollection(HttpContext.Current.Request.QueryString);
        foreach (var propertyInfo in parameters.GetType().GetProperties(BindingFlags.Public))
        {
            newQueryStringNameValueCollection[propertyInfo.Name] = propertyInfo.GetValue(parameters, null).ToString();
        }

        return ToQueryString(newQueryStringNameValueCollection);
    }

    private static string ToQueryString(NameValueCollection nvc)
    {
        return "?" + string.Join("&", Array.ConvertAll(nvc.AllKeys, key => string.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(nvc[key]))));
    }
}
它将遍历当前请求中的查询字符串值,并合并到您传入的对象上定义的属性中。因此,您的视图代码可能如下所示:
<a href='/SomeController/SomeAction<%=Html.GetCurrentQueryStringWithReplacements(new {page = "2", parameter2 = "someValue"})%>'>Some Link</a>
这基本上是说“保留当前请求中的查询字符串,但更改页面和参数2值,或者如果它们不存在则创建它们。”请注意,如果当前请求具有“页面”查询字符串参数,则此方法将使用您从视图中显式传入的值覆盖当前请求中的值。 在这种情况下,如果您的查询字符串是:
?parameter1=abc&page=1
它会变成:
?parameter1=abc&page=2&parameter2=someValue
编辑: 上述实现可能不适用于您描述的查询字符串参数名称的字典查找。这是一个实现,它使用字典而不是对象:
    public static string UpdateCurrentQueryString(this HtmlHelper helper, Dictionary<string, string> newParameters)
    {
        var newQueryStringNameValueCollection = new NameValueCollection(HttpContext.Current.Request.QueryString);
        foreach (var parameter in newParameters)
        {
            newQueryStringNameValueCollection[parameter.Key] = parameter.Value;
        }

        return ToQueryString(newQueryStringNameValueCollection);
    }
您的视图将通过对字典进行内联初始化并将其传递给辅助函数来调用该函数,如下所示:
<a href='/SomeController/SomeAction<%=Html.GetCurrentQueryStringWithReplacements(new Dictionary<string,string>() {
{ QuerystringHandler.Instance.KnownQueryParameters[QuaryParameters.PageNr], "2" },
{ QuerystringHandler.Instance.KnownQueryParameters[QuaryParameters.AnotherParam], "1234" }})%>'>Some Link</a>
    
我只做你需要的! 我为此创建了一个HTML帮助器。帮助程序采用与普通帮助程序相同的参数。然而,它保留了URL中的当前值。我为
URL helper
做了
ActionLink helper
。 这取代了:
Url.Action()
<a href='<%= Html.UrlwParams("TeamStart","Inschrijvingen", new {modID=item.Mod_ID}) %>'  title="Selecteer">
    <img src="<%= Url.Content("~/img/arrow_right.png") %>" alt="Selecteer" width="16" /></a>
这取代了
Html.ActionLink()
<%: Html.ActionLinkwParams("Tekst of url", "Action", new {test="yes"}) %>
这是帮手:
using System;
using System.Web.Mvc;
using System.Web.Routing;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Web.Mvc.Html;

namespace MVC2_NASTEST.Helpers {
    public static class ActionLinkwParamsExtensions {
        public static MvcHtmlString ActionLinkwParams(this HtmlHelper helper, string linktext, string action, string controller, object extraRVs, object htmlAttributes) {

            NameValueCollection c = helper.ViewContext.RequestContext.HttpContext.Request.QueryString;

            RouteValueDictionary r = new RouteValueDictionary();
            foreach (string s in c.AllKeys) {
                r.Add(s, c[s]);
            }

            RouteValueDictionary htmlAtts = new RouteValueDictionary(htmlAttributes);

            RouteValueDictionary extra = new RouteValueDictionary(extraRVs);

            RouteValueDictionary m = RouteValues.MergeRouteValues(r, extra);

            //return System.Web.Mvc.Html.LinkExtensions.ActionLink(helper, linktext, action, controller, m, htmlAtts);
            return helper.ActionLink(linktext, action, controller, m, htmlAtts);
        }

        public static MvcHtmlString ActionLinkwParams(this HtmlHelper helper, string linktext, string action) {
            return ActionLinkwParams(helper, linktext, action, null, null, null);
        }

        public static MvcHtmlString ActionLinkwParams(this HtmlHelper helper, string linktext, string action, string controller) {
            return ActionLinkwParams(helper, linktext, action, controller, null, null);
        }

        public static MvcHtmlString ActionLinkwParams(this HtmlHelper helper, string linktext, string action, object extraRVs) {
            return ActionLinkwParams(helper, linktext, action, null, extraRVs, null);
        }

        public static MvcHtmlString ActionLinkwParams(this HtmlHelper helper, string linktext, string action, string controller, object extraRVs) {
            return ActionLinkwParams(helper, linktext, action, controller, extraRVs, null);
        }

        public static MvcHtmlString ActionLinkwParams(this HtmlHelper helper, string linktext, string action, object extraRVs, object htmlAttributes) {
            return ActionLinkwParams(helper, linktext, action, null, extraRVs, htmlAttributes);
        }
    }

    public static class UrlwParamsExtensions {
        public static string UrlwParams(this HtmlHelper helper, string action, string controller, object extraRVs) {
            NameValueCollection c = helper.ViewContext.RequestContext.HttpContext.Request.QueryString;

            RouteValueDictionary r = RouteValues.optionalParamters(c);

            RouteValueDictionary extra = new RouteValueDictionary(extraRVs);

            RouteValueDictionary m = RouteValues.MergeRouteValues(r, extra);

            string s = UrlHelper.GenerateUrl("", action, controller, m, helper.RouteCollection, helper.ViewContext.RequestContext, false);
            return s;
        }

        public static string UrlwParams(this HtmlHelper helper, string action) {
            return UrlwParams(helper, action, null, null);
        }

        public static string UrlwParams(this HtmlHelper helper, string action, string controller) {
            return UrlwParams(helper, action, controller, null);
        }

        public static string UrlwParams(this HtmlHelper helper, string action, object extraRVs) {
            return UrlwParams(helper, action, null, extraRVs);
        }
    }
}
它是如何工作的? 这些电话与
Html.ActionLink()
相同,所以你可以简单地取代它们。 该方法执行以下操作: 它从当前URL获取所有可选参数,并将它们放在
RouteValueDictionary
中。 它还将
htmlattributes
放在字典中。 然后它需要手动指定的额外路由值,并将它们放在
RouteValueDictionary
中。 然后,关键是合并URL中的URL和手动指定的URL。 这发生在RouteValues类中。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;
using System.Collections.Specialized;
using System.Web.Mvc;

namespace MVC2_NASTEST {
    public static class RouteValues {

        public static RouteValueDictionary optionalParamters() {
            return optionalParamters(HttpContext.Current.Request.QueryString);
        }

        public static RouteValueDictionary optionalParamters(NameValueCollection c) {
            RouteValueDictionary r = new RouteValueDictionary();
            foreach (string s in c.AllKeys) {
                r.Add(s, c[s]);
            }
            return r;
        }

        public static RouteValueDictionary MergeRouteValues(this RouteValueDictionary original, RouteValueDictionary newVals) {
            // Create a new dictionary containing implicit and auto-generated values
            RouteValueDictionary merged = new RouteValueDictionary(original);

            foreach (var f in newVals) {
                if (merged.ContainsKey(f.Key)) {
                    merged[f.Key] = f.Value;
                } else {
                    merged.Add(f.Key, f.Value);
                }
            }
            return merged;
        }

        public static RouteValueDictionary MergeRouteValues(this RouteValueDictionary original, object newVals) {
            return MergeRouteValues(original, new RouteValueDictionary(newVals));
        }
    }
}
这一切都非常简单。最后,
actionlink
由合并的路由值构成。此代码还允许您从URL中删除值。 例子: 您的网址是
localhost.com/controller/action?id=10&foo=bar
。如果在该页面中放置此代码
 <%: Html.ActionLinkwParams("Tekst of url", "Action", new {test="yes"}) %>
该元素中返回的URL将为
localhost.com/controller/action?id=10&foo=bar&test=yes
。 如果要删除项目,只需将项目设置为空字符串即可。例如,
 <%: Html.ActionLinkwParams("Tekst of url", "Action", new {test="yes", foo=""}) %>
将返回&lt; a>元素中的URL:
localhost.com/controller/action?id=10&test=yes
我猜这就是你需要的一切? 如果您还有其他问题,请询问。 额外: 当您重定向到另一个Action时,有时您也希望将值保留在您的操作中。使用我的RouteValues类,可以非常轻松地完成:
 public ActionResult Action(string something, int? somethingelse) {
                    return RedirectToAction("index", routeValues.optionalParamters(Request.QueryString));
 }
如果你还想添加一些可选参数,没问题!
 public ActionResult Action(string something, int? somethingelse) {
                    return RedirectToAction("index", routeValues.optionalParamters(Request.QueryString).MergeRouteValues(new{somethingelse=somethingelse}));
 }
我认为这几乎涵盖了你需要的一切。     
如果要在视图的链接中设置查询字符串:
Html.ActionLink("LinkName", "Action", "Controller", new { param1 = value1, param2 = value2 }, ...)
如果要在回发后在浏览器URL中设置它,只需在
RouteToAction()
之类的操作中调用Route *并设置所需的参数键/值。     
如果使用动作
public ActionResult List(MyStrongType data)
,则需要将所有页面设置(页面索引,排序等)作为参数包含在“MyStrongType”中,并且数据对象将包含视图的所有信息。 在视图中,如果您需要使用CallMeLaNN的方法生成URL:
Html.ActionLink("LinkName", "Action", "Controller", new { param1 = Model.value1, param2 = Model.param2, ... });
。您需要在此处手动设置所有参数或创建帮助程序以帮助您填写URL。 您无需关心地址中包含的当前参数。 你可以路线: routes.MapRoute(     “custome”     “{控制器} / {行动} /”,     new {controller =“Home”,action =“Index”} ); 生成所有参数作为查询字符串。     

要回复问题请先登录注册