Whilst this may concern to other topics as well, I'm just heading the following trouble with validation:
I use validation attributes from System.ComponentModel.DataAnnotations. The model looks like
public class NewUserModel
{
[Required]
public string Username { get; set; }
}
So, nothing special. According to that, a pretty much default controller action
public ActionResult New()
{
return View(new NewUserModel());
}
and the view
@using (Html.BeginForm())
{
@Html.LabelFor(m => m.Username)
@Html.EditorFor(m => m.Username)
@Html.ValidationMessageFor(m => m.Username)
<button type="submit">save</button>
}
Based on user preferences, culture is set via following filter
public class CultureFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext filterContext)
{
// simplified for this example
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("de");
}
}
which is registered in global.asax with
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new CultureFilter());
}
Default language is english, so the web.config contains
<globalization culture="en-US" uiCulture="en"/>
With that done, client-side validation works perfectly. Data attributes for unobtrusive jQuery validation are localized as you can see in the resulting HTML:
<input data-val="true"
data-val-required="Das Feld Username ist erforderlich."
id="Username" name="Username" type="text" value="" />
The trouble is, that forcing server-side validation by disabling JavaScript renders following unlocalized validation message, while the data attribute is still localized:
<input data-val="true"
data-val-required="Das Feld Username ist erforderlich."
id="Username" name="Username" type="text" value="" />
<span class="field-validation-error" data-valmsg-for="Username"
data-valmsg-replace="true">The Username field is required.</span>
Looks pretty funny, doesn't it? ;-)
First, I checked if the server-side culture is set by web.config. Yes, it is. If I change the <globalization/> attributes to german cultures (or just remove the node as by system language is german), the server-side validation message is german too.
This let me believe there might be a difference in times when server-side and client-side take their messages from resources. And maybe the server-side does it prior to executing the action, which means CultureFilter.OnActionExecuting() is called after that, which of course is too late in this case.
So I tried to set the culture on begin request (global.asax):
protected void Application_BeginRequest()
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo("de");
}
Well, that did the trick. But I really think this is an ugly solution. So...
Is it true, that server-side validation takes the messages from resource before a filter could set the culture? If not, what am I doing wrong? If yes, is there another, cleaner option for setting the culture than the global.asax "hack"?
Thank you in advance.
The problem is that the DefaultModelBinder creates the model before yourFilter is executed, and its during the creation of the model that validation errors are added (and at this point the culture is en-US as defined in your web.config file.
One option may be to create a custom ModelBinder (and register it as the DefaultModelBinder) and override the OnPropertyValidating() method to set the culture.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With