我有一个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)(默认活页夹)。

问题是:说我要在我的站点页面上添加页面按钮(更改页面),该列表将由诸如filter,sortorder,每页页面等的设置控制(由querystring控制) )。首先,我需要在URL中包含所有当前查询参数,然后我需要更新页面参数,而无需篡改其他查询参数。我如何从视图/“ HTML助手”中获得该URL?

我当然可以手动操纵URL字符串,但这将涉及很多工作,如果更改路线,很难保持最新状态,必须有一种更简单的方法?像某种可以在服务方面更改的Querystring集合(例如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类创建了一个扩展方法,该方法将对象采用对象,并将其属性名称和值与当前请求中的查询字符串合并,并返回修改后的Querystring。看起来像这样:

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

编辑:以上实现可能无法与您描述的Querystring参数名称的字典查找。这是一个实现,它使用词典而不是对象:

    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 并手动指定了这些。

这发生在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中删除值。

例子:

您的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=""}) %>

将返回u003Ca>元素中的URL:u003C/a> localhost.com/controller/action?id=10&test=yes

我猜这就是您需要的吗?

如果您还有一些其他问题,请询问。

额外的:

有时,当您将其重定向到另一个动作时,您也需要将价值保留在动作中。在我的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() 并设置所需的参数键/值。

  • 如果您使用动作 public ActionResult List(MyStrongType data), ,您需要将所有页面设置(页面索引,订购等)作为“ mystrongtype”的参数,并且数据对象将包含视图的所有信息。

  • 在视图中,如果您需要生成一个 URL, ,使用Callmelann的方法:Html.ActionLink("LinkName", "Action", "Controller", new { param1 = Model.value1, param2 = Model.param2, ... });. 。您需要在此处手动设置所有参数或创建助手以帮助您填充URL。

  • 您无需关心地址中包含的当前参数。

  • 您可以路由:routes.maproute(“ Custome”,“ {Controller}/{action}/”,new {Controller =“ HOME”,ACTION =“ index”});将所有参数作为查询字符串生成。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top