Share via


Exercise 1: UI Rendering Metadata in ASP.NET MVC 2

In this Exercise, you will learn how to add Metadata Attributes to your model entities, and then take advantage of them to help rendering entity instances in an MVC View. These attributes are used to construct the Model Metadata objects that will be used in the views.

The following attributes can be added to your entity to describe how it should be rendered:

  • [DisplayName] defines the name of the property that will be displayed when rendering the entity.
  • [HiddenInput] generates a hidden input field for the property. If the DisplayValue flag is set to true, it also generates a visible field containing its value; though the input field will still be hidden.
  • [UIHint] sets the TemplateHint property with the given value. This property is used to suggest which template to use when rendering this model.
  • [DataType] sets the DataTypeName property with the specified value. This property is used upon rendering, to format the data.
  • [ScaffoldColumn] sets both the ShowForEdit and ShowForDisplayed properties which defines whether the model should be displayed in editable/list or detail views respectively.
  • [ReadOnly] sets the IsReadOnly property with its value.
  • [DisplayFormat] allows defining the value of different properties which describe how to display the model. The available properties are: NullDisplayText, DataFormatString, ApplyFormatInEditMode, EditFormatString, and ConvertEmptyStringToNull

    Note:
    Most of these attributes are included in System.ComponentModel and System.ComponentModel.DataAnnotations namespaces; the exeption is HiddenInput which is included in System.Web.Mvc

Throughout this lab you will decorate your model entities with attributes to render the Activities in the Create view. Later on, you will extract this data from the view to create a Templated Helper for the Activity Class.

Task 0 – Exploring the Solution

In this task, you will explore the assets provided with this Lab in order to get a basic idea of what has to be done to implement the functionality it shows using MVC 1.0

  1. Open Microsoft Visual Studio 2010. Click Start | All Programs | Microsoft Visual Studio 2010 | Microsoft Visual Studio 2010.
  2. Open the solution file Begin.sln located under \Ex1-UIMetadata\begin\ (Choosing the folder that matches the language of your preference)
  3. The PlanMyNight solution consist of an MVC based application that demonstrate different scenarios created using the version 1.0 of the ASP.NET MVC framework.

    Figure 1

    Exploring the PlanMyNight solution (C#)

    Figure 2

    Exploring the PlanMyNight solution (Visual Basic)

  4. The Details view of the Activities controller show all the relevant information about the Activity entity. To review this file, expand the Views\Activities folder and open the Details.aspx file.
  5. Review the Details.aspx file and notice the use of Html.Encode and <label> tags to show data. Also, you should notice the specific use of the rating CSS class to show the activity current rating. To do this, expand the <div> element with the CSS items class applied.
  6. You can verify how this view is rendered by navigating directly to an activity. To do this, start a new instance of the application by pressing CTRL + F5 within Visual Studio. When the browser’s window appears, edit the address bar to navigate to https://localhost:50000/.
  7. You should search for activities and click on activity link in the search results. To do this, select OH in the State dropdown list, enter 43082 in the Zip textbox and click the Search button. When the result list appears, click on the link of the first item. The Details view will appear.

    Figure 3

    Exploring the Activity Details view

  8. The Details view also let you rate an activity which will turn the rating rendering in a 5-stars control. To do this, select a value in the Rating control at the bottom of the page and lick the Rate link.

    Figure 4

    Rating an Activity and reviewing the rating control

  9. Close the Browser.

Task 1 – Modifying Markup to Make Use New LabelFor and DisplayFor Methods

  1. ASP.NET MVC 2 introduced several-strongly typed HTML helpers in addition to the MVC 1 helpers. These methods use a lambda expression when referencing models or viewmodels which enables compile-time checking of views and better code intellisense inside views.
  2. In this task you will modify the activity details view used to display information for a selected activity and to rate the activity to make use of the new strongly-typed helper methods.
  3. Open the Details.aspx file used to render the Activity information. To do this, expand the Views\Activities folder in the PlanMyNight project and double click the Details.aspx file to open it.
  4. You will make use of the new strongly-typed helpers to replace the labels and encoded values displayed in the view. Each call to the LabelFor method will replace the <label> tags, and a call to the DisplayFor method will replace the Encode method. To do this, replace the code inside the items <div> element and replace it with the bolded code shown below.

    (Code SnippetBuilding MVC2 AppActivityDetailItems CSharp)

    <div class="items">
    <p><%=Html.LabelFor(activity=>activity.Rating) %>
    <% if(rating > 0) { %>
    <span class="rating rating_<%=rating.ToString("0.0", System.Globalization.CultureInfo.InvariantCulture).Replace(".", "_")%>"><%=rating.ToString("0.0")%></span>
    <% } else { %>
    Awaiting at least one more vote.
    <% } %>
    </p>
    <p>
    <%=Html.LabelFor(activity => activity.Street)%>
    <%=Html.DisplayFor(activity => activity.Street)%> |
    <%=Html.DisplayFor(activity => activity.City)%>,
    <%=Html.DisplayFor(activity => activity.State)%>
    <%=Html.DisplayFor(activity => activity.Zip)%>
    </p>
    <p>
    <%=Html.LabelFor(activity => activity.PhoneNumber) %>
    <%=Html.DisplayFor(activity => activity.PhoneNumber)%>
    </p>
    </div>

    (Code SnippetBuilding MVC2 AppActivityDetailItems VB)

    <div class="items">
    <p><%= Html.LabelFor(Function(activity) activity.Rating)%>
    <% If (rating > 0) Then%>
    <span class="rating rating_<%=rating.ToString("0.0", System.Globalization.CultureInfo.InvariantCulture).Replace(".", "_")%>"><%=rating.ToString("0.0")%></span>
    <% Else%>
    Awaiting at least one more vote.
    <% End If%>
    </p>
    <p>
    <%= Html.LabelFor(Function(activity) activity.Street)%>
    <%= Html.DisplayFor(Function(activity) activity.Street)%> |
    <%= Html.DisplayFor(Function(activity) activity.City)%>,
    <%= Html.DisplayFor(Function(activity) activity.State)%>
    <%= Html.DisplayFor(Function(activity) activity.Zip)%>
    </p>
    <p>
    <%= Html.LabelFor(Function(activity) activity.PhoneNumber)%>
    <%= Html.DisplayFor(Function(activity) activity.PhoneNumber)%>
    </p>
    </div>

    Note:
    One of the new features in ASP.NET MVC 2 is the support strongly-typed HTML helpers that use lambda expressions. This enables better compile-time checking of views (at build-time as opposed to runtime), and also enables better code intellisense support within view templates.

    These methods use an Html.HelperNameFor() naming convention. For example: Html.TextBoxFor(), Html.CheckBoxFor(), Html.TextAreaFor().

    In MVC 1 helper methods you should specify both the control name and the model value to render on it. New helper methods support using a lambda expression to specify both the name/id of the element, as well as the value to render for it.

    The resulting HTML rendered is the same as the MVC 1 late-bound version of the helper.

    Below is a list of strongly-typed HTML helper methods available:

    - Html.TextBoxFor()

    - Html.TextAreaFor()

    - Html.DropDownListFor()

    - Html.CheckboxFor()

    - Html.RadioButtonFor()

    - Html.ListBoxFor()

    - Html.PasswordFor()

    - Html.HiddenFor()

    - Html.LabelFor()

    - Html.EditorFor()

    - Html.DisplayFor()

    - Html.DisplayTextFor()

    - Html.ValidationMessageFor()

  5. Now, you will verify that the new approach is displaying the data as you expected. To do this, press CTRL + F5 to execute the solution without debugging.
  6. You will open the detailed information for a specific Activity to review the results of the work done. You will see that the activity information is being displayed but the labels for each field are not friendly. To do this, edit your browser’s address bar to navigate to https://localhost:50000/Activities/Details/49.

    Figure 5

    PlanMyNight Activity details

Task 2 – Adding Metadata for UI Rendering

One of the classes introduced in MVC 2 is ModelMetadata. This class in intended to provide convenient information about your model entities with the objective of enhancing the displaying and edition of them.

In this task you will create a new metadata class for including attributes for rendering the activity entity.

  1. You will create a new class to store the Activity entity metadata. This class will provide simple information of how the entity should be displayed. To do this, expand and right-click on the Model\Entities folder in the PlanMyNight project and select Add | Class…. When the Add New Item dialog appears enter ActivityMetadata.cs (C#) or ActivityMetadata.vb (Visual Basic) in the Name field.

    Figure 6

    ActivityMetadata class (C#)

    Figure 7

    ActivityMetadata class (Visual Basic)

  2. Add the following namespaces in the ActivityMetadata.cs (C#) or ActivityMetadata.vb (Visual Basic) class.using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;

    Imports System.ComponentModel
    Imports System.ComponentModel.DataAnnotations

  3. The PlanMyNight project uses ADO.NET Entity Data Model to automatically generate classes that represent entities. Manual changes applied to this classes will be lost if the associated class file is regenerated. Conveniently, entity classes are defined as partial classes which allow you to still decorate this entity classes in a file of your control by adding a new partial class definition. To do this, in the ActivityMetadata.cs (C#) or ActivityMetadata.vb (Visual Basic) class file add a partial class definition named Activity.partial class Activity
    {
    }

    Partial Class Activity
    End Class

  4. Next, you will associate the Activity entity class with another class containing its metadata by decorating it with the MetadataType atribute. This allows you to apply metadata to an unmanaged partial class with no risk of losing changes. To do this, decorate the Activity partial class with the MetadataType attribute and passing the ActivityMetadata type as the parameter.

    (Code SnippetBuilding MVC2 AppActivityPartialClass CSharp)

    [MetadataType(typeof(ActivityMetadata))]
    partial class Activity
    {
    }

    (Code SnippetBuilding MVC2 AppActivityPartialClass VB)

    <MetadataType(GetType(ActivityMetadata))>
    Partial Class Activity
    End Class

  5. The ActivityMetadata class is now associated with the Activity class and you can use the metadata attributes over its properties as if you were decorating the Activity class properties itself. Property names of the metadata class must match the property names of the entity class, but the data type is irrelevant. You will create metadata properties for several entity properties. To do this, create three object properties named Rating, PhoneNumber and Street in the ActivityMetadata class.public class ActivityMetadata
    {
    public object Rating { get; set; }

    public object PhoneNumber { get; set; }

    public object Street { get; set; }
    }

    Public Class ActivityMetadata
    Public Property Rating As Object

    Public Property PhoneNumber As Object

    Public Property Street As Object
    End Class

  6. Now that you have the properties available, they can be decorated with any metadata attribute. In this case, you will use the DisplayName attribute to control the label text generated in the Activity details view. To do this, decorate the three properties created with the DisplayName attribute as shown in the bolded code below.

    (Code SnippetBuilding MVC2 AppActivityMetadataProperties CSharp)

    public class ActivityMetadata
    {
    [DisplayName("Rating:")]
    public object Rating { get; set; }

    [DisplayName("Phone:")]
    public object PhoneNumber { get; set; }

    [DisplayName("Address:")]
    public object Street { get; set; }
    }

    (Code SnippetBuilding MVC2 AppActivityMetadataProperties VB)

    Public Class ActivityMetadata
    <DisplayName("Rating:")>
    Public Property Rating As Object

    <DisplayName("Phone:")>
    Public Property PhoneNumber As Object

    <DisplayName("Address:")>
    Public Property Street As Object
    End Class

  7. Build the solution by pressing CTRL + SHIFT + B.

Exercise 1: Verification

  1. Press CTRL+F5 to run the solution without debugging.
  2. You will open the detailed information for a specific Activity to review the results of the work done. To do this, edit your browser’s address bar to navigate to https://localhost:50000/Activities/Details/49.
  3. You should notice that the label for each field is managed by the DisplayName attribute parameter specified in the metadata class.

    Figure 8

    PlanMyNight Activity details using Metadata

  4. Close the browser.