Alternative to ViewBag.Title in ASP.NET MVC 3
Asked Answered
M

8

26

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?)

Magistery answered 8/8, 2011 at 8:48 Comment(1)
Using the viewbag for this is great as you can declare the variable in a layout page and then specify a different title for each view that inherits from it. There's really no other way to do it without using a statically typed model.Prem
A
28

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.

Alberich answered 8/8, 2011 at 9:5 Comment(5)
Just to clarify(I was not thinking of a default controller base class, I was thinking that you could create your own derived baseclass for the view (which I think razor let's you do) and expose a PageTitle property on this class which the view can assign and the layout can render)Magistery
I like this @ViewBag.Title ?? "Default" approach. It can be moved to _ViewStart.cshtml and you can set defaults here for all shared properties.Noetic
@Magistery : suppose you created a base-class for views to handle page title, probably inside your views you would set title like this @{this.pageTitle="New Title";} , while with default functionality you could set title like @{ ViewBag.Title = "New Title";}. There is not much difference in syntax. One more benefit you get with this code ViewBag.Title="something", you can set title inside view or in controller, both will work.Alberich
Accepting this as the answer since this seems to sum of the general feel of the answers: (1) dynamic is not evil and (2) you could do some slight improvementsMagistery
Nice suggestion on using a section!Vulgarize
E
7

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.

Enschede answered 8/8, 2011 at 9:34 Comment(2)
Or just <title>@(ViewBag.Title ?? ViewBag.Title + " | ")Site Name</title> to keep it as short as possible.Acyclic
@Acyclic your suggestion doesn't work, it results in | Site Name if the Title property has not been set.Rutledge
A
3

I also do not use the ViewBag, at all.

At the top of _Layout.shtml ...

@model <YourWebAppNameSpace>.Models.Base.EveryPageViewModel

In _Layout.shtml ...

<title>@Model.Title</title>

In your Model ...

/// <summary>
/// Index View Model
/// </summary>
public class IndexViewViewModel : EveryPageViewModel {

}

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

In your controller action

    /// <summary>
    /// Index
    /// </summary>
    /// <returns></returns>
    public ActionResult Index() {
        var model = new IndexViewViewModel();
        model.Title = "Home";
        return View(model);
    }
Athletics answered 22/12, 2016 at 17:0 Comment(0)
F
2

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.

Freitas answered 20/3, 2015 at 14:13 Comment(2)
The page title should be set in the view and not the controller.Rutledge
Should it? Suppose you reuse a view for uploading different types of files? E.g. MyFiles/UploadExcel, MyFiles/UploadCsv...Freitas
D
1

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!

Daughterly answered 8/8, 2011 at 9:7 Comment(0)
N
1

I would say that as long as it's only the Title you want to set, it's ok to use the ViewBag. Well, maybe not only - at most 2-3 properties.

But if you start to see you're setting more and more (common) properties in every controller action, I would go with a strongly typed "ViewModelBase class". But it's just me.

Noetic answered 8/8, 2011 at 9:12 Comment(0)
R
1

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);
}
Rearm answered 8/8, 2011 at 9:36 Comment(0)
C
1

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.

Clog answered 8/8, 2011 at 12:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.