MVC - 服务层应如何与控制器通信

时间:2011-12-16 22:00:51

标签: c# asp.net-mvc service-layer

我一直在使用以下模式进行控制器操作:

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);
    }
}

我的服务层如何轻松与我的控制器通信?

这些是我想与控制器沟通的事物类型:

        
  • 业务逻辑/验证错误
  •     
  • 数据库失败(无法保存等)

如果不从服务层返回真/假或状态代码,我怎么能这样做?

2 个答案:

答案 0 :(得分:2)

如果选择例外,请注意,这些都很昂贵。它还为控制器代码提供了额外的嵌套,具体取决于可能引发的异常数量。实际上,您应该只针对异常情况抛出异常,而不应该由应用程序的正常流程处理。

我会选择Wouter de Kort建议的其他路由,使用服务的返回类型作为消息传递对象。您可以使用服务可能遇到的各种情况在简单枚举上键入返回消息对象。这些在控制器中看起来更好,因为您可以使用switch / 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; }
}

答案 1 :(得分:1)

如果要在发生错误时返回详细消息,可以始终使用“例外”。也许可以使用特定的详细信息定义您自己的内容,或者重用.NET Framework中已有的内容。

如果这不是一个选项,你总是可以返回一个包装类,它可能包含更详细的错误信息并在Controller中处理它。