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

Posted

技术标签:

【中文标题】MVC ActionLink 从当前 url 添加所有(可选)参数【英文标题】:MVC ActionLink add all (optional) parameters from current url 【发布时间】:2010-09-23 15:29:15 【问题描述】:

非常有名的ActionLink

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

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

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

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

现在,我已经厌倦了手动操作,1 可以,但 6 不行。这应该会容易得多。

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

我一直在寻找Request.QueryString。它必须与那个有关。我正在考虑在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:

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

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

编辑 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") %>

【问题讨论】:

【参考方案1】:

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

视图中的调用:

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

但是对于重载,它可以是普通 ActionLink 采用的任何东西。

助手:

helper 从 url 中获取所有不在路由中的参数。 例如:这个网址:

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

因此,它将获取 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;

        
    


在视图中使用重载:

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

在 URL 中,我的参数 postalCode 具有一定的价值。我的代码将所有这些都包含在 URL 中,通过将其设置为 string.Empty,我从列表中删除了此参数。

欢迎对优化提出意见或想法。

【讨论】:

当您需要获取当前查询字符串时,对于下一页/上一页功能非常有用。为这个 +1 干杯 谢谢。我用它来排序链接。 这对我来说效果很好(在我对其进行了一些修改以重命名一些可怕的变量名之后)。 +1! 真是救命稻草,现在我知道如何创建自己的 Html 扩展方法了。竖起两个大拇指!【参考方案2】:

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

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

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

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;
        
    

要在您的视图中使用扩展方法,请参阅以下问题和答案:How do I use an extension method in an ASP.NET MVC View?

这比公认的答案更简单,涉及的代码也少得多。

【讨论】:

您是否阅读了接受的代码?它与您描述的相同,相同的代码等等。合并 url 路由值和个人添加的路由值,等等。我必须说它的效果非常好。 感谢您的评论,@Stefanvds。我确实阅读了接受的答案。它没有任何问题,但它增加了问题中没有的行为。此外,问题还问“我最好把这段代码放在哪里?”这个答案提供了使用扩展方法的选项。【参考方案3】:

这是一个 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;
        
    

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

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

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

This article对我的解决方案有更详细的解释。

【讨论】:

【参考方案4】:
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);
        
    

我已经对此及其工作进行了测试。可选参数可以从查询字符串中获取 高温

【讨论】:

【参考方案5】:

也许最好的方法是编写自己的 html 帮助程序,在其中遍历之前的路由值字典并将路由值添加到当前操作链接,但操作参数偏离路线。

编辑: 您可以像这样编写 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

【讨论】:

RouteValueDictionary 正是我所需要的。但是你会怎么做那个助手呢? @Stefanvds:你可以用&lt;%= Html.CustomLink("Foo") %&gt; 来称呼它。附: @Muhammad - 所有的 txt spk 是怎么回事?你知道,我们不限于 160 个字符! 我需要更多关于这件事的信息,我不明白。有些文章可能会有所帮助。错误:“System.Web.Mvc.HtmlHelper”不包含“ActionLinkwParams”的定义,并且没有扩展方法“ActionLinkwParams”接受类型为“System.Web.Mvc.HtmlHelper' 可以找到(您是否缺少 using 指令或程序集引用? 啊抱歉请用字符串代替 MvcHtmlString 另外你需要在你的 veiw 中添加命名空间以使用自定义 html 帮助器请***.com/questions/1105276/… 了解更多详细信息

以上是关于MVC ActionLink 从当前 url 添加所有(可选)参数的主要内容,如果未能解决你的问题,请参考以下文章

每日踩坑 2018-11-26 MVC Razor ActionLink 生成的URL中多生成了一个参数 ?length=n

将 Css 类添加到 ASP.NET MVC 的 ActionLink

为啥 T4MVC 尝试从 Html.ActionLink 运行控制器动作?

在 ASP.NET MVC Html.ActionLink 中包含锚标记

如何在 C# 代码中使用 MVC 3 @Html.ActionLink

ASP.NET MVC - 如何获取 URL 而不是操作链接?