Blaise
Blaise

Reputation: 22212

Values in the ViewBag cannot be used in HtmlHelper?

I got an HtmlHelper to spit out html for my page title and description.

public static class HeaderHelper
{
    public static MvcHtmlString StandardHeader(this HtmlHelper htmlHelper,
        string title,
        string description="")
    {            
        var tbSection= new TagBuilder("div");
        tbSection.AddCssClass("page-header");

        var tbTitle = new TagBuilder("h2") {InnerHtml = title};
        if (!string.IsNullOrEmpty(description))
        {
            var tbDescription = new TagBuilder("p") {InnerHtml = description};
            tbSection.InnerHtml = string.Concat(tbTitle, tbDescription);
        }
        else
        {
            tbSection.InnerHtml = tbTitle.ToString();
        }
        
        return MvcHtmlString.Create(tbSection.ToString());
    }
}

It works good for

@Html.StandardHeader("View Employees")

and

@Html.StandardHeader("Edit Employee","...some description...")

But when I use ViewBag values like

@Html.StandardHeader(ViewBag.Title)

or

@Html.StandardHeader(ViewBag.Title.ToString())

So the question: how can we pass in ViewBag.Title into an HtmlHelper?


Update

There is red line below my @Html.StandardHeader(...) statement.

It is a Compilation Error

Compiler Error Message: CS1973: 'System.Web.Mvc.HtmlHelper' has no applicable method named 'StandardHeader' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.

I have tried some other variation:

@{
    var test = "test";
    var title = string.Format("Welcome {0}", ViewBag.Title);
}
@Html.StandardHeader(test)   // works
@Html.StandardHeader(title)  // won't work :(

Also, I have made sure ViewBag.Title is not null.


Final Update

Just a few more comments on the solution provided.

Basically, we have to do an explicit cast.

All C# object has a .ToString() method. But not every one can be cast to a string. A ViewBag value is essentially an object, a .ToString() on which is not a cast.

As for why we have to use string instead of var to explicitly declare the variable,

string title = string.Format("Welcome {0}", ViewBag.Title);

I got a good answer in my separate SO question.

Direct quote from there.

All expressions are evaluated at runtime, with the occasional exception of some operations on compile time literals.

So: if at least one of the parameters is dynamic, the entire expression is treated as it was dynamic and evaluated on runtime.

Hope this update helps.

Upvotes: 6

Views: 11666

Answers (1)

user3559349
user3559349

Reputation:

You need to cast the ViewBag property (because ViewBag is dynamic).

@Html.StandardHeader((string)ViewBag.Title)

and in the second example

@Html.StandardHeader((string)title)

or explicitly declare the variable as a string rather that var

@{ string title = string.Format("Welcome {0}", ViewBag.Title); }
@Html.StandardHeader(title)

Upvotes: 9

Related Questions