I have a service which has a method that's called when a certain controller method is triggered.
My service returns a custom result object PlacementResult in which I want to communicate errors that may have happened (validation) back to the controller method.
Should PlacementResult have a ModelState or a ModelStateDictionary to communicate errors back to the controller (and finally view)? How would I string this together?
Finally, how do I get the ModelState/ModelStateDictionary (whichever you tell me I should choose) back into the view (highlighting the appropriate text box, show the error message etc.)?
Thank you !
This is a good link that shows how a service can perform validation and communicate the result back to the controller:
http://www.asp.net/mvc/tutorials/validating-with-a-service-layer-cs (fixed link)
No, you do not want to add a ModelStateDictionary to your result type. There is already a ModelStateDictionary on the Controller (in the ModelState property). It is not appropriate for results to set the controller's model state. That should be done during binding or within the controller action itself. Use a custom model binder if you need to.
Your choose one can see the model state errors by examining the controller's ViewData.ModelState property.
Your PlacementResult should return a dictionary object or a List which you should merge with the model state at the beginning of each action.
If you step through you will notice the controllers model state dictionary contains all your input fields, their values and the errors associated with them. You want to merge the PlacementResult errors into the model state dictionary at the appropriate keys. This is how the view engine knows which fields to flag as invalid.
ModelState.Merge(PlacementResult);
if(ModelState.IsValid)
{
...
}
I don't know what your PlacementResult looks like, see if you can possibly utilize this in your view:
ModelState.AddModelError(ErroredProperty, ErrorMessage);
Make sure you return the object that failed back to the view
return View(myObjectInstance);
Based on SoC I think you have to return errors from your services and merge them in your ModelState if needed.
But our objective is maintain decoupling and also to use ModelState.Merge() method. it isn't?
There is an concrete implementation that could help
You can pass the Controller to your method, since the Controller class contains the ModelState property. Once in your method you can do the following:
private PlacementResult BuildResult(Controller controller)
{
controller.ModelState.AddModelError(propertyName, errorMessage);
}
In your action...
BuildResult(this);
if(ModelState.IsValid) {...