【问题标题】:Asp.net MVC 3 global querystring?Asp.net MVC 3 全局查询字符串?
【发布时间】:2011-09-08 21:53:59
【问题描述】:

我正在为两个业务组构建一个通用 Web 应用程序。徽标/横幅需要根据查询字符串进行更改。例如,如果 url 是 http://foo.com/test?bg=a,则显示业务组 a 的徽标,如果 url 是 http://foo.com/test?bg=b,则显示业务组 b 的徽标。如果我只有一个动作,这不是问题。但是我有很多动作。

我可以检查所有操作的查询字符串,但必须有一个很好的方法来做到这一点。我有一种感觉,我需要对路由的东西做点什么,但就是不知道怎么做。谁能告诉我怎么做?

【问题讨论】:

    标签: asp.net asp.net-mvc routing query-string


    【解决方案1】:

    您可以编写Custom Routing Handler 并使用路由将querystring 作为参数提取,然后传递到RouteData 中,可以在任何地方访问它。

    public class RouteWithQueryStringValueHandler : MvcRouteHandler
    {
        private readonly string key;
    
        public RouteWithQueryStringValueHandler(string key)
            : base()
        {
            this.key = key;
        }
    
        protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            var request = requestContext.HttpContext.Request;
            var qsValue = requestContext.HttpContext.Request[key];
            var router = base.GetHttpHandler(requestContext);
            requestContext.RouteData.DataTokens[key] = qsValue;
            return router;
        }
    }
    

    如下注册:

    routes.Add(new Route("{controller}/{action}/{id}", 
                     new RouteValueDictionary(
                             new { controller = "Home", 
                                   action = "Index",
                                   id = UrlParameter.Optional 
                             }),
                     new RouteWithQueryStringValueHandler("bg")));
    

    获取路由数据的标志:

    var logo = RouteData.DataTokens["bg"];
    

    【讨论】:

      【解决方案2】:

      您可以编写一个基于查询字符串参数的自定义帮助器方法,它将给定的类名附加到某个 div。那么当然你会在你的 CSS 文件中使用不同的类定义来应用背景图像。

      例如:

      public static class HtmlExtensions
      {
          public static string BannerClass(this HtmlHelper html)
          {
              var bg = html.ViewContext.Controller.ValueProvider.GetValue("bg");
              if (bg == null || string.IsNullOrEmpty(bg.AttemptedValue))
              {
                  // no bg parameter => return a default class
                  return "default_banner";
              }
      
              if (string.Equals("a", bg.AttemptedValue))
              {
                  return "banner_a";
              }
              else if (string.Equals("b", bg.AttemptedValue))
              {
                  return "banner_b";
              }
      
              // unknown value for the bg parameter => return a default class
              return "default_banner";
          }
      }
      

      然后在您的_Layout 中,您可以将此类应用于某些占位符,例如 div 甚至是正文:

      <div class="@Html.BannerClass()">OK</div>
      

      这样,它将始终应用于您应用程序中的所有视图。

      现在剩下的就是为不同的横幅定义 CSS 规则:

      .default_banner {
          background-image: url('../images/default_banner.png')
      }
      
      .banner_a {
          background-image: url('../images/banner_a.png')
      }
      
      .banner_b {
          background-image: url('../images/banner_b.png')
      }
      

      【讨论】:

      • 谢谢。但这似乎只适用于当前网址。我需要更改所有链接以包含相同的查询字符串。有什么办法可以持久化查询字符串?
      • 没关系,我意识到我可以将它保存在会话中并检查会话是否为空。
      【解决方案3】:

      如果您使用的是 Razor(我相信这确实违反了职责分离准则),请更改 _ViewStart.cshtml 来执行此操作。

      @{
          if (/* Context.QueryString Params, not at my development box*/)
          {
              Layout = "~/Views/Shared/Layout-Group1.cshtml";
          }
          else
          {
              Layout = "~/Views/Shared/Layout-Group2.cshtml";
          }
      }
      

      我更喜欢这条路线,因为它使任何未来的请求(布局 + css + javascript)变得相当容易,因为它们都可以在布局中更新。

      【讨论】:

        【解决方案4】:

        在您的母版页中放置一些代码,以根据查询字符串决定显示哪个横幅。理想情况下,代码不会完全内联,即它应该在一个帮助类中。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-03-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多