【问题标题】:Is calling service from controller a violation of MVC?从控制器调用服务是否违反 MVC?
【发布时间】:2015-07-10 11:15:37
【问题描述】:

我在网上看到很多代码参考,他们直接在Controller中使用服务。

public class PersonController : Controller
{
   public ActionResult Index(int personId)
   {
       Person personDataModel = null;
       using(var service = new Personservice())
       {
          personDataModel = service.GetPerson(personId);
       }

       var personVM = MapPersonDataModelToViewModel(personDataModel);

       return View("Index",personVM);
   }
}

根据MSDN控制器是处理用户交互的组件,与模型一起工作,并最终选择一个视图来呈现显示 UI。

哪里提到了服务? 我知道人们在谈论服务层模式或 SOA 架构。但这仍然是一个违规为了方便而违反

出于某种原因,如果我想取消服务。然后我将最终更改控制器。并且必须建立我的模型。 我想只更改模型。

我觉得 Model 应该具备智能,可以通过调用外部服务或自行处理来自 Controller 的请求。

public class PersonController : Controller
{
   public ActionResult Index(int personId)
   {
       var personVM = PersonModel.GetPerson(personId);

       return View("Index",personVM);
   }
}

public class PersonModel
{
   public PersonVM GetPerson(int personId)
   {
      Person personDataModel = null;
       //Can either do this
       using(var service = new Personservice())
       {
          personDataModel = service.GetPerson(personId);
       }

       //Or can do this
       personDataModel = GetPersonDataModel(personId);

      var personVM = MapPersonDataModelToViewModel(personDataModel);

      return personVM;
   }
}

我知道 PersonModel 需要重构,但这不是重点。

更新:

当我指的是模型时,我指的不是我们传递给视图的模型(具有属性的类)。我的意思是文件夹模型中的类。

根据MSDN,模型:模型对象是应用程序中实现应用程序数据域逻辑的部分。通常,模型对象检索模型状态并将其存储在数据库中。

我从上面假设文件夹 Model 中的类对象应该具有执行 CRUD 操作的逻辑。

我是不是错过了什么。请分享您的宝贵想法。

【问题讨论】:

  • 这取决于许多活动部件。如果您遵循 DDD,您将拥有不同类型的服务,如果您在控制器中使用它们中的一些是可以的,而其他一些则更有意义从对象持久层或视图模型中调用它们,就像您的情况一样。除此之外,这也取决于您的系统范围,我不敢为了遵循规则而为简单的应用程序构建服务和添加层。最后,这是个人品味的问题......只是一个想法。
  • 我说的是专门针对 CRUD 操作的服务。
  • 首先,您的文章有点过时(MVC4.)。话虽如此,MVC 更像是使用 MV 的 M-MV-V-C。看看这个页面:en.m.wikipedia.org/wiki/Model_View_ViewModel

标签: c# asp.net-mvc design-patterns model-view-controller n-tier-architecture


【解决方案1】:

没有。事实上,advocated 是一种让控制器保持美观和纤薄的方式。

【讨论】:

  • 在您提供的链接中,控制器中使用的 Orchestrator 对象类似于我提到的 PersonModel。我的观点是与外部服务交谈是模型而不是控制器的责任。控制器必须将命令传递给模型以获取 crud。模型反过来可能会使用外部服务。
  • 当我接近 MVC 和 MVP 时,我以最抽象的方式看待术语“模型”。我将外部服务、编排器、存储库以及控制器完成工作所需的任何其他内容视为“模型”。恕我直言,将“模型”视为单一事物是有关这些模式的文档长期存在的最大误解之一。
  • 我明白你在说什么,但是编排器或存储库不应该是文件夹模型的一部分。如果不是,那么在 asp.net mvc 项目中拥有文件夹 Models 有什么意义。
  • 或者如果它们是 Models 文件夹的一部分,您有什么顾虑吗?
  • 我的模型文件夹中只有视图模型类。
【解决方案2】:

我更喜欢将存储库与 UnitOfWork 模式一起使用。这是一篇很棒的文章:http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

我已经这样做了好几年了,我发现管理应用程序要容易得多。对于某些模型,我创建一个基类,然后创建一个接受基类的通用存储库。

【讨论】:

  • 抱歉,我的问题不是关于构建数据访问的最佳实践。根据 mvc,控制器应该将命令传递给 Model 以进行 crud 操作。模型可能使用存储库模式或其他方式来执行命令。我的问题是,控制器与服务而不是模型进行通信是否违规?
  • 不,这不是违规行为。您还必须考虑视图模型与数据模型。通过允许使用不同的视图模型(如registrationViewModel)访问相同的数据模型(如帐户),服务运行良好。
【解决方案3】:

控制器:处理传入浏览器请求、检索模型数据,然后指定向浏览器返回响应的视图模板的类。

如果你发现你的控制器中有太多的代码(或者,更重要的是,它有业务逻辑),那么你需要的是一个位于控制器和服务层之间的应用程序外观层,co-协调您的服务并为您的控制器提供更简单的界面。

或者,如果您尝试移动的代码是表示层逻辑(例如模型验证、视图模型的构造、表单值的处理、视图模型到服务层实体的映射等),那么它确实属于您的控制器 - 即使它有几行以上。如果这样做是有益的,您仍然可以通过将其分解为帮助程序来简化事情,但不要仅仅因为有人告诉您您的控制器操作中的代码行数不应超过五行而这样做。

另一种选择是为您的服务创建一个扩展方法并像这样在控制器中调用

ISStudentService 的扩展方法:

public static class StudentServiceExtensions
{
public static StudentViewModel CreateViewModel(
    this IStudentService service,
    int id)
{
    var e = service.GetStudentDetails(id);
    var vm = ConvertStudentToViewModel(e);
    return vm;
}
}

然后你会像这样在你的控制器中调用它:

 var viewModel = this.StudentService.CreateViewModel(id);

【讨论】:

    猜你喜欢
    • 2012-07-15
    • 1970-01-01
    • 1970-01-01
    • 2020-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-21
    • 2012-01-14
    相关资源
    最近更新 更多