MVC - 控制器到服务层通信

时间:2012-02-17 15:33:35

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

在我的ASP.net mvc应用程序中,我使用服务层和存储库来保持我的控制器很薄。典型的详细信息只读视图如下所示:

public ActionResult Details(int id)
{
    var project = _projectService.GetById(id);

    return View(Mapper.Map<Project, ProjectDetails>(project));
}

服务层:

public class ProjectService : IProjectService
{
    public Project GetById(int id)
    {
        var project = _projectRepository.GetProject(id);

        // do some stuff

        return project;
    }
}

public class ProjectRepository : IProjectRepository
{
    public Project GetProject(int id)
    {
        return context.Projects.Find(id);
    }
}

从服务层移动到视图模型非常容易,因为自动化器可以很容易地平整事物。将另一个直接从视图模型移到我的服务层是我努力想出一个好的解决方案。

在像Create一样的情况下,对此有什么好处?

[HttpPost]
public ActionResult Create(CreateProjectViewModel model)
{
    if(!ModelState.IsValid)
    {
        return View(model);
    }

    // TODO

    return RedirectToAction("Index");
}

我很确定服务层不应该对视图模型有所了解,但我也不认为AutoMapper在这种情况下运行良好,因为它不擅长采用扁平模型并将其变为复杂的对象。

我的控制器应该如何与服务层进行通信?我想尽可能保持控制器中的代码。

3 个答案:

答案 0 :(得分:5)

您可以定义双向映射,然后反过来:

[HttpPost]
public ActionResult Create(CreateProjectViewModel model)
{
    if(!ModelState.IsValid)
    {
        return View(model);
    }

    Project project = Mapper.Map<CreateProjectViewModel, Project>(model);
    // pass the project entity to your service layer
    _projectService.Create(project);

    return RedirectToAction("Index");
}

或者如果您要更新实体,您可能首先要从服务中获取要更新的现有实体:

[HttpPost]
public ActionResult Update(CreateProjectViewModel model)
{
    if(!ModelState.IsValid)
    {
        return View(model);
    }

    Project project = _projectService.GetById(model.Id);
    Mapper.Map<CreateProjectViewModel, Project>(model, project);

    // pass the project entity to your service layer
    _projectService.Update(project);

    return RedirectToAction("Index");
}

答案 1 :(得分:1)

到目前为止,我看到这种方法的唯一方法是手动创建一组模型转换类,例如:

public interface ITransformer<out To, in From>
    where To : class
{
    To Transform(From instance);
}

public class SomeDataToSomeViewModelTransformer : ITransformer<SomeViewModel, SomeDataModel>
{
    public SomeViewModel Transform(SomeDataModel instance)
    {
        return new SomeViewModel
            {
                InvitationId = instance.Id,
                Email = instance.EmailAddress,
                GroupId = instance.Group.Id
            };
    }
}

另一个Transformer实现以另一种方式返回(ViewModel -> DataModel)。 让控制器知道呼叫正确的变压器。

我给你的问题+1,因为我很乐意看到一个很好的干净方法,而不必手动编写一堆代码来映射模型。

答案 2 :(得分:0)

如果您的服务层专门用于支持您的MVC应用程序而不支持其他客户端,则可以考虑使用通过服务层传递的对象作为视图模型的一部分。这样可以避免在您从控制器发送实际对象时自动执行入站调用的需要。

您还可以考虑 not 让服务返回域对象,这意味着应该使用服务方法而不是控制器操作来调用自动化。