Question

I need a solution for ASP.NET MVC3 model validation logic. I have a custom localization solution and i'm passing all strings through a method for translating, something like that:

    @Localizer.Translate("Hello world!") 

Note: I'm not sure but i think this approach comes from QT localizastion logic. WordPress is using smillar technique also.

When i try to apply this solution for model validation attributes like that:

    [Required(ErrorMessage = Localizer.Translate( "Please enter detail text!"))]
    [DisplayName(Localizer.Translate( "Detail"))]
    public string Details { get; set; }

compiler gives me this error:

Error 1 An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type...

So, i tried to modify error messages and DisplayName attributes on the fly, but i couldn't.

Is there a any way to do this? If there is, it could be life saver for me :)

Was it helpful?

Solution 3

I have a workaround creating my custom @Html.LabelFor() and @html.DescriptionFor() helper.

my helper:

namespace MyCMS.Helpers
{
public static class Html
{
    public static MvcHtmlString DescriptionFor<TModel, TValue>(
        this HtmlHelper<TModel> self, 
        Expression<Func<TModel, TValue>> expression)
    {
        var metadata = ModelMetadata.FromLambdaExpression(expression, self.ViewData);
        var description = Localizer.Translate(metadata.Description);

        return MvcHtmlString.Create(string.Format(@"<span class=""help-block"">{0}</span>", description));
    }

    public static MvcHtmlString LabelFor<TModel, TValue>(
        this HtmlHelper<TModel> self, 
        Expression<Func<TModel, TValue>> expression, 
        bool showToolTip
    )
    {
        var metadata = ModelMetadata.FromLambdaExpression(expression, self.ViewData);
        var name = Localizer.Translate(metadata.DisplayName);

        return MvcHtmlString.Create(string.Format(@"<label for=""{0}"">{1}</label>", metadata.PropertyName, name));
    }
}
}

my view is:

@using MyCMS.Localization; @using MyCMS.Helpers;

    <div class="clearfix ">
        @Html.LabelFor(model => model.RecordDetails.TitleAlternative)
        <div class="input">
            @Html.TextBoxFor(model => model.RecordDetails.TitleAlternative, new { @class = "xxlarge" })
            @Html.ValidationMessageFor(model => model.RecordDetails.TitleAlternative)
            @Html.DescriptionFor(model => model.RecordDetails.TitleAlternative)
        </div>
    </div>

and i can use my localization approach :)

Thanks everyone again...

OTHER TIPS

You can use resource files to do localization.

Add a Resource File (you can use the Add New Item wizard through Visual Studio - lets call it MyResourcesType.resx) to your project. Then add your validation messages like this:

[Required(
    ErrorMessageResourceType = typeof(MyResourcesType),
    ErrorMessageResourceName = "MyMessageIdOnTheResourcesFile")]

From now on changing the language is just a matter adding new resources files. Check this question's first answer.

By the way don't use DisplayNameAttribute but DisplayAttribute from System.ComponentModel.DataAnnotations namespace. It's the attribute used by MVC and you can do localization on it too:

[Display(
    ResourceType = typeof(MyResourcesType),
    Name = "MyPropertyIdOnResourcesFile_Name",
    ShortName = "MyPropertyIdOnResourcesFile_ShortName",
    Description = "MyPropertyIdOnResourcesFile_Description")]

The way attributes work is that they are statically compiled into the code. Thus, you cannot have any dynamic functionality like that when using attributes.

Jota's answer is the recommended way to do things, however if you're determined to use your own solution you could create your own attribute, and in that attribute you could add code that looks up the messages.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top