How to inform the controller why the object creation has failed so an appropriate response can be returned?

softwareengineering.stackexchange https://softwareengineering.stackexchange.com/questions/418162

  •  17-03-2021
  •  | 
  •  

Question

In my MVC web application the controller calls a service layer which takes any relevant request parameters and builds the model for the view e.g.

Controller

var model = _modelService.Build(id);
return View("ViewName", model);

If there are multiple reasons why the model service will fail to build a valid model, how do I communicate that to the controller so it can return an appropriate response?

Below is a contrived example.

Model Service

var entity = _dataService.Get(id);
if (entity == null) {
  return null;
}

var entityMeta = _dataService.GetMeta(id);
if (entityMeta == null) {
  return null;
}

return new Model(entity);

Controller

var model = _modelService.Build(id);

// Null because of invalid id
if (model == null) { 
  return View("Invalid Id");
}

// Null because of missing meta data
if (model == null) {
  return View("Invalid meta data");
}
return View("ViewName", model);

In the example above there are two reasons why the model is null, but there is no way to inform the controller what has happened because all it gets is a null object back.

I can think of some possible solutions: throw an exception (which doesn't feel right - this isn't necessarily an unexpected outcome), move some of this logic to the controller (the general advise is to keep controllers slim), create a generic ModelResult object which contains the model or some information about why it has failed etc.

I feel like this is a common situation so there must be a standard pattern to apply.

Était-ce utile?

La solution

The simplest way is to beef up the service layer. So instead of the controller puzzling out the reason, you can have the result and errors/messages returned from the service layer.

var entity = _dataService.Get(id);
if (entity == null) {
  return null;
}

var entityMeta = _dataService.GetMeta(id);
if (entityMeta == null) {
  return null;
}

return new EntityOperationResult 
{
    Entity = entity,
    Messages = new List<Message>(),
};

Where an error might look like:

return new EntityOperationResult 
{
    Entity = null,
    Messages = new List<Message>() { new Message("Invalid foobar") }
};

This way, the service layer deals entirely with the entities and returns validation messages, but the controller can puzzle out what happened and instantiate the model from the entity.

Licencié sous: CC-BY-SA avec attribution
scroll top