Reputation: 435
Does anyone know when model binding takes place in the request lifecycle? The reason I ask is that I'm running into some localization issues.
Does Model Binding happen before OnActionExecuting is executed?
Currently I set the current culture in a global action filters OnActionExecuting method but this isn't being respected when performing model binding. The request is a POST.
Thanks in advance.
Upvotes: 7
Views: 2558
Reputation: 11384
I also run into the same problem. When the model binder has invalid data it runs before the ActionFilter(s).
I didn't like the proposed solutions because messing with the routing was not my preferred solution. Listen for Application_AcquireRequestState is problematic because this event fire for each and every request, not just for requests that will be routed into MVC controllers.
I've end up writing a custom implementation of IControllerFactory
that use DefaultControllerFactory
internally and execute the localization code inside CreateController
method.
This is not ideal either, hope it helps.
public class PluggableControllerFactory : IControllerFactory {
private readonly IControllerFactory innerControllerFactory;
public PluggableControllerFactory() {
innerControllerFactory = new DefaultControllerFactory();
}
public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName) {
// Run your culture localization here
return innerControllerFactory.CreateController(requestContext, controllerName);
}
public System.Web.SessionState.SessionStateBehavior GetControllerSessionBehavior(System.Web.Routing.RequestContext requestContext, string controllerName) {
return innerControllerFactory.GetControllerSessionBehavior(requestContext, controllerName);
}
public void ReleaseController(IController controller) {
innerControllerFactory.ReleaseController(controller);
}
}
}
Upvotes: 0
Reputation: 56466
I found that in a MVC application the best way is to use a custom routehandler and set the culture in that handler. This works flawlessly with ModelBinders
and localized resources in data annotations.
public class MultiCultureMvcRouteHandler : MvcRouteHandler
{
protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
{
// get culture from route data
var culture = requestContext.RouteData.Values["culture"].ToString();
var ci = new CultureInfo(culture);
Thread.CurrentThread.CurrentUICulture = ci;
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);
return base.GetHttpHandler(requestContext);
}
}
There is an excellent blog article by Alex Adamyan describing this technique.
See also this question & answers on SO.
Upvotes: 2
Reputation: 32758
I would suggest you to set the culture at a very earlier point not in action filter. In my current project I've set the culture in the Application_AcquireRequestState
event in Global.asax.cs. You can try that.
protected void Application_AcquireRequestState(Object sender, EventArgs e)
{
// set the culture
}
Upvotes: 3
Reputation: 20674
BindModel is hit first. Can your localization change per request? If it does you could override the default model binder and if required set your locale there. Follow link below on creating custom model binder
ASP.NET MVC Model Binder for Generic Type
(to prove for yourself just put two breakpoints in and you'll see the order)
I'm thinking there might be a better place to set the localization but would need more specific information, and that might be a different question.
Upvotes: 0