Why do DataAnnotation attributes have difficulty accessing resources created by PublicResxFileCodeGenerator?
I find that the following attribute:
[Compare("NewPassword", ErrorMessageResourceName = "RegisterModel_ConfirmPasswordError", ErrorMessageResourceType = typeof(Resources.Global))]
Will fail to find the resource if it has been created with PublicResxFileCodeGenerator. However an identical resource created with GlobalResourceProxyGenerator will work correctly. Both resource files are set to Content and live in App_GlobalResources. I've tried putting the default language in App_LocalResources too but it seems to make no difference. My test being that my secondary language (GlobalResourceProxyGenerator) works but my primary language (PublicResxFileCodeGenerator) throws an exception (it fails to find the resource file). If I switch both to GlobalResourceProxyGenerator then everything is fine (but obviously there is no public access).
Does anyone know why this is? I'd like to move the resources into another assembly in the future.
That's because you placed your resource file inside the App_GlobalResources
folder which is a special folder in ASP.NET. This should work if you put your resources file somewhere else. This could also be a completely separate project from your ASP.NET MVC application.
Here are the steps you could make this work:
~/Messages.resx
file containing the RegisterModel_ConfirmPasswordError
resource stringSet the custom tool to PublicResXFileCodeGenerator
for this resource file:
Add a model:
public class MyViewModel
{
[Compare("NewPassword",
ErrorMessageResourceName = "RegisterModel_ConfirmPasswordError",
ErrorMessageResourceType = typeof(MvcApplication1.Messages))]
public string Password { get; set; }
public string NewPassword { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new MyViewModel());
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
return View(model);
}
}
View:
@model MyViewModel
@using (Html.BeginForm())
{
<div>
@Html.LabelFor(x => x.Password)
@Html.EditorFor(x => x.Password)
@Html.ValidationMessageFor(x => x.Password)
</div>
<div>
@Html.LabelFor(x => x.NewPassword)
@Html.EditorFor(x => x.NewPassword)
@Html.ValidationMessageFor(x => x.NewPassword)
</div>
<button type="submit">OK</button>
}
Then you could start localizing by providing respective translations:
UPDATE:
I was asked in the comments section what's so special about the App_GlobalResources
folder and why it doesn't work with it. Well, actually you could make it work. All you need to do is set the Build Action
to Embedded Resource
. By default when you add a file to the App_GlobalResources
folder, Visual Studio set it to Content
meaning that this resource will not be incorporated into the runtime assembly and ASP.NET MVC cannot find it:
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