在Razor视图中注入依赖项的最佳实践是什么?
我们可以将控制器用作服务,并注入该服务或注入服务
我不知道这些注入方式的利弊。
- 控制器:
在Startup.cs 中
public void ConfigureServices(IServiceCollection services)
{
.
.
.
services.AddControllersWithViews().AddControllersAsServices().AddRazorRuntimeCompilation();
}
那么内部home.cshtml
@inject CourseController _courseControler
.
.
.
<select asp-for="CategoryID" class="form-control round">
@foreach (var item in await _courseControler.GetAllCourceCategory()){
<option value="@item.ID">@item.Description</option>
}
</select>
- 服务:
在Startup.cs 中
public void ConfigureServices(IServiceCollection services)
{
.
.
.
services.AddTransient<ICourseService, CourseService>();
}
那么内部home.cshtml
@inject ICourseService _courseService
.
.
.
<select asp-for="CategoryID" class="form-control round">
@foreach (var item in await _courseService.GetAllCourceCategory()){
<option value="@item.ID">@item.Description</option>
}
</select>
我将通过假设应用程序是来解释这一点。NET核心MVC应用程序。(事实上,相同的原则也适用于Razor Page应用程序,但在实现时会有一些不同。(
简而言之,在视图中注入控制器或服务不是一个好主意。
使用@inject
来自。NET核心文档:
ASP。NET Core支持在视图中注入依赖项。这对于视图特定服务非常有用。
因此,视图特定是关键。
将控制器注入视图
同样,来自微软的文档:
MVC控制器负责响应针对ASP的请求。NET MVC网站。
当您将控制器注入视图文件时,您的控制器没有执行它应该执行的操作。
将服务注入视图
如果服务是特定于UI的,那么您可以这样做。你可以从官方文档中找到一个例子。
如果您的服务不处理特定于UI的内容(例如,从数据库中获取数据(,则应在控制器级别注入(或者,当您使用Razor Pages时,在.cshtml.cs
文件中(。
使用视图模型
如果ICourseService
是特定于数据的服务,则应在控制器操作中调用_courseService.GetAllCourseCategory()
。
您可能需要一个视图模型,如下所示:
public class HomeViewModel
{
public List<Course> Courses { get; set; }
}
在您的控制器操作中:
// inject ICourseService in the controller constructor
public Task<IActionResult> Home()
{
var viewModel = new HomeViewModel
{
Courses = await _courseService.GetAllCourseCategory()
};
return View(viewModel);
}
在视图文件中:
@model HomeViewModel
<select asp-for="CategoryID" class="form-control round">
@foreach (var item in Model.Courses) {
<option value="@item.ID">@item.Description</option>
}
</select>
这就是典型的MVC应用程序的样子。
结论
可以在视图文件中注入控制器或服务,但大多数情况下,不应该在MVC应用程序中这样做。这违反了控制器和视图的目的。类似地,向视图注入非UI特定的服务也违反了视图的目的。
使用模型携带您的数据(从服务中检索(。对流量使用控制器。使用视图渲染模型。这就是MVC的工作原理。