简体   繁体   English

我应该将服务注入我的MVC视图吗?

[英]Should I inject services into my MVC views?

We're working on some kind of Cloud CMS using ASP.NET MVC technology, and have found some obstacles on the way. 我们正在使用ASP.NET MVC技术开发某种云CMS,并且在途中遇到了一些障碍。 There is a number of parameters user could change thru the control panel that we need to end up in Views. 用户可以通过控制面板更改许多参数,我们需要在视图中结束这些参数。 For example, Facebook application id to initialize the Facebook JS API. 例如,Facebook应用程序ID初始化Facebook JS API。 Or additional text to be shown on the page. 或者在页面上显示其他文本。 Or background picture. 或背景图片。 For now we're not using DI to transfer this parameters, instead we're adding them to the ViewModel, but this ruin the ASP.NET MVC way of working with models (eg form validation, bindings etc.) 目前我们没有使用DI来传输这些参数,而是将它们添加到ViewModel中,但这破坏了ASP.NET MVC处理模型的方式(例如表单验证,绑定等)

It looks like that using DI to inject services for providing parameters, texts and pictures could make my views less dependent on controllers specific, and there is even some Microsoft technique to do it http://www.asp.net/mvc/tutorials/hands-on-labs/aspnet-mvc-4-dependency-injection#Exercise2 . 看起来使用DI注入提供参数,文本和图片的服务可能会使我的视图更少依赖于特定于控制器,甚至还有一些Microsoft技术可以做到这一点http://www.asp.net/mvc/tutorials/动手实验/ aspnet-mvc-4-dependency-injection#Exercise2 However, there are a lot of answers on forums against injecting services into Views using DI. 但是,在论坛上有很多答案反对使用DI将服务注入到视图中。

So the question: what is a right way to inject some services into Views? 所以问题是:在视图中注入一些服务的正确方法是什么? Or I shouldn't do it at all and something is wrong in the application design? 或者我根本不应该这样做,应用程序设计出了什么问题?

UPDATE : some real code examples (now we're using Model to inject the services) 更新 :一些真实的代码示例(现在我们使用Model来注入服务)

Injecting texts from database (they have to be user-editable, as it is CMS): 从数据库中注入文本(它们必须是用户可编辑的,因为它是CMS):

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

Injecting translations from database (actually, it is localization): 从数据库中注入翻译(实际上,它是本地化):

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

Injecting parameters (from database, could be request-specific; for example, if the site has different domains, facebook application should be per-domain): 注入参数(来自数据库,可能是特定于请求的;例如,如果站点具有不同的域,则facebook应用程序应为每个域):

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

The problem of current approach is that this code has taken from contest mechanic. 当前方法的问题在于此代码取自竞赛机制。 It is definitely out of contest business scope to deal with custom texts, translations or facebook application Id. 处理自定义文本,翻译或Facebook应用程序ID绝对不在竞争业务范围之内。 Also it ruins the Model as model models not actual business domain but deals with a lot of things actually belongs to View (like translations and custom texts) 它也破坏了模型作为模型模型而不是实际的业务领域,但处理很多事实际上属于View(如翻译和自定义文本)

UPDATE 2 : Have modified the snippet from the answer below to be a bit more generic: 更新2 :修改了以下答案的片段,使其更具通用性:

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

No, you shouldn't inject services into Views, but... 不,你不应该将服务注入视图,但......

For scenarios such as theming where you want to give the theme developer more power, just one model isn't enough. 对于诸如主题的场景,您希望为主题开发人员提供更多功能,仅仅一个模型是不够的。 If your model contains the current post for example, how can a theme designer asks for a list of categories for the sidebar? 例如,如果您的模型包含当前帖子,主题设计师如何请求侧边栏的类别列表? Or for a widget? 或者对于小部件?

In asp.net mvc you can use extension methods to offer that functionality.THe extension method will use the dependency resolver to get the service. 在asp.net mvc中,您可以使用扩展方法来提供该功能。扩展方法将使用依赖项解析程序来获取服务。 This way, you can have the needed functionality in the view without actually injecting a service. 这样,您可以在视图中拥有所需的功能,而无需实际注入服务。

Note that calling the business layer to update the model is still a violation of Separation of Concerns. 请注意,调用业务层更新模型仍然违反了“关注点分离”。 THe services made available to the view should contain only read model or general utility functionality. 视图可用的服务应仅包含读取模型或常规实用程序功能。

An example 一个例子

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

IMyViewServices lifetime configured in the DI Container should be per http (scope) request 在DI容器中配置的IMyViewServices生命周期应该是每个http(范围)请求

No, end of story. 不,故事结束。 Why? 为什么? Here is why: 原因如下:

Your view only needs to know what the view model it's going to be working with to present that model. 您的视图只需要知道它将用于呈现该模型的视图模型。 There are couple of reasons for this but the biggest one is the separation of concerns. 这有几个原因,但最大的原因是关注点的分离。 Keep your view as stupid as possible. 保持你的观点尽可能愚蠢。 You will see that this seperation will give you a clean application structure throughout the way. 您将看到这一分离将在整个过程中为您提供干净的应用程序结构。

There is a number of parameters user could change through the control panel that we need to end up in Views. 用户可以通过控制面板更改许多参数,我们需要在视图中进行更改。

I'm not sure what you exactly mean here but this is why there are view models. 我不确定你在这里究竟是什么意思,但这就是为什么有视图模型的原因。 Your business layer will shape models up, your controller will simply map them to your view models and pass them into the view (presentation layer). 您的业​​务层将塑造模型,您的控制器将简单地将它们映射到您的视图模型并将它们传递到视图(表示层)。

This really depends on how much or little you want your controllers to do and to what degree of separation you want to achieve. 这实际上取决于您希望控制器做多少,以及您希望实现的分离程度。

In my world, the "controller" in an MVC app does as little as possible because I have a service layer handling all of the business logic and a data layer above that handling all of the database interaction. 在我的世界中,MVC应用程序中的“控制器”尽可能少,因为我有一个处理所有业务逻辑的服务层和一个处理所有数据库交互的数据层。

On a GET, the controller will simply call a service method that will build the view model and hands it back to the controller and the controller passes it on to the view. 在GET上,控制器将简单地调用一个服务方法,该方法将构建视图模型并将其交还给控制器,然后控制器将其传递给视图。 On POST, the view posts data to the controller which sends it off to the service layer for validation, saving to DB, etc. The service is injected into the controller's constructor. 在POST上,视图将数据发布到控制器,控制器将其发送到服务层进行验证,保存到DB等。服务被注入到控制器的构造函数中。

I'd be more than happy to post code examples if you'd like to see them. 如果你想看到它们,我会非常乐意发布代码示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用 Ninject 注入我的服务以获取 GetVaryByCustomString - How Can I Inject My Services To GetVaryByCustomString With Ninject 我应该对我的域服务进行授权吗? - Should i do authorization on my Domain Services? ASP.Net MVC Pager助手和视图无法一起使用-我应该在视图的第一行中添加什么 - ASP.Net MVC Pager helper and view not working together - what should I put in my views first line 我应该在ASP.NET MVC视图中公开主键 - Should I expose primary keys in ASP.NET MVC views 如何让Ninject将依赖项注入到我的MVC控制器中? - How do I let Ninject inject dependencies into my MVC controllers? 我正在将我的服务注入控制器。 我应该将服务注入到ViewModel中吗? - I'm injecting my Service into my controller. Should I inject my Service into my ViewModel instead? 我应该在服务中的哪个位置创建DbContext? - Where should I create my DbContext among my services? 我应该如何将我的商业模式与我的观点联系起来? - How should I be binding my business models to my views? 我是否应该将Prism视图设置为特殊的View类? - Should I make my Prism views a special View class? 我应该何时在Web服务(ASMX)中实例化我的类? - When should I instantiated my classes in Web Services (ASMX)?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM