MVC ActionLink从当前url添加所有(可选)参数

时间:2022-06-07 11:03:23

The very famous ActionLink:

非常有名的ActionLink:

 <%: Html.ActionLink("Back to List", "Index")%>

Now, this link is in my Details view. The Index view is a search page. The URL of that looks like this:

现在,此链接位于我的详细信息视图中。索引视图是搜索页面。其URL如下所示:

http://localhost:50152/2011-2012/Instelling/Details/76?gemeente=Dendermonde&postcode=92**&gebruikerscode=VVKSO114421&dossiernr=114421%20&organisatie=CLB

As you can see, quite the amount of parameters. Obviously I want to keep all these parameters when I return to the Index page, so I need to add them in the ActionLink.

如您所见,相当多的参数。显然我想在返回Index页面时保留所有这些参数,所以我需要在ActionLink中添加它们。

Now, I'm tired of doing that manually, it's ok for 1, but not for 6. This should go a lot easier.

现在,我已经厌倦了手动操作,它可以1,但不适用于6.这应该会更容易。

Question: How do I return All parameters of the current URL into the ActionLink as optional RouteValues.

问题:如何将当前URL的所有参数作为可选的RouteValues返回到ActionLink。

I've been looking to Request.QueryString. It has to be something with that. I was thinking of writing some static method in Global.asax doing the job but no luck yet. Maybe there is an easy way to do this which I don't know about?

我一直在寻找Request.QueryString。它必须是那样的东西。我正在考虑在Global.asax中编写一些静态方法来完成工作,但还没有运气。也许有一种简单的方法可以做到这一点,我不知道呢?

Edit: This is what I came up with (which works)

编辑:这是我想出的(哪个有效)

In global.asax:

在global.asax中:

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

Details.aspx:

Details.aspx:

    <%: Html.ActionLink("Back to List", "Index", MVC2_NASTEST.MvcApplication.optionalParamters(Request.QueryString))%>

Where do I best put this code? not in Global.asax I guess...

我最好把这段代码放在哪里?不在Global.asax我猜...

Edit 2:

编辑2:

using System;
using System.Web.Mvc;

namespace MVC2_NASTEST.Helpers {
    public static class ActionLinkwParamsExtensions {
        public static MvcHtmlString CustomLink(this HtmlHelper helper, string linktext) {
            //here u can use helper to get View context and then routvalue dictionary
            var routevals = helper.ViewContext.RouteData.Values;
            //here u can do whatever u want with route values
            return null;
        }

    }
}


<%@ Import Namespace="MVC2_NASTEST.Helpers" %>
...
<%: Html.ActionLinkwParams("Index") %>

5 个解决方案

#1


20  

This is how I finally fixed it, and i'm rather proud because it's working very well and very DRY.

这就是我最终解决它的方式,我很自豪,因为它工作得非常好而且非常干燥。

The call in the View:

视图中的调用:

    <%: Html.ActionLinkwParams("Back to List", "Index")%>

but with the overloads it can be anything which a normal ActionLink takes.

但是有了重载,它可以是普通ActionLink所采用的任何东西。

The Helper:

帮助者:

The helper takes all parameters from the url which are not in the route. For example: this url:

帮助程序从URL中获取不在路径中的所有参数。例如:这个网址:

http://localhost:50152/2011-2012/myController/Details/77?postalCode=9***&org=CLB

So it will take the postalCode and the Org and place it in the new ActionLink. With the overload, additional parameters can be added, and parameters from the existing url can be removed.

因此它将采用postalCode和Org并将其放入新的ActionLink中。通过过载,可以添加其他参数,并且可以删除现有URL中的参数。

using System;
using System.Web.Mvc;
using System.Web.Routing;
using System.Collections.Specialized;
using System.Collections.Generic;

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 = Merge(r, extra);

            return System.Web.Mvc.Html.LinkExtensions.ActionLink(helper, 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);
        }




        static RouteValueDictionary Merge(this RouteValueDictionary original, RouteValueDictionary @new) {

            // Create a new dictionary containing implicit and auto-generated values
            RouteValueDictionary merged = new RouteValueDictionary(original);

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

            return merged;

        }
    }

}

In the View using overloads:

在使用重载的视图中:

 <%: Html.ActionLinkwParams("Back to List", "Index","myController", new {testValue = "This is a test", postalCode=String.Empty}, new{ @class="test"})%>

in the URL I have the paramters postalCode with some value. my code takes All of them in the URL, by setting it to string.Empty, I remove this parameter from the list.

在URL我有paramters postalCode有一些价值。我的代码在URL中获取所有这些代码,通过将其设置为string.Empty,我从列表中删除此参数。

Comments or ideas welcome on optimizing it.

欢迎评论或想法优化它。

#2


9  

Create a ToRouteValueDictionary() extension method for Request.QueryString to use Html.ActionLink as-is and simplify your view markup:

为Request.QueryString创建一个ToRouteValueDictionary()扩展方法,以便按原样使用Html.ActionLink并简化视图标记:

<%: Html.ActionLink("Back to List", "Index", Request.QueryString.ToRouteValueDictionary())%>

Your extension method might look like this:

您的扩展方法可能如下所示:

using System.Web.Routing;
using System.Collections.Specialized;

namespace MyProject.Extensions
{
    public static class CollectionExtensions
    {
        public static RouteValueDictionary ToRouteValueDictionary(this NameValueCollection collection)
        {
            var routeValueDictionary = new RouteValueDictionary();
            foreach (var key in collection.AllKeys)
            {
                routeValueDictionary.Add(key, collection[key]);
            }
            return routeValueDictionary;
        }
    }
}

To use the extension method in your view see this question and answer: How do I use an extension method in an ASP.NET MVC View?

要在视图中使用扩展方法,请参阅此问题和答案:如何在ASP.NET MVC视图中使用扩展方法?

This is simpler and involves much less code than the accepted answer.

这比接受的答案更简单,代码少得多。

#3


5  

Here is an extension method for ViewContext that creates a RouteValueDictionary based on the request route values and querystring.

这是ViewContext的扩展方法,它根据请求路由值和查询字符串创建RouteValueDictionary。

using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;

namespace MyMvcApplication.Utilities
{
    public static class ViewContextExtensions
    {
        /// <summary>
        /// Builds a RouteValueDictionary that combines the request route values, the querystring parameters,
        /// and the passed newRouteValues. Values from newRouteValues override request route values and querystring
        /// parameters having the same key.
        /// </summary>
        public static RouteValueDictionary GetCombinedRouteValues(this ViewContext viewContext, object newRouteValues)
        {
            RouteValueDictionary combinedRouteValues = new RouteValueDictionary(viewContext.RouteData.Values);

            NameValueCollection queryString = viewContext.RequestContext.HttpContext.Request.QueryString;
            foreach (string key in queryString.AllKeys.Where(key => key != null))
                combinedRouteValues[key] = queryString[key];

            if (newRouteValues != null)
            {
                foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(newRouteValues))
                    combinedRouteValues[descriptor.Name] = descriptor.GetValue(newRouteValues);
            }


            return combinedRouteValues;
        }
    }
}

You can pass the created RouteValueDictionary to Html.ActionLink or Url.Action

您可以将创建的RouteValueDictionary传递给Html.ActionLink或Url.Action

@Html.ActionLink("5", "Index", "Product",
    ViewContext.GetCombinedRouteValues(new { Page = 5 }),
    new Dictionary<string, object> { { "class", "page-link" } })

If the Page parameter does not exist in the request URL, it will be added in the generated URL. If it does exist, its value will be changed to 5.

如果请求URL中不存在Page参数,则会将其添加到生成的URL中。如果确实存在,则其值将更改为5。

This article has a more detailed explanation of my solution.

本文对我的解决方案有更详细的解释。

#4


1  

public static class Helpers
    {
        public static MvcHtmlString CustomLink(this HtmlHelper helper,string LinkText, string actionName)
        {
            var rtvals = helper.ViewContext.RouteData.Values;
            var rtvals2 = helper.RouteCollection;
            RouteValueDictionary rv = new RouteValueDictionary();
            foreach (string param in helper.ViewContext.RequestContext.HttpContext.Request.QueryString.AllKeys) 
            {
                rv.Add(param, helper.ViewContext.RequestContext.HttpContext.Request.QueryString[param]);
            }
            foreach (var k in helper.ViewContext.RouteData.Values) 
            {
                rv.Add(k.Key, k.Value);
            }
            return helper.ActionLink(LinkText, actionName, rv);
        }
    }

i have tested this and its working. optional parameters can be acquired from query string HTH

我测试了这个和它的工作。可以从查询字符串HTH获取可选参数

#5


0  

Perhaps the best way is to write your own html helper where you traverse through the previous route value dictionary and add route values to the current action link, except the action parameter off course.

也许最好的方法是在遍历前一个路由值字典的地方编写自己的html帮助程序,并将路由值添加到当前操作链接,但当前操作参数除外。

edit: You can write the html helper like this:

编辑:您可以像这样编写html帮助器:

public static MvcHtmlString CustomLink(this HtmlHelper helper,string linktext) 
{
    //here you can use helper to get View context and then routvalue dictionary
    var routevals = helper.ViewContext.RouteData.Values;
    //here you can do whatever you want with route values
}

#1


20  

This is how I finally fixed it, and i'm rather proud because it's working very well and very DRY.

这就是我最终解决它的方式,我很自豪,因为它工作得非常好而且非常干燥。

The call in the View:

视图中的调用:

    <%: Html.ActionLinkwParams("Back to List", "Index")%>

but with the overloads it can be anything which a normal ActionLink takes.

但是有了重载,它可以是普通ActionLink所采用的任何东西。

The Helper:

帮助者:

The helper takes all parameters from the url which are not in the route. For example: this url:

帮助程序从URL中获取不在路径中的所有参数。例如:这个网址:

http://localhost:50152/2011-2012/myController/Details/77?postalCode=9***&org=CLB

So it will take the postalCode and the Org and place it in the new ActionLink. With the overload, additional parameters can be added, and parameters from the existing url can be removed.

因此它将采用postalCode和Org并将其放入新的ActionLink中。通过过载,可以添加其他参数,并且可以删除现有URL中的参数。

using System;
using System.Web.Mvc;
using System.Web.Routing;
using System.Collections.Specialized;
using System.Collections.Generic;

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 = Merge(r, extra);

            return System.Web.Mvc.Html.LinkExtensions.ActionLink(helper, 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);
        }




        static RouteValueDictionary Merge(this RouteValueDictionary original, RouteValueDictionary @new) {

            // Create a new dictionary containing implicit and auto-generated values
            RouteValueDictionary merged = new RouteValueDictionary(original);

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

            return merged;

        }
    }

}

In the View using overloads:

在使用重载的视图中:

 <%: Html.ActionLinkwParams("Back to List", "Index","myController", new {testValue = "This is a test", postalCode=String.Empty}, new{ @class="test"})%>

in the URL I have the paramters postalCode with some value. my code takes All of them in the URL, by setting it to string.Empty, I remove this parameter from the list.

在URL我有paramters postalCode有一些价值。我的代码在URL中获取所有这些代码,通过将其设置为string.Empty,我从列表中删除此参数。

Comments or ideas welcome on optimizing it.

欢迎评论或想法优化它。

#2


9  

Create a ToRouteValueDictionary() extension method for Request.QueryString to use Html.ActionLink as-is and simplify your view markup:

为Request.QueryString创建一个ToRouteValueDictionary()扩展方法,以便按原样使用Html.ActionLink并简化视图标记:

<%: Html.ActionLink("Back to List", "Index", Request.QueryString.ToRouteValueDictionary())%>

Your extension method might look like this:

您的扩展方法可能如下所示:

using System.Web.Routing;
using System.Collections.Specialized;

namespace MyProject.Extensions
{
    public static class CollectionExtensions
    {
        public static RouteValueDictionary ToRouteValueDictionary(this NameValueCollection collection)
        {
            var routeValueDictionary = new RouteValueDictionary();
            foreach (var key in collection.AllKeys)
            {
                routeValueDictionary.Add(key, collection[key]);
            }
            return routeValueDictionary;
        }
    }
}

To use the extension method in your view see this question and answer: How do I use an extension method in an ASP.NET MVC View?

要在视图中使用扩展方法,请参阅此问题和答案:如何在ASP.NET MVC视图中使用扩展方法?

This is simpler and involves much less code than the accepted answer.

这比接受的答案更简单,代码少得多。

#3


5  

Here is an extension method for ViewContext that creates a RouteValueDictionary based on the request route values and querystring.

这是ViewContext的扩展方法,它根据请求路由值和查询字符串创建RouteValueDictionary。

using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;

namespace MyMvcApplication.Utilities
{
    public static class ViewContextExtensions
    {
        /// <summary>
        /// Builds a RouteValueDictionary that combines the request route values, the querystring parameters,
        /// and the passed newRouteValues. Values from newRouteValues override request route values and querystring
        /// parameters having the same key.
        /// </summary>
        public static RouteValueDictionary GetCombinedRouteValues(this ViewContext viewContext, object newRouteValues)
        {
            RouteValueDictionary combinedRouteValues = new RouteValueDictionary(viewContext.RouteData.Values);

            NameValueCollection queryString = viewContext.RequestContext.HttpContext.Request.QueryString;
            foreach (string key in queryString.AllKeys.Where(key => key != null))
                combinedRouteValues[key] = queryString[key];

            if (newRouteValues != null)
            {
                foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(newRouteValues))
                    combinedRouteValues[descriptor.Name] = descriptor.GetValue(newRouteValues);
            }


            return combinedRouteValues;
        }
    }
}

You can pass the created RouteValueDictionary to Html.ActionLink or Url.Action

您可以将创建的RouteValueDictionary传递给Html.ActionLink或Url.Action

@Html.ActionLink("5", "Index", "Product",
    ViewContext.GetCombinedRouteValues(new { Page = 5 }),
    new Dictionary<string, object> { { "class", "page-link" } })

If the Page parameter does not exist in the request URL, it will be added in the generated URL. If it does exist, its value will be changed to 5.

如果请求URL中不存在Page参数,则会将其添加到生成的URL中。如果确实存在,则其值将更改为5。

This article has a more detailed explanation of my solution.

本文对我的解决方案有更详细的解释。

#4


1  

public static class Helpers
    {
        public static MvcHtmlString CustomLink(this HtmlHelper helper,string LinkText, string actionName)
        {
            var rtvals = helper.ViewContext.RouteData.Values;
            var rtvals2 = helper.RouteCollection;
            RouteValueDictionary rv = new RouteValueDictionary();
            foreach (string param in helper.ViewContext.RequestContext.HttpContext.Request.QueryString.AllKeys) 
            {
                rv.Add(param, helper.ViewContext.RequestContext.HttpContext.Request.QueryString[param]);
            }
            foreach (var k in helper.ViewContext.RouteData.Values) 
            {
                rv.Add(k.Key, k.Value);
            }
            return helper.ActionLink(LinkText, actionName, rv);
        }
    }

i have tested this and its working. optional parameters can be acquired from query string HTH

我测试了这个和它的工作。可以从查询字符串HTH获取可选参数

#5


0  

Perhaps the best way is to write your own html helper where you traverse through the previous route value dictionary and add route values to the current action link, except the action parameter off course.

也许最好的方法是在遍历前一个路由值字典的地方编写自己的html帮助程序,并将路由值添加到当前操作链接,但当前操作参数除外。

edit: You can write the html helper like this:

编辑:您可以像这样编写html帮助器:

public static MvcHtmlString CustomLink(this HtmlHelper helper,string linktext) 
{
    //here you can use helper to get View context and then routvalue dictionary
    var routevals = helper.ViewContext.RouteData.Values;
    //here you can do whatever you want with route values
}