views:

168

answers:

2

The reason seems simple enough: model binding (and therefore validation) happens before the earliest ActionFilter method (OnActionExecuting) is executed, therefore changing UICulture has no affect on validation messages.

Is there an earlier integration point (besides an IHttpModule) that I could use here?

I'd rather an Attribute-based approach, since the functionality doesn't apply to all controllers/actions so IHttpModules doesn't sound like a good idea (exclude-filter lists and such)

+1  A: 

Well, the easiest "attribute-based" solution I can think of is some kind of a hack...

Authorization filters run before the model binder does its work. So if you write a bogus AuthorizeAttribute, you can set the culture there.

public class SetCultureAttribute : AuthorizeAttribute {
    protected override bool AuthorizeCore(HttpContextBase httpContext) {
        //set the culture here
        return true; //so the action will get invoked
    }
}
//and your action
[SetCulture]
public ActionResult Foo(SomeModel m) {
    return View();
}
çağdaş
Great idea, I'd forgotten about `AuthorizeAttribute`. I'll leave the question open in case there's a more elegant solution, but your answer is looking good :)
Richard Szalay
A: 

Just thought of another solution to tackle this problem.
I believe this is a lot more elegant than the other solution and it's attribute-based (though this depends on how you want to attach this binder to your model).

You can create your own model binder and derive it from DataAnnotationsModelBinder. Then set the culture before telling the base class to bind the model.

public class CustomModelBinder : DataAnnotationsModelBinder {
    public override object BindModel(ControllerContext controllerContext,
        ModelBindingContext bindingContext) {

        //set the culture
        return base.BindModel(controllerContext, bindingContext);
    }
}
//and the action
public ActionResult Foo([ModelBinder(typeof(CustomModelBinder))]SomeModel m) {
    return View();
}

//Or if you don't want that attribute on your model in your actions
//you can attach this binder to your model on Global.asax
protected void Application_Start() {
    ModelBinders.Binders.Add(typeof(SomeModel), new CustomModelBinder());
    RegisterRoutes(RouteTable.Routes);
}
çağdaş