Web Forms in ASP.NET MVC3 and Razor

Introduction to ASP.NET MVC3

ASP.NET MVC3 builds the capabilities of Web forms found in the previous versions and adds exciting new capabilities. When combined with the new Razor view engine, MVC3 allows you to create sophisticated Web forms faster than ever before with even cleaner separation between your model and your views.

MVC3 data entry forms are designed to allow you to leverage built in HTML generation methods or to design your own custom HTML that will still map to and validate against your model. This means that even if you custom build one HTML field, it will still map correctly to your server side object in the controller.

This example creates a simple ASP.NET MVC3/Razor application that allows the user to edit a boat in a web form and save it. To get started, create a new "ASP.NET MVC 3 Web Application" in Microsoft Visual Studio.NET 2010. If this option doesn't show up for you in the new project dialog, go to http://www.microsoft.com/downloads/en/details.aspx?FamilyID=a920ccee-1397-4feb-824a-2dfefee47d54 and download ASP.NET MVC3.

ASP.NET MVC3 - The Model

Our boat includes a BoatID as the key column, a captain's name, the name of the boat and the date it was christened. The purpose of the model is to define the data of your object and how it relates to other objects.

In ASP.NET MVC3 web forms you have 3 primary choices when it comes to your model.

  • Entity Framework -You can use the entity framework to generate a model that you can then customize by changing the properties or adding partial classes that add additional attributes.
  • No model - You can access the Request object in your controller and handle the form data manually.
  • Plain Old CLR Objects (POCO) - You can define your own objects with public properties to be used by your web form's model.

If you use the entity framework or plain old CLR objects, you can add validation attributes to your objects that define validation in a declarative way that can be easily validated on the client and the server.

Add the following code to the Models directory as Boat.cs:

  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Web;
  using System.ComponentModel.DataAnnotations;
  
  namespace MVC3WebForms.Models
  {
      public class Boat
      {
          public int BoatID { get; set; }
          public string CaptainName { get; set; }
          public string BoatName { get; set; }
          public DateTime DateChristened { get; set; }
      }
  }

ASP.NET MVC3 Controller

The design of the controller is to allow a single group of methods to add a new boat or to edit an existing boat. If the user loads the edit page with a valid BoatID in the URL, then you know they want to edit an existing boat. If the user follows a link that doesn't pass in a BoatID then the controller will create a new boat instead of editing an existing one.

The controller in the code example below defines 3 methods. The Index method is the default method for this controller and is mapped to the /Home path which is the default URL. The other two methods EditBoat(int BoatID) and EditBoat(Boat b) are used to display the boat create/edit page and to save the changes to the boat respectively.

EditBoat(int BoatID) is meant to load a boat from the database and present it to the user for editing if a BoatID is supplied and to create a new blank boat if the BoatID isn't supplied. MVC3 will parse URL get parameters and map them to your controller's defined arguments by name.

EditBoat(Boat b) has the HttpPost markup on it letting ASP.NET MVC know that this method should handle EditBoat actions when a post is done from a web form. This will help it differentiate between when a form is initially loaded versus when the user clicks submit on the form.

The code example below is defined in Controllers/HomeController.cs:

  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Web;
  using System.Web.Mvc;
  using MVC3WebForms.Models;
  
  namespace MVC3WebForms.Controllers
  {
      public class HomeController : Controller
      {
          public ActionResult Index()
          {
              return View();
          }
          //GET: /Home/EditBoat
          public ActionResult EditBoat(int BoatID)
          {
              Boat b = new Boat();
              if (BoatID != 0)
              {
                  //Real world: Load the boat from the database
                  //Example World: We're just setting properties.
                  b.BoatID = BoatID;
                  b.BoatName = "Boat 555";
                  b.CaptainName = "Leo Decaf";
                  b.DateChristened = new DateTime(1920, 5, 5);
              }
              else { b.BoatID = -1; }
              return View(b);
          }
  
          //POST: /Home/EditBoat
          [HttpPost]
          public ActionResult EditBoat(Boat b)
          {
              //Real World: Save the boat then return Redirect("~/Home");
              //Example World: We're going to show that we have
              //    the user's input inside of our boat object.
  Response.Write("<h1>Boat Saved!</h1>");
  Response.Write("<p>BoatID:" + b.BoatID + "</p>");
  Response.Write("<p>BoatName:" + b.BoatName + "</p>");
  Response.Write("<p>CaptainName:" + b.CaptainName + "</p>");
              return View(b);
          }
      }
  }



Web Forms in ASP.NET MVC3 and Razor

ASP.NET MVC3 - The View

The Boat example uses 2 views. The default view shows two links, one to create a new boat and one to edit an existing boat. The EditBoat view displays the web form. To define a view, right click the corresponding method name in your controller and choose "Add View".

Right at the top of our EditBoat view is the following line:

  @model MVC3WebForms.Models.Boat

This line tells Razor the data model that are binding to our view and will enable intellisense to work properly as you access the model.

On any Razor Web form, you use @using(Html.BeginForm()) to define the part of the page that defines your form. The BeginForm call can specify a specific action to target in your controller if you want to target a different route than you are currently in.

In order to provide the cleanest separation between your model and view, it is recommended to use the html helper methods to render out your fields and labels. The HTML helper methods represent a two way binding. This means when you use @Html.TextBoxFor(model => model.BoatName) a text box will be rendered with the currently bound BoatName in it and when the user saves the form, the BoatName entered in that field will be in your server side Boat object.

  • @Html.TextBoxFor - Standard textbox.
  • @Html.HiddenFor - A hidden field that stores a value but renders no visible UI element to the page.
  • @Html.DropDownListFor - A drop down list that allows the user to choose one option from a list of options.
  • @Html.CheckBoxFor - A single checkbox option.
  • @Html.ListBoxFor - A multi-select listbox bound to an array of options.
  • @Html.PasswordFor - A password field.
  • @Html.RadioButtonFor - A single radio button option.
  • @Html.TextAreaFor - Multi-Line text area.
  • @Html.DisplayFor - Generic display, will follow what is set in the UI Hints or the best option for the specific data type.
  • @Html.EditorFor - Generic editor, will follow what is set in the UI Hints or the best option for the specific data type.

If you want to manually define one or more fields on your form, you can do so simply by naming your HTML widget the same as the property you want to set on the form. In the code example below, the CaptainName field is manually defined as an HTML form field named "CaptainName" and will be mapped to the corresponding field on the Boat object in the controller.

  @model MVC3WebForms.Models.Boat
  @{
      Layout = null;
  }
  <!DOCTYPE html>
  <html>
  <head>
  <link rel="Stylesheet" href="@Url.Content("~/Content/Site.css")" type="text/css" />
  <title>Edit Boat</title>
  </head>
  <body>
      <div>
  @using (Html.BeginForm())
  {
      
      <fieldset>
      
      @Html.HiddenFor(model => model.BoatID)
  
      <div class="editor-label">
          @Html.LabelFor(model => model.BoatName) 
      </div>
      <div class="editor-field">
          @Html.TextBoxFor(model => model.BoatName)
      </div>
  
      <div class="editor-label">
          Captain's Name
      </div>
      <div class="editor-field">
          <input type="text" name="CaptainName" value="@Model.CaptainName" />
      </div>
  
      <div class="editor-label">
          @Html.LabelFor(model => model.DateChristened)
      </div>
      <div class="editor-field">
          @Html.TextBoxFor(model => model.DateChristened)
      </div>
      
      <input type="submit" value="Save"></fieldset>
  }
      </div>
  </body>
  </html>

Pre-Defined CSS in ASP.NET MVC3 Web Forms

Even in "blank" MVC 3 web applications there are CSS styles defined by default in the Site.css file. If at all possible, it is recommended to use these style names as they are leveraged by many of the code generation templates.

The two main ones worth using are the editor-label and the editor-field styles. You can set these styles on a DIV or SPAN containing the corresponding elements and customize the look and feel of these elements in Site.css.

Conclusion

ASP.NET MVC3 makes it easier and faster than ever before to create highly efficient web forms with a clean separation between the model definition and the HTML views. MVC 3 provides the convenience of form building functions with the power of being able to manually custom define the HTML without having to give up the server side model mapping.





Related Articles

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • By providing developers with the right tools to detect, understand, and fix problems early, your business can simplify software development, shorten development lifecycles, and improve the quality of software code. The end result is increased innovation, secure applications, and a faster time to market — all at a lower cost.

  • Bonita BPM 7 is here! And for you, an in-depth tour of its innovation. In this webinar, we'll guide you through the brand-new features of this release and demonstrate them live. You will: Discover how business application implementation and maintenance is now even easier, with decoupling of process logic, business data and user interface Learn how to create "living applications" for business processes which present business data in custom views We recommend that you watch the half-hour recording of our …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date