MVC-控制器到服务层的通信

本文关键字:通信 服务 控制器 MVC- | 更新日期: 2023-09-27 18:24:55

在我的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);
    }
}

从服务层移动到视图模型非常容易,因为有了automapper,它可以非常容易地将事物扁平化。将另一个直接从视图模型转移到我的服务层是我很难想出一个好的解决方案的地方。

在"创建"操作这样的情况下,什么是好的方法?

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

我很确定服务层不应该知道任何关于视图模型的信息,但我也不认为AutoMapper在这种情况下也能很好地工作,因为它不擅长将平面模型制作成复杂的对象。

我的控制器应该是什么样子才能与服务层通信?我想让控制器中的代码尽可能轻。

MVC-控制器到服务层的通信

您可以定义一个双向映射,然后使用另一种方法:

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

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

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你的问题,因为我也想看到一种很好的干净的方法来做到这一点,而不必手动编写一堆代码来映射模型。

如果您的服务层仅用于支持MVC应用程序,而没有其他客户端,则可以考虑将通过服务层和从服务层传递的对象作为视图模型的一部分。这将消除自动映射入站调用的需要,因为您将从控制器发送所需的实际对象。

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