Alternative to ViewBag.Title in ASP.NET MVC 3
默认情况下,ASP.NET MVC 3的新项目模板将以下内容添加到默认布局(剃刀中的母版页):
1 | @ViewBag.Title |
然后,该视图必须包含以下内容以分配页面标题,例如:
1 2 3 | @{ ViewBag.Title ="Log On"; } |
也许这只是我自己的喜好,但我发现使用ViewBag来保持标题有点错误(我想的是太多的魔术弦味)。 所以我的问题是:对于使用ASP.NET MVC 3和剃须刀(使用动态属性包)的人们,这是推荐的最佳实践,还是您选择了更强类型的内容(可能涉及自定义基类?)
我认为asp.net MVC 3附带的默认标题处理功能没有什么不好的,可以这样做。
我亲自(下面写的)来处理标题,我不认可以下代码,也不是说它比默认功能更好,它只是一个首选项。
主
1 | @RenderSection("Title"); |
视图
1 2 3 4 | @section Title { write title } |
我可能建议改善默认功能的一件事
1 2 3 4 | @{ string pageTitle = @ViewBag.Title ??"Title Not Set"; } @pageTitle |
因此,每当您忘记将其添加到视图包中时,页面就会显示title =
也可以创建一个基类,然后使所有控制器从该基类继承。但是我认为它为
标题的ViewBag非常好(我什至会说这是拥有ViewBag的目的)-动态并不是绝对的邪恶。"标题"是众所周知的,不可能更改甚至在视图模板中预定义。我个人使用以下标题:
1 | @(ViewBag.Title == null ? string.Empty : ViewBag.Title +" |")Site Name |
如果您担心误输入
我建议坚持使用
我也完全不使用ViewBag。
在_Layout.shtml的顶部...
1 | @model <YourWebAppNameSpace>.Models.Base.EveryPageViewModel |
在_Layout.shtml中...
1 | @Model.Title |
在您的模型中...
1 2 3 4 5 6 | /// <summary> /// Index View Model /// </summary> public class IndexViewViewModel : EveryPageViewModel { } |
在EveryPageViewModel中
1 2 3 4 5 6 7 8 9 10 11 12 13 | /// <summary> /// Every Page View Model /// </summary> public abstract class EveryPageViewModel { /// <summary> /// Title /// </summary> public string Title { get; set; } /// <summary> /// Sub Title /// </summary> public string SubTitle { get; set; } } |
在您的控制器动作中
1 2 3 4 5 6 7 8 9 | /// <summary> /// Index /// </summary> /// <returns></returns> public ActionResult Index() { var model = new IndexViewViewModel(); model.Title ="Home"; return View(model); } |
我喜欢创建PageTitle ActionFilter属性,而不是编辑单个ViewBags
用法:保持视图不变
1 | @ViewBag.Title |
对于控制器范围内的页面标题:
1 2 3 4 | [PageTitle("Manage Users")] public class UsersController : Controller { //actions here } |
对于个人观点:
1 2 3 4 5 6 | public class UsersController : Controller { [PageTitle("Edit Users")] public ActionResult Edit(int id) { //method here } } |
属性代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class PageTitleAttribute : ActionFilterAttribute { private readonly string _pageTitle; public PageTitleAttribute(string pageTitle) { _pageTitle = pageTitle; } public override void OnActionExecuted(ActionExecutedContext filterContext) { base.OnActionExecuted(filterContext); var result = filterContext.Result as ViewResult; if (result != null) { result.ViewBag.Title = _pageTitle; } } } |
易于管理,魅力十足。
使用ViewBag.Title =" My Title"没有什么错;
您要做的就是使用动态属性。
问题实际上是应该在哪里"声明"信息。
即,出于手头的目的,它在哪里最容易访问。
如果以每页为基础,那是正确的位置。
但是,如果页面标题可以从Model派生,则应该这样做。
在这种情况下,我可能会为您使用的ViewModel使用基类,并在其中创建PageTitle属性,该属性包含从Model属性中派生页面标题的逻辑。
所以:
1 | Model.PageTitle |
总而言之,只要您了解它们的本质和作用,参加课程的马就不必害怕使用动态属性。
我们更喜欢强标题设置。.BaseController类中的一些示例。 (页面定义了封装视图模态)
1 2 3 4 5 6 7 8 9 10 | protected override ViewResult View(string viewName, string masterName, object model) { if (model is Page) { ViewBag.Title = ((Page)model).Title; //HACK: SEO //TODO: SEO } return base.View(viewName, masterName, model); } |
我想说的是,只要是您要设置的标题,就可以使用ViewBag。好吧,也许不仅如此-最多2-3个属性。
但是,如果您开始发现您在每个控制器操作中都设置了越来越多的(通用)属性,那么我将使用强类型的" ViewModelBase类"。但这只是我。
就我个人而言,我认为这种情况是
祝好运!