带有可选第一个参数的MVC路由

时间:2014-10-12 19:07:36

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

我想尝试一条路线:

{郎:可选} / {控制器} / {行动} / {ID:可选}

使用"控制器约束"本文的想法:(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原因的子域名想法(也许我在这一点上错了)。

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

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

我不想强迫" en-us"在网址

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

" lang"如果当前文化不是英语,则只应在Url中显示:

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

感谢。

1 个答案:

答案 0 :(得分:1)

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

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将为double //。我只需要一个小帮手来移除额外的" /"。

定义路线时,一个技巧是必须将区域名称添加到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}",

它可以随心所欲地运作。