What's the best way to localize non Data Annotation Errors with ASP.NET MVC 3?

落花浮王杯 提交于 2019-12-07 06:09:08

问题


With Data Annotations it's now easy to localize error messages using Resource.resx files like this for example:

public class Student
{
    . . .

    [Required(ErrorMessageResourceName ="Required",
     ErrorMessageResourceType = typeof(StudentResources))]
    [StringLength(16)] 
    [Display(Name = "FirstName", ResourceType = typeof(StudentResources))]
    public string FirstName { get; set; }

    . . .
}

Now, let's say I want to check if a Student has already made a Payment for a given month and year:

public bool CheckIfAlreadyPaid(Payment payment)
{
    return repository.GetPayments().Any(p => p.StudentId == payment.StudentId &&
                                        p.Month == payment.Month &&
                                        p.Year == payment.Year);
}

If he has already made the Payment, I'm doing the following in my Services layer:

if (CheckIfAlreadyPaid(payment))
{
    modelState.AddModelError("AlreadyPaid",
    Resources.Views.Payment.PaymentCreateResources.AlreadyPaid);
}

It works, but I don't fell confident about referencing the Resource file inside the Services layer.

Is there a standard or better way of localizing error messages that are not tied to model properties (Data Annotation) - errors that come from business logic rules? Should I still add these errors to the ModelStateDictionary?


回答1:


I agree, I don't think that should be in the service layer. It looks like it could either be put into a custom data validation attribute, or handled with some other approach at that level (using Fluent Validation might be a good option). Either way, I think as long as the validation stays in the MVC app itself, you can be comfortable using resource files to store the messages.




回答2:


I did it in a different way. The Service layer is used to check if the Payment was already made. In my Controller I add a validation error message to the ModelState object passing to it a localized string resource. Now I feel more comfortable with this approach.

Here's the code:

/// <summary>
/// Performs validation of business logic...
/// </summary>
/// <param name="payment"></param>
/// <returns></returns>
private bool ValidatePayment(Payment payment)
{
    if (paymentService.IsPaymentMade(payment))
    {
        ModelState.AddModelError("AlreadyPaid", Localization.AlreadyPaid);
    }

    return ModelState.IsValid;
}

EDIT:

To complement my answer, I just found today that ValidationSummary @Html.ValidationSummary(true) does exactly what I want:

Html.ValidationSummary returns an unordered list (ul element) of validation messages that are in the ModelStateDictionary object and optionally displays only model model-level errors.

I'm passing true and it will only display model-level errors (non data annotation errors) in the summary just at the top of the page. This is great but only if it would work... :)

I was facing a problem where my custom error messages not tied to model properties weren't appearing when I set ValidationSummary(true). I then searched using Google and found this post. I tried his solution but it didn't work. I then searched a little bit more and found this link in Google Books (Pro ASP.NET MVC 2 Framework by Steven Sanderson).

I tried what is described there passing an empty string as key (string.Empty) and it did the job.

if(paymentService.IsPaymentMade(payment))
{
    ModelState.AddModelError(string.Empty, Localization.PaymentAlreadyCreated);
}


来源:https://stackoverflow.com/questions/5697487/whats-the-best-way-to-localize-non-data-annotation-errors-with-asp-net-mvc-3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!