[英]Adding Razor keywords
扩展Razor视图引擎以添加其他关键字的最佳流程是什么?
我不是dynamic ViewBag
属性的粉丝,因此对于我的所有页面,我既定义了强类型的ViewModel
POCO,又定义了强类型的ViewData
对象:
public abstract class BaseViewData<TModel,TController> : ViewDataDictionary<TModel>
(指定TController
可选择允许对父Controller
进行强类型回调)
这样我就可以拥有编译时验证过的成员,比如String PageTitle
(在一个站点范围的基类中)和每页成员 - 它与ViewModel协同工作: BaseViewData
-subclass包含单向数据,并且ViewModel
-class包含双向数据。 当您调整MSBuild系统以将视图预编译到输出程序集中时,这非常有用 - 不再需要.aspx
或.cshtml
文件!
在ASP.NET MVC中(使用WebForms视图引擎)我有自己的基础ViewPage
子类:
public class ViewPage2<TViewModel,TViewData> : ViewPage<TModel> where TViewData : ViewDataDictionary<TModel> {
private TViewData _data;
public new TViewData ViewData {
get {
if( _data == null ) {
_data = (TViewData)base.ViewData;
}
return _data;
}
}
}
我最近把它带到了Razor,很容易做到:
public abstract class WebViewPage2<TViewModel,TViewData> : WebViewPage<TModel> where TData : ViewDataDictionary<TModel> {
// same ViewData property code as above
}
在.cshtml
文件中,您可以使用@inherits
razor关键字手动指定基类 - 这需要完全限定的具体泛型类型名称 - 但是您可以省略@inherits
而是指定@model
关键字,Razor将通过该关键字作为WebViewPage<TModel>
的TModel
参数。
当我的基类添加第二个泛型类型参数时,我宁愿不必输入我的.cshtml
文件:
@inherits MyNamespace.WebViewPage2<MyOtherNameSpace.Views.FooViewModel,MyOtherNameSpace.Views.FooViewData>
......而是这样做:
<system.web.webPages.razor>
<pages pageBaseType="MyNamespace.WebViewPage2">
...
@model FooViewModel
@data FooViewData
但这需要以某种方式扩展Razor View引擎 - 但这是不明显的,因为它需要扩展Razor解析器本身,因此它识别@data TViewData
并将其作为第二类型参数传递。
您可以像这样实现一个继承的ViewClass(注意命名空间,不能更改它):
namespace System.Web.Mvc {
public abstract class WebViewPage<TViewModel, TModel> : WebViewPage<TModel> where TViewModel : class {
private TViewModel _viewModel;
public TViewModel ViewModel {
get {
if (_viewModel == null) {
throw new InvalidOperationException("No ViewModel defined for this View.");
}
return _viewModel;
}
set { _viewModel = value; }
}
public override void InitHelpers() {
base.InitHelpers();
if (this.ViewBag.ViewModel == null) {
// No ViewModel defined => set null.
}
else if (!(this.ViewBag.ViewModel is TViewModel)) {
throw new InvalidOperationException(string.Format("The specified ViewModel value is of type '{0}' and must be of type '{1}'.", this.ViewBag.ViewModel.GetType(), typeof(TViewModel)));
} else {
_viewModel = this.ViewBag.ViewModel;
}
}
}
}
然后你不必更改web.config或其他任何东西,并可以像这样实例化视图:
@model ViewModelType, (Input?)ModelType
然后,通过@ViewModel
在视图中可以使用键入的ViewModel(View by ViewModelType类型)。 类型(输入)ModelType的模型仍然像@Model
一样可用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.