我应该在MVC视图中注入服务吗?

本文关键字:服务 注入 MVC 视图 我应该 | 更新日期: 2023-09-27 18:10:10

我们正在使用ASP开发某种云CMS。NET MVC技术,并在此过程中发现了一些障碍。用户可以通过控制面板更改许多参数,我们需要在视图中结束这些参数。例如,Facebook应用程序id来初始化Facebook JS API。或要在页面上显示的附加文本。或者背景图片。现在我们没有使用DI来传递这些参数,而是将它们添加到ViewModel中,但是这会破坏ASP。. NET MVC处理模型的方式(例如表单验证、绑定等)

看起来使用DI注入服务来提供参数、文本和图片可以使我的视图更少地依赖于特定的控制器,甚至有一些微软技术可以做到http://www.asp.net/mvc/tutorials/hands-on-labs/aspnet-mvc-4-dependency-injection#Exercise2。然而,论坛上有很多反对使用DI向视图中注入服务的回答。

那么问题来了:把一些服务注入视图的正确方式是什么?或者我根本不应该这样做,而应用程序设计中出现了问题?

UPDATE:一些真实的代码示例(现在我们使用Model来注入服务)

从数据库中注入文本(它们必须是用户可编辑的,因为它是CMS):

<div class="steps">@Html.Raw(Model.Texts["Main", "Step2"]</div>

从数据库注入翻译(实际上是本地化):

<div class="gonfalon">@Model.Translations["Title_Winners"]</div>

从数据库注入参数,可以是特定于请求的;例如,如果站点有不同的域,facebook应用程序应该是每个域):

Facebook.Initialize(Model.Parameters["FbApplicationId"], Model.Parameters["FbApplicationSecret"]);

当前方法的问题在于该代码取自竞赛机制。处理自定义文本、翻译或facebook应用程序Id绝对不在竞赛业务范围之内。它还破坏了模型,因为模型不是实际的业务领域,而是处理了许多实际上属于视图的事情(如翻译和自定义文本)

UPDATE 2:修改了下面答案的代码片段,使其更通用:

public static class WebViewPageExtensions 
{ 
    public static I ResolveService<I>(this WebViewPage page) 
    { 
         return DependencyResolver.Current.GetService<I>(); 
    } 
} 

我应该在MVC视图中注入服务吗?

不,你不应该把服务注入到视图中,但是…

对于像主题这样的场景,你想给主题开发人员更多的权力,只有一个模型是不够的。例如,如果您的模型包含当前帖子,主题设计人员如何为侧边栏请求类别列表?还是一个小部件?

在asp.net mvc中,您可以使用扩展方法来提供该功能。扩展方法将使用依赖解析器来获取服务。这样,您就可以在视图中拥有所需的功能,而无需实际注入服务。

注意调用业务层来更新模型仍然违反了关注点分离。视图可用的服务应该只包含读取模型或通用实用程序功能。

示例

 public static IMyViewServices MyServices(this WebViewPage view)
     {
         return DependencyResolver.Current.GetService<IMyViewServices>();
     }

IMyViewServices在DI容器中配置的生存期应该是每个http(作用域)请求

不,故事结束了。为什么?原因如下:

你的视图只需要知道它将与什么视图模型一起工作来呈现那个模型。这有几个原因,但最大的一个原因是关注点的分离。保持你的观点尽可能愚蠢。您将看到,这种分离将在整个过程中为您提供一个干净的应用程序结构。

用户可以通过控制面板更改许多参数,我们需要在视图中结束。

我不确定你到底是什么意思,但这就是为什么有视图模型。您的业务层将塑造模型,您的控制器将简单地将它们映射到您的视图模型并将它们传递到视图(表示层)。

这实际上取决于你希望你的控制器做多少以及你想要实现的分离程度。

在我的世界里,MVC应用中的"控制器"做得尽可能少,因为我有一个服务层处理所有的业务逻辑,上面有一个数据层处理所有的数据库交互。

在GET中,控制器将简单地调用一个服务方法,该方法将构建视图模型并将其交还给控制器,然后控制器将其传递给视图。在POST中,视图将数据发送给控制器,控制器将数据发送到服务层进行验证,保存到DB,等等。服务被注入到控制器的构造函数中。

如果你想看的话,我很乐意贴出代码示例。