开发者

MVC validation in model requires database repository

I'm writing an MVC app using the repository pattern.

It is a financial system which has invoices in them. I have validation in the Invoice model:

#region IValidatableObject Members

        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if ((TotalExcludingTax + (TotalExcludingTax * .15m)) != TotalIncludingTax) {
                yield return new ValidationR开发者_如何学Cesult("The total (exc. Tax) + Tax does not equal the total (inc. Tax).");
            }
        }

        #endregion

The problem is the tax rate .15 is variable. At the moment it is hard coded in here which isn't much good. The only way I can think of doing this is:

#region IValidatableObject Members

        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            var taxRepository = new Repository<tax>();

            if ((TotalExcludingGst + (TotalExcludingGst * taxRepository.GetCurrentTaxRate())) != TotalIncludingGst) {
                yield return new ValidationResult("The total (exc. Gst) + Gst does not equal the total (inc. Gst).");
            }
        }

        #endregion

Using this method I now am instantiating a taxRepository instance within the invoice model.

Is this bad practice?

Is there a better way of doing this?


Yeah, your current approach isn't great and this is exactly the scenario that FluentValidator was built for.

As an example, in one of our objects we have some PostCode validation that requires complex rules to determine if a postcode is valid so we do something like this:

public class AddressValidator : AbstractValidator<Address>
{
    private readonly IPostCodeRepository _postcodeRepo;
    
    public AddressValidator(IPostCodeRepository postcodeRepo)
    {
        _postcodeRepo = postcodeRepo;
        
        RuleFor(a => a.Postcode)
                .NotEmpty()
                .WithMessage("Postcode is required")
                .Must(BeValidPostcodeSuburbStateCombo)
                .WithMessage("Postcode is not valid for this state");
    }
    
    private bool BeValidPostcodeSuburbStateCombo(Address model, string property)
    {
        return _postcodeRepo.ValidatePostcode(model.Postcode, model.Suburb, model.State);
    }
}

The advantage of this approach is that it keeps your models nice and clean and still allows you to validate complex logic.

If switching to FluentValidator isn't an option for you, I would suggest putting an additional property on your model called TaxRate and setting it before the Validate method is called.

It's not ideal, but it means you're not taking a dependency in the repository within your model.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜