2

I am trying to get a route like:

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

With "controller constraints" idea from this article: (MVC Routing Constraint on Controller Names), the above route works very well, when {lang} value is presented or not.

However I have a problem to match this route:

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

for the above route, the {lang} value must be presented, otherwise it does not work.

I have two workarounds to work it out.

The first way is to set two routes for the above:

The very standard one:

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

and another very standard one:

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

I am wondering if there is a way to combine the two standard routes into one single route.

The second workaround is to use subdomain name, such as

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

But I really do not like the subdomain idea for the SEO reasons (maybe I am wrong on this point).

My goal is to remove the default "en-us" in the URL. I like this

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

I do not want to force "en-us" in the url

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

The "lang" should only be presented in the Url if the current culture is not English:

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

Thanks.

Community
  • 1
  • 1
user985287
  • 133
  • 1
  • 6

1 Answers1

1

Finally I found an very easy and DRY solution. The core thing is to use the HttpContext.Current.RewritePath to inject the default "en", while this "en" will not be shown in the 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);
  }
}

When generate URL, if lang is null/empty, the URL will be have a double //. I just need a little helper to remove the extra "/".

When define a route, a trick is that the area name must be added to the DataTokens, otherwise the view cannot be correctly located, if areas are presented in the project.

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");

The CultureConstraint is very straightforward -- just verify whether it is a valid culture name. The namespace constraints is not necessary. However if the route table is big and complicated then the controller constraints, or even action constraints is very necessary otherwise duplicated routes will be an issue.

My default route in my project now is: url: "{lang}/{area}/{controller}/{action}/{id}/{slug}",

and it works beautifully as I want.

user985287
  • 133
  • 1
  • 6