MVC - как уровень сервиса должен взаимодействовать с контроллером

Я использовал следующий шаблон для действий моего контроллера:

public ActionResult Create(CreateViewModel model) {
    if( !ModelState.IsValid ) {
        return View(model); 
    }

    var project = new Project {
        Name = model.Name,
        // ...
    };

    projectRepository.Add(project);

    return RedirectToAction("Index");
}

Это работает для простых сценариев, но у меня было несколько ситуаций, когда репозитория было недостаточно. Я создал уровень / класс сервиса, который будет обрабатывать сохранение проекта и любую дополнительную бизнес-логику (не обычные проверки с плавной проверкой или аннотациями данных).

public class ProjectService : IProjectService {

    void AddProject(Project project) {
        // do business logic
        // ...

        repository.Add(project);
    }
}

Как мой сервисный уровень может легко взаимодействовать с моим контроллером?

Вот что я хотел бы сообщить контроллеру:

  • Ошибки бизнес-логики / валидации
  • Сбои базы данных (не удалось сохранить и т. Д.)

Как я могу сделать это, не возвращая только истинное / ложное или коды состояния из уровня сервиса?


person Dismissile    schedule 16.12.2011    source источник


Ответы (2)


Будьте осторожны, выбирая исключения, это дорого. Это также дает вашему коду контроллера дополнительную вложенность, в зависимости от того, сколько исключений может быть сгенерировано. На самом деле вы должны генерировать исключение только для исключительного условия, а не для того, что должно обрабатываться обычным потоком вашего приложения.

Я бы пошел другим путем, предложенным Воутером де Корт, используя тип возврата службы для объекта обмена сообщениями. Вы можете указать объект возвращаемого сообщения в простом перечислении с различными случаями, с которыми может столкнуться служба. Они выглядят лучше в контроллере, потому что вы можете обрабатывать перечисление с помощью переключателя / case, а не try / catch.

Обновлять

Как может выглядеть объект обмена сообщениями:

public interface IServiceAbc
{
    ServiceResponse InvokeMyService([params]);
}

public enum ResponseScenario
{
    Success,
    DatabaseFailed,
    BusinessRuleViolated,
    ValidationRuleViolated
}

public class ServiceResponse
{
    public ResponseScenario Scenario { get; internal set; }
    public string Message { get; internal set; }
}
person danludwig    schedule 16.12.2011

Если вы хотите возвращать подробные сообщения при возникновении ошибки, вы всегда можете использовать исключения. Возможно, определите свои собственные с конкретными деталями или повторно используйте те, которые уже есть в .NET Framework.

Если это не вариант, вы всегда можете вернуть класс-оболочку, который может содержать более подробную информацию об ошибке, и обработать ее в контроллере.

person Wouter de Kort♦    schedule 16.12.2011