views:

49

answers:

3

When the Service layer is only executing a task (checking if Id exists, sending an email, etc.), what is the best way for it to let the controller know if there were any errors?

Two solutions I can think of:

  1. Always passing in an extra "broken rules" parameter by reference to the methods in the Service layer which it would update if there were any error.

  2. Have the Service raise an exception and having the controller do a try/catch.

Are either one of these two approaches recommended? If not, what approach could I take to have the Service layer let the controller know what something went wrong (such as invalid parameter)?

+2  A: 

I created interface:

public interface IModelStateWrapper
{
    void AddModelError(string name, string error);
}

Then I created implementation for every controller:

public class ControllerModelStateWrapper : IModelStateWrapper
{
    private ModelStateDictionary _dictionary;

    public ControllerModelStateWrapper(ModelStateDictionary dictionary)
    {
        _dictionary = dictionary;
    }

    public void AddModelError(string name, string error)
    {
        if (_dictionary[name] == null)
            _dictionary.Add(name, new ModelState());
        _dictionary[name].Errors.Add(error);
    }
}

Every service implements:

public interface IModelWrapperService
{
    IModelStateWrapper ModelWrapper {get;set;}
}

And then I set it in Controller:

public UserController(IUserService service)
{
    _service.ModelWrapper = new ControllerModelStateWrapper(ModelState);
}

IModelStateWrapper is not the best name, because this interface can work not only with Controller.ModelState. Works pretty ok. You can easily replace IModelStateWrapper with mock or other implementation in your service tests. This solution also automatically sets ModelState as invalid.

LukLed
+2  A: 

Your service should collection all the broken rules and after that throw the "BrokenRuleException". Your controller will catch the "BrokenRuleException" and then use the brokenrules to update the user interface.

azamsharp
A: 

I think that throwing the BrokenRuleException is a good choice.

Personally, I don't like to put state in a service, it's often a singleton (performed by a DI container), and only has other singletons collaborators (in my case, domain objects).

bloparod