2

モデルバインディング時にViewModelを検証するためのエレガントなAPIのように見えるため、FluentValidationの使用を検討しています。このライブラリとビジネス (サービス) レイヤーを使用して検証を適切に集中化し、モデル状態エラーを追加するための 2 つの異なるアプローチを使用せずにビューに上げる方法についての意見を探しています。

私はまったく別の API を使用することにオープンですが、本質的にこの分岐検証戦略を解決しようとしています。

[補足: 私が試したことの 1 つは、ビジネス メソッドを FluentValidation のカスタム RsvpViewModelValidator クラスに移動し、.Must メソッドを使用することでしたが、その呼び出しをそこで非表示にするのは間違っているように思われました。範囲外であるため、再度クエリを実行する]

サンプルコード:

[HttpPost]
public ActionResult AcceptInvitation(RsvpViewModel model)
{
    //FluentValidation has happened on my RsvpViewModel already to check that 
    //RsvpCode is not null or whitespace
    if(ModelState.IsValid)
    {
        //now I want to see if that code matches a customer in my database.
        //returns null if not, Customer object if existing
        customer = _customerService.GetByRsvpCode(model.RsvpCode);
        if(customer == null)
        {
            //is there a better approach to this?  I don't like that I'm
            //splitting up the validation but struggling up to come up with a 
            //better way.
            ModelState.AddModelError("RsvpCode", 
                string.Format("No customer was found for rsvp code {0}", 
                              model.RsvpCode);

            return View(model);
        }

        return this.RedirectToAction(c => c.CustomerDetail());
    }

    //FluentValidation failed so should just display message about RsvpCode 
    //being required
    return View(model);
}

[HttpGet]
public ActionResult CustomerDetail()
{
     //do work.  implementation not important for this question.
}
4

2 に答える 2

0

流暢な検証で検証ロジック全体を使用できます。

public class RsvpViewValidator : AbstractValidator<RsvpViewModel>
{
    private readonly ICustomerService _customerService = new CustomerService();
    public RsvpViewValidator()
    {
        RuleFor(x => x.RsvpCode)
            .NotEmpty()
            .Must(BeAssociatedWithCustomer)
            .WithMessage("No customer was found for rsvp code {0}", x => x.RsvpCode)
    }

    private bool BeAssociatedWithCustomer(string rsvpCode)
    {
        var customer = _customerService.GetByRsvpCode(rsvpCode);
        return (customer == null) ? false : true;
    }
}
于 2013-04-07T03:01:56.337 に答える