ASP.NET MVC 3中ViewBag.Title的替代方案

时间:2011-08-08 08:48:18

标签: asp.net-mvc-3 razor viewbag

默认情况下,ASP.NET MVC 3的新项目模板将以下内容添加到默认布局(razor中的母版页):

<title>@ViewBag.Title</title>

然后,视图必须包含以下内容以分配页面标题,例如:

@{
     ViewBag.Title = "Log On";
}

也许这只是我自己的偏好,但我发现使用ViewBag来保持标题有点不对(我想的是太多魔术字符串的味道)。所以我的问题是:对于使用ASP.NET MVC 3和razor(使用动态属性包)的人来说这是推荐的最佳实践吗?或者你选择了更强类型的东西(可能涉及自定义基类?)

8 个答案:

答案 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使其成为强类型,但您仍然必须使用ViewBagHttpContext.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>

总之,马匹用于课程,不要害怕使用动态属性......只要你了解它们是什么以及它们做了​​什么。