【问题标题】:MVC routing with optional first parameter带有可选第一个参数的 MVC 路由
【发布时间】:2014-12-07 08:42:37
【问题描述】:

我正在尝试获取如下路线:

{lang:optional}/{controller}/{action}/{id:optional}

使用本文中的“控制器约束”思想:(MVC Routing Constraint on Controller Names),无论是否提供 {lang} 值,上述路由都非常有效。

但是我有一个问题来匹配这条路线:

routeName: testRoute
url: {lang:optional}/list/{something:optional}
{controller = "product", action = "index"}

对于上述路由,必须提供{lang}值,否则不起作用。

我有两个解决方法。

第一种方式是为上面设置两条路由:

非常标准的:

routeName: testRoute
url: /list/{something}
{controller = "product", action = "index"}

还有一个非常标准的:

routeName: testRouteLang
url: {lang:not_optional}/list/{something:optional}
{controller = "product", action = "index", lang="de"}

我想知道是否有办法将两条标准路线组合成一条路线。

第二种解决方法是使用子域名,例如

http://example.com/list (default to English)
http://de.example.com/list (de)

但出于 SEO 的原因,我真的不喜欢子域的想法(也许我在这一点上错了)。

我的目标是删除 URL 中的默认“en-us”。我喜欢这个

http://www.example.com/list/something (default as English)

我不想在 url 中强制使用“en-us”

http://www.example.com/en-us/list/something

只有在当前文化不是英语的情况下,“lang”才应该出现在 URL 中:

http://www.example.com/de
http://www.example.com/fr/list/something

谢谢。

【问题讨论】:

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


    【解决方案1】:

    最后,我找到了一个非常简单且 DRY 的解决方案。核心是使用HttpContext.Current.RewritePath来注入默认的“en”,而这个“en”不会显示在URL中。

    protected void Application_BeginRequest() 
    {
      var rawUrl = HttpContext.Current.Request.RawUrl;
      var segments = HttpContext.Current.Request.Url.Segments;
      var segment1 = segments.Count() >= 2 ? segments[1] : string.Empty;
      if (IsSomethingThatIWantToHandle("are,you,js,script,css,jpg,png,and,so,on?")
         && !LittleHelper.DoIHaveValidLangAlready(segment1))
      {
        HttpContext.Current.RewritePath("/en" + rawUrl);
      }
    }
    

    生成 URL 时,如果 lang 为 null/empty,则 URL 将有一个双 //。我只需要一个小帮手来删除多余的“/”。

    定义路由时,一个技巧是必须将区域名称添加到DataTokens,否则如果项目中存在区域,则无法正确定位视图。

    routes.MapRoute(
       "good name",
       "{lang}/some-cool-stuff/{id}/{slug}",
       defaults: new { area = "bigarea", controller = "bigcontroller", action = "tinyaction", 
       lang = UrlParameter.Optional, id = UrlParameter.Optional, slug = UrlParameter.Optional }
       , constraints: new { lang = new CultureConstraint() }
    ).DataTokens.Add("area", "bigarea");
    

    CultureConstraint 非常简单——只需验证它是否是有效的文化名称。命名空间约束不是必需的。但是,如果路由表又大又复杂,那么控制器约束,甚至动作约束都是非常必要的,否则重复的路由将是一个问题。

    我现在项目中的默认路由是: 网址:“{lang}/{area}/{controller}/{action}/{id}/{slug}”,

    它可以随心所欲地完美运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-30
      • 1970-01-01
      • 1970-01-01
      • 2013-05-24
      • 1970-01-01
      • 2013-05-07
      • 2011-04-08
      相关资源
      最近更新 更多