Rendering ViewData Items Using ViewData.Eval
One of the main uses for inline code is to pull out and display data from ViewData, either by
treating it as a dictionary (e.g., <%= ViewData["message"] %>) or as a strongly typed object
(e.g., <%= Model.LastUpdateDate.Year %>). What you haven’t seen yet is ViewDataDictionary’s
Eval() method, and how you can use it to scan for a value that might be anywhere in ViewData
or Model.
Eval() is a way of searching through the whole ViewData object graph—both its dictionary
and Model object elements—using a dot-separated token syntax. For example, you might render
<%= ViewData.Eval("details.lastlogin.year") %>. Each token in the dot-separated
expression is understood as either the name of a dictionary entry, or case-insensitively as the
name of a property. Eval() recursively walks both the underlying dictionary and the Model
object, in a particular priority order, to find the first non-null value. The previous example is
capable of finding any of the following:
• ViewData["details.lastlogin.year"]
• ViewData["details"].lastlogin.year
• ViewData["details.lastlogin"].year
• ViewData["details"]["lastlogin"]["year"]
• ViewData.Model.Details.LastLogin.Year
• ViewData.Model.Details["lastlogin.year"]
These are just a few of the many possible ways it can resolve your expression. It will actually
check every possible combination of dictionary entry names and property names, firstly
on ViewData as a dictionary, and secondly on ViewData.Model, stopping when it finds a nonnull
value.
<%= Html.TextBox("mytext", "val", new { someAttribute = "someval" }) %>
The C# compiler doesn’t expect you to use C# reserved words as property names. So, if you try to render
a class attribute by passing new { class = "myCssClass" }, you’ll get a compiler error (class is a
reserved word in C#). To avoid this problem, prefix any C# reserved words with an @ symbol (e.g., write new
{ @class = "myCssClass" }). That tells the compiler not to treat it as a keyword. The @ symbol disappears
during compilation (as it’s just a hint to the compiler), so the attribute will be rendered simply as class.
Table 10-3. HTML Helpers for Rendering Links and URLs
Description Example
App-relative URL Url.Content("~/my/content.pdf")
Output: /my/content.pdf
Link to named action/controller Html.ActionLink("Hi", "About", "Home")
Output: <a href="/Home/About">Hi</a>
Link to absolute URL Html.ActionLink("Hi", "About", "Home", "https",
"www.example.com", "anchor", new{}, null)
Output: <a href="https://www.example.com/Home/
About#anchor">Hi</a>
Raw URL for action Url.Action("About", "Home")
Output: /Home/About
Raw URL for route data Url.RouteUrl(new { controller = "c", action = "a" })
Output: /c/a
Link to arbitrary route data Html.RouteLink("Hi", new { controller = "c", action =
"a" }, null)
Output: <a href="/c/a">Hi</a>
Link to named route Html.RouteLink("Hi", "myNamedRoute", new {})
Output: <a href="/url/for/named/route">Hi</a>
In each case other than Url.Content(), you can supply an arbitrary collection of
extra routing parameters in the form of a parameter called routeValues. It can be a
RouteValueDictionary, or it can be an arbitrary object (usually anonymously typed) to be
inspected for properties and values. The framework’s outbound URL-generation facility will
CHAPTER 10 n VIEWS 335
either use those values in the URL path itself, or append them as query string values—for
example,
Html.ActionLink("Click me", "MyAction", new {controller = "Another", param = "val"})
may render the following, depending on your routing configuration:
<a href="/Another/MyAction?param=val">Click me</a>
Drop-down list Html.DropDownList("myList", new SelectList(new [] {"A", "B"}),
"Choose")
Output:
<select id="myList" name="myList">
<option value="">Choose</option>
<option>A</option>
<option>B</option>
</select>
Multiselect list Html.ListBox("myList", new MultiSelectList(new [] {"A", "B"}))
Output:
<select id="myList" multiple="multiple" name="myList">
<option>A</option>
<option>B</option>
</select>
Link as lambda expression Html.ActionLink<HomeController>(x => x.About(), "Hi")
Output: <a href="/Home/About" >Hi</a>
Mail-to link Html.Mailto("E-mail me", "[email protected]", "Subject")
Output: <a href="mailto:[email protected]?subject=Subject">
E-mail me</a>
Submit button Html.SubmitButton("submit1", "Submit now")
Output: <input id="submit1" name="submit1" type="submit"
value="Submit now" />
Submit image Html.SubmitImage("submit2", "~/folder/img.gif")
Output: <input id="submit2" name="submit2"
src="/folder/img.gif" type="image" />
URL as lambda expression Html.BuildUrlFromExpression<HomeController>(x => x.About())
Output: /Home/About
Html.BeginForm() Renders opening and closing <form> tags (see the “Rendering
Form Tags” section later in this chapter)
Html.RenderAction(), In Microsoft.Web.Mvc.dll, performs an independent internal
Html.RenderRoute() request, injecting the response into the current request’s output.
See the “Using Html.RenderAction to Create Reusable Widgets
with Application Logic” section later in this chapter)
Html.RenderPartial() Renders a partial view (see the “Using Partial Views” section later
in this chapter)
Html.ValidationMessage() Renders a validation error message for a specific model property
(see the “Validation” section in Chapter 11)
Html.ValidationSummary() Renders a summary of all validation errors recorded (see the
“Validation” section in Chapter 11)
Html.AntiForgeryToken() Attempts to block cross-site request forgery (CSRF) attacks (see
the “Preventing CSRF Using the Anti-Forgery Helpers” section in
Chapter 13)
Creating Your Own HTML Helper Methods
There’s nothing magical or sacred about the framework’s built-in helper methods. They’re just
.NET methods that return strings, so you’re free to add new ones to your application.
For example, let’s create a helper method that renders <script> tags to import JavaScript
files.Make a new static class called MyHelpers (perhaps at /Views/MyHelpers.cs):
namespace DemoProject.Views
{
public static class MyHelpers
{
private const string ScriptIncludeFormat = "<script src=\"{0}\"></script>";
public static string IncludeScript(string virtualPath)
{
string clientPath = VirtualPathUtility.ToAbsolute(virtualPath);
return string.Format(ScriptIncludeFormat, clientPath);
}
}
}
<%= DemoProject.Views.MyHelpers.IncludeScript("~/Scripts/SomeScript.js") %>