关于专业核心的最受欢迎的书籍之一是亚当·弗里曼的“专业ASP.NET核心3”。
在第7-11章中,他构建了一个示例应用程序SportsStore。
HomeController的Index方法显示了一个产品列表:

下面是Index方法:
public ViewResult Index(int productPage = 1)
=> View(new ProductsListViewModel {
Products = repository.Products
.OrderBy(p => p.ProductID)
.Skip((productPage - 1) * PageSize)
.Take(PageSize),
PagingInfo = new PagingInfo {
CurrentPage = productPage,
ItemsPerPage = PageSize,
TotalItems = repository.Products.Count()
}
});与此方法对应的视图文件是Views\Home\Index.cshtml。此文件的顶部有以下行:
@model ProductsListViewModel所以视图需要一个ProductsListViewModel类型的对象。但是,在Visual Studio中,IntelliSense将View显示为需要object类型的参数

令我惊讶的是,这里的View没有显示为期望ProductsListViewModel类型的对象。因为它被设置为接受object类型的参数,所以我们实际上可以传入一些无意义的值:
public ViewResult Index(string category, int productPage = 1) =>
View(10);并且项目仍然会被编译!
有没有办法让View实际上只接受视图文件中指定的模型类型?也就是说,在这种情况下,设置使View只接受ProductsListViewModel
谢谢!
发布于 2020-07-17 00:04:44
通过使用泛型,我完成了以下操作。
//This is the Base class for every model must inherit.
public class EntityModel
{
public int ID { get; set; }
}
//Model / view model must inherit from EntityModel
public class EmployeeModel : EntityModel
{
public string Name { get; set; }
}创建一个仅接受EntityModel或其派生类的新ViewController。将视图及其重载方法标记为过时,以便只能使用实体模型调用作为参数。另外,如果有人使用它,请限制他们使用它。因此抛出错误。
public class ViewController<T> : Controller where T: EntityModel
{
[Obsolete]
public override ViewResult View()
{
return base.View();
}
[Obsolete]
public override ViewResult View(object model)
{
throw new Exception("Use view method which accepts EntityModel");
}
[Obsolete]
public override ViewResult View(string viewName)
{
throw new Exception("Use view method which accepts EntityModel");
}
[Obsolete]
public override ViewResult View(string viewName, object model)
{
throw new Exception("Use view method which accepts EntityModel");
}
public new ViewResult View(T model)
{
return base.View(model);
}
}使用家庭控制器中新创建的ViewController。
public class HomeController : ViewController<EmployeeModel>
{
public IActionResult Index()
{
EmployeeModel emp = new EmployeeModel();
emp.ID = 1;
emp.Name = "Satish Pai";
return View(emp);
}
}发布于 2020-07-17 03:36:59
我不认为有办法捕捉任何错误的视图模型在编译时传递到视图中!
问题所在
视图与您在顶部声明的视图模型是强类型的,因此它知道要进入哪个模型,但控制器不知道您希望它返回到哪个视图……
默认情况下,控制器将返回与该方法同名的视图,但您可以更改该默认设置,甚至可以将视图的名称作为字符串参数传递给某个View()重载:
public IActionResult Index(string category, int page = 1)
{
...
return View("OutOfStock", vm);
}现在,Visual Studio不知道您希望控制器构建哪个视图模型并将其传递给视图。事实上,Visual Studio甚至不知道我想要返回什么视图。即使在我把"OutOfStock“作为视图名称之后,Visual Studio甚至不知道视图是否存在……
使用泛型
@Satish的解决方案确实很有趣,但它假设您只为一个控制器使用一个单一视图模型,通常情况并非如此。通常,对于不同的操作,您会有不同的视图模型。
如果泛型是可行的,我建议把它放在动作上,而不是放在控制器上:
public abstract class BaseController : Controller
{
public ViewResult View<T>(T viewModel) where T : new()
{
return View(viewModel);
}
}然后你可以像这样在控制器中使用它:
public class ProductController : BaseController
{
public IActionResult Index(string category, int page = 1)
{
var vm = new ProductListViewModel
{
...
};
return View<ProductListViewModel>(vm);
// This would give you the compile time error!
// return View<ProductListViewModel>(10);
}
}但是为什么呢?这样做的意义是什么?作为开发人员,您必须知道ProductListViewModel无论如何都是要传递的正确视图模型。只有当有初级或新员工正在处理您的代码,而不检查返回的视图所要求的视图模型时,这样的事情才会有帮助?
也许吧?
现在,我知道像Resharper这样的工具也许能够在编译时帮助并捕捉不匹配的情况。
另外,编写关于控制器中返回的方法的单元测试可能会有所帮助?
https://stackoverflow.com/questions/62935070
复制相似问题