I'm exploring using FluentValidation as it seems to be an elegant API for validation of my ViewModels upon model binding. I'm looking for opinions on how to properly centralize validation using this library as well as from my business (service) layer and raise it up to the view without having 2 different approaches to adding modelstate errors.
I'm open to using an entirely different API but essentially looking to solve this branching validation strategy.
[Side Note: One thing I tried was to move my business method into my FluentValidation's custom RsvpViewModelValidator class and using the .Must method but it seemed wrong to hide that call in there because if I needed to actually use my Customer object they I would have to re-query it again since its out of scope]
Sample Code:
[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.
}
invitationService.Accept()(or whatever kind of service would describe the process) method that either passed/failed, and that's where the logic would be housed, but without the service, the next best place is within the controller. personally I'd say you'd done it the best was possible given the circumstance._customerService). The code was based on an example problem but it i'm not confined to it as I just wrote it up for this question. So, using your example ofinvitationService.Accept(), would this be void and throw exceptions or do you return something like anIList<Error>out of it to populate ModelState or something else. Just picking your brain a little more. Sorry, I'm not trying to drag this out.outparameters, and some throw exceptions. (this is across the various one-off projects I've done). personally I think having aProjectNameExceptionbase that I can have validation exceptions spawn from is the better way (usually in the infra/core lib).