mccalltd / AttributeRouting

Define your routes using attributes on actions in ASP.NET MVC and Web API.
http://mccalltd.github.io/AttributeRouting/
MIT License
416 stars 89 forks source link

ConstrainTranslatedRoutesByCurrentUICulture is not working #274

Open mdmoura opened 11 years ago

mdmoura commented 11 years ago

Following the AttributeRouting.NET localization example I have:

routes.MapAttributeRoutes(config => {
  config.ConstrainTranslatedRoutesByCurrentUICulture = true;
  config.CurrentUICultureResolver = (httpContext, routeData) => {
    return (string)routeData.Values["culture"] ?? Thread.CurrentThread.CurrentUICulture.Name;
  };
  config.UseRouteHandler(() => new CultureRouteHandler());
});

The logic to define the culture is in the CultureRouteHandler:

public class CultureRouteHandler : MvcRouteHandler {
  protected override IHttpHandler GetHttpHandler(RequestContext context) {
    var c = context.RouteData.Values["culture"];
    // Remaining code
  } 
}

And the HomeController is the following:

[RoutePrefix("{culture?}")]
public partial class HomeController : WebController {
  [GET("")]
  public virtual ActionResult Index() { }
}

I added a breakpoint inside the GetHttpHandler method in the CultureRouteHandler.

When I start the site this breakpoint is not fired so the default culture becomes "en-US".

This way on the start of the site my logic to choose the culture does not run.

In the next requests, e.g. navigating through pages, the GettHttpHandler fires.

Is this a bug or is expected to work like this? How can I solve this?

Thank You

mdmoura commented 11 years ago

I think there is an error on AR documentation or maybe in AR itself.

When a parameter is optional the key is being added to the route dictionary. This means its value is empty, e.g., equal to UrlParameter.Optional ...

AR documentation has the following (the casting will not work when the UrlParameter is Optional): return (string)routeData.Values["culture"] ?? Thread.CurrentThread.CurrentUICulture.Name;

The solution to fire the CultureRouteHandler for the nullable culture in the home page is:

config.CurrentUICultureResolver = (context, data) => {
      var value = data.Values["culture"];
      if (value == null) {
        return Thread.CurrentThread.CurrentUICulture.Name;
      } else if (value == UrlParameter.Optional) {
        return "";
      } else 
        return (String)value;
}

Now the CultureHandler is fired even on the site start ... And in the Culture Handler I have:

protected override IHttpHandler GetHttpHandler(RequestContext context) {
  String culture = context.RouteData.Values[_culture] as String;
  if (culture == null) {
     // remaining code
}

This is now working ... But am I missing something or is there a bug in AR?

Thank You, Miguel

mdmoura commented 11 years ago

The solution I presented works fine with only one problem:

config.x.ConstrainTranslatedRoutesByCurrentUICulture = true;

This has no effect ... I needed to add:

config.AddDefaultRouteConstraint(@"^culture$", new RegexRouteConstraint(@"(?i:^(pt|en)$)"));

Could someone look at this thread so we arrive to a working localization solution?