默认情况下,ASP.NET MVC 3的新项目模板将以下内容添加到默认布局(razor中的母版页):
<title>@ViewBag.Title</title>
然后,视图必须包含以下内容以分配页面标题,例如:
@{
ViewBag.Title = "Log On";
}
也许这只是我自己的偏好,但我发现使用ViewBag来保持标题有点不对(我想的是太多魔术字符串的味道)。所以我的问题是:对于使用ASP.NET MVC 3和razor(使用动态属性包)的人来说这是推荐的最佳实践吗?或者你选择了更强类型的东西(可能涉及自定义基类?)
答案 0 :(得分:26)
我认为asp.net MVC 3附带的默认标题处理功能没有任何不妥之处,可以这样做。
我个人这样做(下面写的)处理标题,我不支持下面的代码或者说它比默认功能更好,只是一个偏好。
主
<title>
@RenderSection("Title");
</title>
查看
@section Title
{
write title
}
我可以建议改善默认功能的一件事
@{
string pageTitle = @ViewBag.Title ?? "Title Not Set";
}
<title>@pageTitle</title>
因此,每当您忘记在viewbag中添加它时,页面将显示title = Title Not Set
创建基类然后使所有控制器从该基类继承也可以完成。但我认为它对title
带来了太大的痛苦。
答案 1 :(得分:7)
标题的ViewBag非常好(我甚至说它是ViewBag的目的) - 动态不是绝对的邪恶。 “标题”是众所周知的,不太可能改变甚至在视图模板中预定义。我个人使用以下标题:
<title>@(ViewBag.Title == null ? string.Empty : ViewBag.Title + " | ")Site Name</title>
如果您担心错误输入ViewBag.Title
,可以通过创建自定义WebViewPage
使其成为强类型,但您仍然必须使用ViewBag
或HttpContext.Items
typed属性,因为在呈现IIRC期间创建了多个WebViewPage
实例。
我建议坚持使用ViewBag
,创建自己的WebViewPage
,因为这似乎有点矫枉过正 - 如果您已经拥有自定义WebViewPage
,我甚至会在其上创建单个属性只是毫无价值的并发症 - 而且来自经常过度工作的人。
答案 2 :(得分:3)
我也根本不使用ViewBag。
在_Layout.shtml的顶部...
@model <YourWebAppNameSpace>.Models.Base.EveryPageViewModel
在_Layout.shtml中......
<title>@Model.Title</title>
在你的模特中......
/// <summary>
/// Index View Model
/// </summary>
public class IndexViewViewModel : EveryPageViewModel {
}
在EveryPageViewModel中
/// <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; }
}
在您的控制器操作中
/// <summary>
/// Index
/// </summary>
/// <returns></returns>
public ActionResult Index() {
var model = new IndexViewViewModel();
model.Title = "Home";
return View(model);
}
答案 3 :(得分:2)
我喜欢创建PageTitle ActionFilter属性,而不是编辑单个ViewBags
用法:保持视图相同
<title>@ViewBag.Title</title>
对于控制器范围的页面标题:
[PageTitle("Manage Users")]
public class UsersController : Controller {
//actions here
}
对于个人观点:
public class UsersController : Controller {
[PageTitle("Edit Users")]
public ActionResult Edit(int id) {
//method here
}
}
属性代码:
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;
}
}
}
易于管理,就像魅力一样。
答案 4 :(得分:1)
就我个人而言,我认为这个案例是ViewBag
的可接受用法。它仅限于“众所周知”的财产,未来可能不会造成任何问题。最后,一切都是务实并找到尽可能快的方法。在我看来,拥有一个你需要设置标题的基类会有太多的代码值得类型安全。
答案 5 :(得分:1)
我想说只要它只是你要设置的标题,就可以使用ViewBag了。好吧,也许不仅仅是 - 最多2-3个属性。
但是如果你开始看到你在每个控制器动作中设置越来越多(常见)的属性,我会使用强类型的“ViewModelBase类”。但这只是我。
答案 6 :(得分:1)
我们更喜欢强大的标题设置..来自我们的BaseController类的一些示例。 (页面定义封装视图模态)
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);
}
答案 7 :(得分:1)
使用ViewBag.Title =“我的标题”没有任何问题;
您所做的只是使用动态属性。
问题实际上是应该“声明”信息的地方。
即,对于手头的目的而言,它最容易到达。
如果它是基于每页,那么这是正确的地方。
但是,如果页面的标题可以从模型中派生出来,那么你应该这样做。
在这种情况下,我可能会使用您使用的ViewModel的基类,并在那里创建一个PageTitle属性,其中包含从模型中的属性派生页面标题的逻辑。
所以:
<title>Model.PageTitle</title>
总之,马匹用于课程,不要害怕使用动态属性......只要你了解它们是什么以及它们做了什么。