【问题标题】:ASP.NET MVC: The right way to propagate query parameter through all ActionLinksASP.NET MVC:通过所有 ActionLink 传播查询参数的正确方法
【发布时间】:2012-03-15 14:18:47
【问题描述】:

在我的应用程序中,key 查询字符串参数可用于授予对某些操作/视图的访问权限。
现在,如果当前查询字符串中存在此参数,我希望所有 ActionLink 和表单自动包含此参数。

这样做的正确方法是什么?

我问的是正确的方法,因为我看到了几种建议以一种或另一种方式更改视图的解决方案(替代扩展方法/帮助程序,手动参数传递)。这不是我正在寻找的解决方案。

更新:
最终解决方案(基于 MikeSW 的回答):https://gist.github.com/1918893

【问题讨论】:

标签: asp.net-mvc asp.net-mvc-3


【解决方案1】:

您可以通过路线来做到这一点,但您需要更多的基础设施。像这样的

public class RouteWithKey:Route
{
  //stuff omitted
   public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
   {
     values.Add("key", requestContext.HttpContext.Request.QueryString["key"]);   
    var t = base.GetVirtualPath(requestContext, values);        
        return t;
    } 
}

当然,您需要从请求参数中检索密钥并处理密钥是查询中的第二个参数的情况,但是此方法会自动将密钥添加到通过普通 as.net mvc 构造的每个 utel帮手

我只是碰巧为应用程序使用了自定义路由,用于不同的目的,但我已经使用上面的代码进行了测试并添加了参数,所以至少在我的项目中似乎可以正常工作。

【讨论】:

  • 这是一个与问题实际上相关的好主意,谢谢。不幸的是,它在带有自己的参数的 ActionLink 中使用时会中断。它产生带有?key=mykey?other=myother 的url,因为ActionLink 不期望?VirtualPath 中。
  • 万岁,这确实有效!非常感谢。不过,我发现了更简单的方法:在调用base.GetVirtualPath 之前将键/值添加到values。你能用那个更新你的答案吗(因为在接受的答案中有最好的解决方案是件好事)?
【解决方案2】:

如何将键添加到路由值。

{controller}/{action}/{key}

当一个 url 包含一个 key=somevalue 的查询字符串时,该 url 看起来像

首页/索引/某个值,

现在所有的动作链接和相对 urls 也将默认包含这个。

【讨论】:

  • 键必须在查询字符串中(并且是可选的),我可以用路由值来做吗?我的意思是预期的 URL 是 Home/Index?key=somevalue
  • 不,这不能通过路由值来完成。但仍然在上述方法中,您可以将键定义为可选。如果您想在查询字符串中使用它,那么您可以定义 ActionLink 方法的扩展,这将在创建链接时附加查询字符串键值(如果可用)。
【解决方案3】:

您好,对于您描述的情况,您可以轻松使用 cookie。创建一个名称 key 和 value 与您的 key URL 参数值相同的 cookie。现在,您可以使用有效 cookie 的存在或不存在来授予或拒绝用户访问权限,而不是使用关键参数的存在或不存在。

您可以使用Response.Cookies访问cookies

如果您仍想更改所有 Form 和 ActionLink 帮助程序,那么您可以创建自己的帮助程序,在内部调用 MVC 帮助程序,并使用额外的 key 参数,并在任何地方使用自定义帮助程序。看here 编写自定义助手

【讨论】:

  • 考虑“共享”,您想在其中向未在网站上注册的某些人展示某个照片库。你可以给他们发一个链接。您也可以在他们第一次访问时设置一个 cookie,但这会使安全验证更加复杂(我们现在检查查询字符串或 cookie),如果他们真的想与其他人共享某些特定的子链接,则会产生问题。也不是每个人都启用了 cookie。
  • 这不完全是我当前的用例,但我也有理由使用当前的用例,所以我更愿意完全按照要求实现它。
  • 请注意,我提到不考虑自定义助手(问题中的替代扩展方法),需要更改视图。更新了问题,使其更清晰。
  • 不要直接访问Response.Cookies,实现一个ValueProvider即可。
  • 用自定义助手替换你的 MVC 助手,它在内部调用 MVC 助手。在调用 mvc 助手之前,您可以保留当前请求中的密钥参数。还可以考虑拥有一个简单的<input type='hidden'> 字段和一些javascript。在您的所有操作中,您都可以从发布的值中获取它并继续将其呈现回响应 html。
【解决方案4】:

为此,我为 HtmlHelper 编写了一个名为“ActionLinkBack”的扩展。这些方法将动作链接组合回同一个控制器的动作,并将现有路由值与指定的任何新路由值合并。

public static HtmlString ActionLinkBack(this System.Web.Mvc.HtmlHelper htmlHelper, string linkText, object routeValues)
{
    return ActionLinkBack(htmlHelper, linkText, new RouteValueDictionary(routeValues), new RouteValueDictionary());
}

public static HtmlString ActionLinkBack(this System.Web.Mvc.HtmlHelper htmlHelper, string linkText, object routeValues, object htmlAttributes)
{
    return ActionLinkBack(htmlHelper, linkText, new RouteValueDictionary(routeValues), new RouteValueDictionary(htmlAttributes));
}

public static HtmlString ActionLinkBack(this System.Web.Mvc.HtmlHelper htmlHelper, string linkText, RouteValueDictionary routeValues)
{
    return ActionLinkBack(htmlHelper, linkText, routeValues, new RouteValueDictionary());
}

public static HtmlString ActionLinkBack(this System.Web.Mvc.HtmlHelper htmlHelper, string linkText, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes)
{
    // Build a new dictionary of route values based on the previous set
    var newRouteValues = new RouteValueDictionary(htmlHelper.ViewContext.RouteData.Values);

    // Retain current querystring parameters
    var queryString = htmlHelper.ViewContext.HttpContext.Request.QueryString;
    if (queryString.Count > 0)
    {
        foreach (string key in queryString.Keys)
        {
            newRouteValues[key] = queryString[key];
        }
    }

    // Add and override entries from the list of new route values
    if (routeValues != null)
    {
        foreach (var routeValueItem in routeValues)
        {
            newRouteValues[routeValueItem.Key] = routeValueItem.Value;
        }
    }

    return new HtmlString(htmlHelper.ActionLink(linkText, null, newRouteValues, htmlAttributes).ToHtmlString());
}

在我可重复使用的“页面导航器”视图中,我使用扩展来组成上一个、下一个和单个页面链接:

@Html.ActionLinkBack("Next", new { page = (int)ViewData["Page"] + 1 }, new { @class = "navigationLink" })

【讨论】:

    【解决方案5】:

    拥有一个控制授权的查询字符串参数是一个坏主意恕我直言。是什么阻止我将此参数添加到不包含的网址中?

    实现授权的首选方式是使用角色 (http://msdn.microsoft.com/en-us/library/system.web.security.roleprovider.aspx)。

    【讨论】:

    • 我知道这一点,但并非所有用例和所有应用程序都需要这种级别的安全性。例如,您可以使用带有特定键的 url 授予某人访问您的 Google 文档的权限。
    • @JakubKonecki 了解基于能力的安全性和 Waterken higherlogics.blogspot.com/2012/01/…
    【解决方案6】:

    最简单的就是把“key”参数放在所有的Url.Action和Html.ActionLink中:

    @Url.Action("MyAction", "MyController", new { key = Request["key"] })
    

    如果Request["key"] 为空,则将跳过查询字符串参数。

    【讨论】:

    • 我提到这不是我在这个问题中寻找的答案。在大多数情况下,拥有专门使横切关注点更容易的框架(ActionFilter 等),我还没有准备好在这里放弃。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-21
    • 2011-01-04
    • 2015-01-04
    • 2015-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多