The Razor View Engine (Cont.) Working with ViewData, the ViewBag and the Model Accessing view data has never been simpler in ASP.NET MVC. To access the data within your view data dictionary you can simply perform the same steps as you would with any other view engine - supply the key to the dictionary to retrieve the value as shown below: @{ var name = ViewData["name"]; }
In the example above I’m retrieving the name object from the dictionary. This could be anything: a string, a complex type, or any other primitive. While there is nothing new and exciting to talk about in regards to the view data dictionary, there is a new kid on the block - the ViewBag object. The ViewBag is a dynamic object which can be used to pass data from the controller to the view in the same manner in which you have set it up with the view data dictionary. What’s nice about the ViewBag object is that because of its dynamic nature you can set and get field values and add any number of additional fields without the need of strongly-typed classes. I think it’s best to see this in action. The example below shows how I’m setting up the ViewData object in a controller. public ActionResult Foo() { ViewData["FirstName"] = "Donn"; ViewData["LastName"] = "Felker"; return View(); }
Using the Razor view engine, I can pull these values out of the view data dictionary fairly easily with the following syntax. In an inline code block: public ActionResult Magazine() { ViewData["FirstName"] = "Donn"; ViewData["LastName"] = "Felker"; return View(); }
Basic output notation: @ViewData["FirstName"] @ViewData["LastName"]
While this works, this same thing can be done a lot cleaner with the ViewBag. To utilize the ViewBag you simply set up the fields in the dynamic ViewBag object. At that point they are available to the rendering view via those same field names. To populate the ViewBag, set it up in the controller action as shown below: public ActionResult Foo() { ViewBag.FirstName = "Donn"; ViewBag.LastName = "Felker"; return View(); }
In the view, access the ViewBag fields directly. This will output the values to the screen as shown below. This is possible because of the ViewBag dynamic type. Inline code: @{ var firstName = ViewBag.FirstName; var lastName = ViewBag.LastName; }
Basic output notation: @ViewBag.FirstName @ViewBag.LastName
While it may look confusing at first, it’s a much cleaner implementation because I am not depending on string literals to be the driving factor in how my view retrieves data. You also have the option of providing multi-token statements to perform various operations within the view. One such example would be concatenating strings in the view as shown here: @{ var name = "Awesome"; } <p>@("Hello Captain " + name)</p>
Last but certainly not least is the view model object. Strongly typing your views is actually quite simple. To set up your view to become strongly typed, include the model declaration at the top of your view as shown here: @using CodeMagazine.Models @model CodeMagazine.Models.LogOnModel @{ ViewBag.Title = "Hello" + Model.UserName; }
<h2>@ViewBag.Message</h2> <p> To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>. </p>
As soon as the model type is declared at the top of the view, the view is strongly typed and you can access the members of the view model from the Model keyword as shown on the fifth line in the code above. Assume that the value of Model.UserName is “Donn.” In the code above I am setting the title of the page to say “Hello Donn” using the strongly typed model object. You can also access the model anywhere in the page using the Razor notation as shown here: Hello, @Model.UserName, how are you?
Expressions If you’re familiar with the WebForm’s view engine implementation of if blocks and loops, then fortunately you will notice that there are not too many changes in regards to expressions with Razor. If blocks are created inline within the HTML. While the implementation is not as versatile as other view engines, namely Spark, it’s still cleaner and more readable than the WebForms. A simple if block expression is shown below: @if (Model.IsLoggedIn) { <p>You're logged in!</p> } else { <p>You're not logged in.</p> }
The loop expression in Razor is much more readable and user friendly than its WebForm processor. For example, here is a for loop implementation using the WebForms view engine: <ul id="current-products"> @foreach(var item in Model.Products) {
<li> @item.Name <br/> @item.Upc <br/> <img src="@item.QrCodeUrl" border="0" /> </li> } </ul>
In this example I’m looping over a list of products in the model object of the view. I’m outputting the name, Upc and QR Code Url of the product. Notice how Razor does not require the explicit closing of Razor notation; it is smart enough to figure out where it starts and when it should stop. There is something interesting to note about how Razor renders content to the screen. When you render content from an if/else block, foreach or any other block construct you should wrap the content within HTML to better identify what is the beginning and end of the content block. For example, you might have some code that looks like this: @if (Model.Count() > 0){ <span> You've got data! </span> }
This code will output to the HTML: <span> You've got data! </span>
However, there are instances in which you do not want to wrap your markup with another tag. To alleviate this you can wrap your content in the <text> tag to escape this as shown below: @if (Model.Count() > 0){ <text> You've got data! </text> }
This code will output to the HTML: You’ve got data!
|