Alternative to ViewBag.Title in ASP.NET MVC 3

2020-05-24 22:39发布

By default the new project template for ASP.NET MVC 3 adds the following to the default layout (masterpage in razor):

<title>@ViewBag.Title</title>

The view must then contain the following to assign the title of the page, for instance:

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

Perhaps it is just my own preference but I find that using the ViewBag to hold the title a little bit wrong (I'm thinking too much magic-string flavor). So my question is: Is this the recommended best practice for people using ASP.NET MVC 3 and razor (using a dynamic property bag) or are you opting for something more strongly typed (perhaps involving a custom baseclass?)

8条回答
爱情/是我丢掉的垃圾
2楼-- · 2020-05-24 23:20

I don't think there is any thing bad with default title handling feature that ships with asp.net MVC 3, its okay to do.

I personally do this(below written) to handle title, I am not endorsing the below code or saying that its better than default functionality, its just a preference.

Master

<title>
    @RenderSection("Title");
</title>

View

@section Title
{
    write title
}

One thing i could suggest to improve default functionality

@{
    string pageTitle = @ViewBag.Title ?? "Title Not Set";
}
<title>@pageTitle</title>

So whenever you forget to add it in viewbag, the page will display title= Title Not Set

Creating a base class then making all your controllers inherit from that base-class can also be done. But I think its taking so much of pain for title.

查看更多
老娘就宠你
3楼-- · 2020-05-24 23:20

ViewBag for title is perfectly fine (I'd even say it is the purpose of having ViewBag) - dynamic is not the absolute evil. "Title" is well known, unlikely to change and even predefined in view templates. I personally use following title:

<title>@(ViewBag.Title == null ? string.Empty : ViewBag.Title + " | ")Site Name</title>

If you are worried about mistyping ViewBag.Title you can make it strong type by creating custom WebViewPage but you will still have to use ViewBag or maybe HttpContext.Items inside that strongly typed property because there are multiple instances of WebViewPage created during rendering IIRC.

I'd recommend to stick with ViewBag, creating own WebViewPage because of this seems like overkill - even creating single property on it if you already have custom WebViewPage is in my opinion just worthless complication - and that comes from person that is often overengineering things.

查看更多
神经病院院长
4楼-- · 2020-05-24 23:25

I like to create a PageTitle ActionFilter attributes rather than editing individual ViewBags

Usage: keep the view the same

<title>@ViewBag.Title</title>

For controller-wide page title:

[PageTitle("Manage Users")]
public class UsersController : Controller {
    //actions here
}

For individual views:

public class UsersController : Controller {
    [PageTitle("Edit Users")]
    public ActionResult Edit(int id) {
          //method here
    }
}

Attribute Code:

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;
        }
    }
}

Easy to manage and works like a charm.

查看更多
爷的心禁止访问
5楼-- · 2020-05-24 23:27

For me personally, I think this case is an acceptable use of ViewBag. It is limited to a "well-known" property, and it likely won't cause any problems in the future. In the end, it is all about being pragmatic and finding a way to be as quick as possible. Having a base class where you need to set the title would in my opinion be too much code to be worth the type safety.

Good luck!

查看更多
劫难
6楼-- · 2020-05-24 23:28

we prefer strong title setting.. few sample from our BaseController class. (Page defines encapsulated view modal)

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楼-- · 2020-05-24 23:30

There is nothing wrong with using ViewBag.Title = "My Title";

All you are doing is use a dynamic property.

The question is really where the information should be "declared".

Ie, where is it most accessible for the purposes at hand.

If it is on a per page basis, then that is the right place.

If, however, the title of the page can be derived from the Model, then you should do that.

In this case, I would probably use a base class for the ViewModel that you use, and create a PageTitle property there that contains the logic to derive the page title from properties in the Model.

So:

<title>Model.PageTitle</title>

In summary, horses for courses and don't be afraid of using dynamic properties... so long as you understand what they are and what they do.

查看更多
登录 后发表回答