Saturday 9 February 2013

ASP.NET MVC Views


View: The whole purpose of views is to allow rendering parts of domain model as a user interface. A view is a standard (X)HTML document that can contain scripts. We can use scripts to add dynamic content to a view. Razor is the view engine that was introduced with MVC 3. The views are translated and compiled by Razor so that we can include code fragments so easily. We can add dynamic content in view in following ways:

Inline code
Self-contained pieces of view logic.
HTML helper methods
MVC Framework includes number of HTML helper methods, any method that returns an MvcHtmlString object can be an HTML helper method.
Partial views
Reusable portion of view markup shared between views.
Child actions
Use for creating reusable UI controls or widgets that need to contain
business logic. When we use as a child action, it invokes an action method, renders a view, and injects the result into the response stream.

Inline Code:  Can use inline code start with @ prefix symbol or we can write multiple statement inside @{} block. 

Example:
@model Models.DemoViewModel
@using Data.Utility

@{
ViewBag.Title = "Index";
}

@foreach (string emp in Model.Employees) {
<span><b>@emp.name</b></span>
}

The @model type of string is used as the type parameter for the generated class

Html Helpers: HTML helpers are used to generate reusable block of HTML, it’s an easy way to render HTML in a view.

The following list shows some of the built in HTML helpers:

Helper
Description
BeginForm
Marks the start of a form and links to the action method that renders the form.
@Html.BeginForm("actionName", "controllerName")
CheckBox
Renders a check box.
@Html.CheckBox("myCheckbox", false)
DropDownList
Renders a drop-down list.
@Html.DropDownList("dropDown")
Hidden
Embeds information in the form that is not rendered for the user to see.
@Html.Hidden("myHidden", "val")
ListBox
Renders a list box.
@Html.ListBox("listBox")
Password
Renders a text box for entering a password.
RadioButton
Renders a radio button
@Html.RadioButton("favColor", "Blue", true)
TextArea
Renders a text area (multi-line text box).
@Html.TextArea("address")
ActionLink
Links to an action method.
@Html.ActionLink("Home", "Index", "Home")
TextBox
Renders a text box.
@Html.TextBox("name")

Creating HTML with BeginForm and a using Statement:
The default overload of the BeginForm helper takes no parameters and generates a URL that refers back to the current action—that is, the one that processed the current request. This is a common pattern in MVC applications, where the same URL is used to handle GET and POST requests. Typically, a GET request displays the HTML form, and the POST request validates and processed the submitted data.

@using (Html.BeginForm("Index", "Home")) {
}

Note: BeginForm method creates an instance of the MvcForm class, which implements the IDisposable interface. When we exit the using block, the .NET Framework calls the Dispose method on the MvcForm object, which causes it to create the closing form tag so that no need to use the EndForm helper

Note: Notice that the checkbox helper (Html.CheckBox) renders two input elements. It renders a checkbox and then a hidden input element of the same name. This is because browsers don’t submit a value for checkboxes when they are not selected. Having the hidden control ensures that the MVC Framework will get a value from the hidden field when this happens.

The following list shows some of the built in strongly type HTML helpers. These helpers can be used only with strongly typed views.

Helper
Description
TextBoxFor
@Html.TextBoxFor(m => m.Name)
TextAreaFor
@Html.TextAreaFor(m => m.Address)
CheckBoxFor
@Html.CheckBoxFor(m => m.ContectMe)
RadioButtonFor
@Html.RadioButtonFor(m => m.Sex, "M")
DropDownListFor
@Html.DropDownListFor(m => m.Country, new SelectList(new [ ] {"UK", "US"}))

The strongly typed input helpers work on lambda expressions. The value that is passed to the expression is the view model object, and we can select the field or property that will be used to set the value attribute.

Html attribute: Most of the HTML helper methods let us add attribute in HTML. Most common attribute is class to add style

@Html.TextBoxFor(m => m.Name, new { @class = "ccs-class", maxlength = "10" })

Inline HTML Helper: The most direct way to create a helper is to do so in the view, using the Razor @helper tag. The @helper syntax easily creates re-usable helper methods that can encapsulate output functionality within your view templates.  They enable better reusable and readable code.

Example:
@helper ShowDiscount(){
    if(DateTime.Now.Hour <= 10)
    {
        <span style="color:orange"> Subscribe now and you will get 10% discout</span>
    }
    else
    {
        <span style="color:green"> Subscribe now and you will get 30% discout</span>
    }
}

We can use ShowDiscount() inline helper method in view like this:

@ShowDiscount()

We can also defined arguments in inline helper methods similar to regular c# methods.

External Helper Method: We can also create and external helper method to use across the views or we can extend our existing built-in helper method.
The first parameter to an external HTML helper method is an HtmlHelper object, annotated with the “this” keyword. Any other parameters we define will allow us to pass values from the view to the helper.

To create and external helper method first we need to create a class where we will define those methods.

Example:
namespace MvcViews.ExternalHtmlHelpers
{
    public static class ExternalHtmlHelpers
    {
        //MvcHtmlString : Represents an HTML-encoded string that should not be encoded again.
        public static MvcHtmlString List(this HtmlHelper html, string[] listItems)
        {
            TagBuilder tag = new TagBuilder("ul");
            foreach (string item in listItems)
            {
                TagBuilder itemTag = new TagBuilder("li");
                itemTag.SetInnerText(item);

                tag.InnerHtml += itemTag.ToString();
            }
            return new MvcHtmlString(tag.ToString());
        }

        public static MvcHtmlString TextBoxFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper,Expression<Func<TModel, TValue>> expression, bool editable)
        {
            MvcHtmlString html = default(MvcHtmlString);

            if (editable)
            {
                html = System.Web.Mvc.Html.InputExtensions.TextBoxFor(htmlHelper, expression);
            }
            else
            {
                html = System.Web.Mvc.Html.InputExtensions.TextBoxFor(htmlHelper, expression,
                    new { @class = "readOnly", @readonly = "read-only" });
            }
            return html;
        }

        public static object DisableAttributeIfTrue(this HtmlHelper html, bool condition)
        {
            if (condition)
                return new { disabled = "disabled" };
            else
                return new { };
        }
    }
}

Note: In order to use a custom external HTML helper method, we must import the namespace that contains the class in view.
@using MvcViews.ExternalHtmlHelpers

@Html.TextBoxFor(m => m.Name, false)
@Html.TextBox("MyTextBox", "MyValue", Html.DisableAttributeIfTrue(true))
@Html.List(new string[]{"a","b","c"})

Layouts and Sections: A Razor Layout page is the equivalent of an ASP.NET Master Page. It defines the structure of a Web page by using HTML markup, and defines sections that will be filled with custom content. Web pages linked to a layout will only have to complete the sections with their own HTML. By using layout pages website will have a consistent look that will also be easier to modify. It is also possible to nest Razor Layout pages.

Razor Layout pages are HTML files that define a Body and sections:
@RenderBody():The RenderBody method resides in the master page and renders content of the page that is not within any sections.

@RenderSection("SectionName"): Renders the content of the section within the given name. Sections are mandatory by default, so each page linked to the template will have to declare them.

@RenderSection("SectionName", optional:true): Renders the content of an optional section. The pages that are linked to the template can omit the definition of an optional section.

@RenderPage("~/Views/Shared/Header.cshtml"): Layout pages can also contain content that can be filled by other pages on disk. This is achieved by using the RenderPage method. This method takes either one or two parameters. The first is the physical location of the file, the second is an optional array of objects that can be passed into the page.

Example:
      Layout Page:
    <div class="page">
        <div id="header">
            <div id="title">
                @RenderPage("~/Views/Shared/Header.cshtml")
            </div>
            <div id="menucontainer">
                @RenderSection("Menu",false
          </div>
        </div>
        <div id="main">
            @RenderBody()
        </div>
        <div id="footer">
        @RenderSection("Footer",false)
        </div>
    </div>

    View Page:
            @section Menu
       {
                <li>@Html.ActionLink("MenuSection", "About", "Home")</li>
}

            @section Footer
       {
              <div>This is footer to demostrate</div>
}

_ViewStart Page: The _ViewStart file can be used to define common view code that we want to execute at the start of each View’s rendering. This is by default use to include top level layout so that all view can access the same.

Example:
@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}


Html.Partial() & Html.RenderPartial(): These two methods is used to rendering partial views and use same logic to render partial view. There fundamental difference is return type, Html.Partial() returns partial view as MvcHtmlString which buffers the content and we can keep in a variable for further use if required. Html.RenderPartial() does not return anything its render the result directly to the Response.

Considering the performance @html.RenderPartial() has fast execution than @html.Partial() due to RenderPartial() give quick response to Output and does not buffers view content.

By default view model passed as model in partial view.

Example:
@Html.Partial("_MyPartial")

@{
     Html.RenderPartial("_MyPartial");
}

Html.Action() & Html.RenderAction(): These two methods allow us to call action method from view and render output of the action in place within the view.

The return type of Html.RenderAction is void that means it directly render the responses in View where return type of Html.Action is MvcHtmlString which we can keep its render view in a variable for further use if required. So, Html.RenderAction performance is better.

Example:
public ActionResult ActionTest(string myActionPar)
{
            PartialTestModel model = new PartialTestModel();
            model.FirstName = "FirstName";
            model.LastName = "LastName";
            return PartialView("_MyPartial",model);
 }


@Html.Action("ActionTest", "Home", new { myActionPar = "Action"})

@{
     Html.RenderAction("ActionTest", "Home", new { myActionPar = "RenderAction" });
}