Using Forms

You might wonder why a book targeted at professional web developers is going to spend time covering the HTML form tag. Isn't it easy to understand?

There are two reasons.

  • The form tag is powerful! Without the form tag, the Internet would be a read-only repository of boring documentation. You wouldn't be able to search the Web, and you wouldn't be able to buy anything (even this book) over the Internet. If an evil genius stole all the form tags from every website tonight, civilization would crumble by lunchtime tomorrow.
  • Many developers coming to the MVC framework have been using ASP.NET WebForms. WebForms don't expose the full power of the form tag (you could say WebForms manages and exploits the form tag for its own purposes). It's easy to excuse the WebForms developer who forgets what the form tag is capable of—such as the ability to create an HTTP GET request.

The Action and the Method

A form is a container for input elements: buttons, checkboxes, text inputs, and more. It's the input elements in a form that enable a user to enter information into a page and submit information to a server. But what server? And how does the information get to the server? The answers to these questions are in the two most important attributes of a form tag: the action and the method attributes.

The action attribute tells a web browser where to send the information, so naturally the action contains a URL. The URL can be relative, or in cases where you want to send information to a different application or a different server, the action URL can also be an absolute URL. The following form tag will send a search term (the input named q) to the Bing search page from any application:

<form action="http://www.bing.com/search">
    <input name="q" type="text" />
    <input type="submit" value"Search!" />
</form>

The form tag in the preceding code snippet does not include a method attribute. The method attribute tells the browser whether to use an HTTP POST or HTTP GET when sending the information. You might think the default method for a form is HTTP POST. After all, you regularly POST forms to update your profile, submit a credit card purchase, and leave comments on the funny animal videos on YouTube. However, the default method value is “get,” so by default a form sends an HTPT GET request:

<form action="http://www.bing.com/search" method="get">
    <input name="q" type="text" />
    <input type="submit" value"Search!" />
</form>

When a user submits a form using an HTTP GET request, the browser takes the input names and values inside the form and puts them in the query string. In other words, the preceding form would send the browser to the following URL (assuming the user is searching for love): http://www.bing.com/search?q=love

To GET or To POST

You can also give the method attribute the value post, in which case the browser does not place the input values into the query string, but places them inside the body of the HTTP request instead. Although you can successfully send a POST request to a search engine and see the search results, an HTTP GET is preferable. Unlike the POST request, you can bookmark the GET request because all the parameters are in the URL. You can use the URLs as hyperlinks in an e-mail or a web page and preserve all the form input values.

Even more importantly, the GET verb is the right tool for the job because GET represents an idempotent, read-only operation. You can send a GET request to a server repeatedly with no ill effects, because a GET does not (or should not) change state on the server.

A POST, on the other hand, is the type of request you use to submit a credit card transaction, add an album to a shopping cart, or change a password. A POST request generally modifies state on the server, and repeating the request might produce undesirable effects (like double billing). Many browsers help a user avoid repeating a POST request (Figure 5.1 shows what happens when trying to refresh a POST request in Chrome).

Web applications generally use GET requests for reads and POST requests for writes. A request to pay for music uses POST. A request to search for music, a scenario you look at next, uses GET.

Searching for Music with a Search Form

Imagine you want to let your music store shoppers search for music from the homepage of the music store application. Just like the search engine example from earlier, you'll need a form with an action and a method. Placing the following code just below the promotion div in the Index view of the HomeController gives you the form you need:

<form action="/Home/Search" method="get">
    <input type="text" name="q" />
    <input type="submit" value="Search" />    
</form>

You can make various improvements to the preceding code, but for now, let's get the sample working from start to finish. The next step is to implement a Search method on the HomeController. The next code block makes the simplifying assumption that a user is always searching for music by album name:

public ActionResult Search(string q)
{
    var albums = storeDB.Albums
                        .Include("Artist")
                        .Where(a => a.Title.Contains(q) || q == null)
                        .Take(10);
    return View(albums);
}

Notice how the Search action expects to receive a string parameter named q. The MVC framework automatically finds this value in the query string, when the name q is present, and also finds the value in posted form values if you made your search form issue a POST instead of a GET.

The controller tells the MVC framework to render a view, and you can create a simple Search.cshtml view in the Home views folder to display the results:

@model IEnumerable<MvcMusicStore.Models.Album>

@{ ViewBag.Title = "Search"; }

<h2>Results</h2>

<table>
    <tr>
        <th>Artist</th>
        <th>Title</th>
        <th>Price</th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>@item.Artist.Name</td>
        <td>@item.Title</td>
        <td>@String.Format("{0:c}", item.Price)</td>
    </tr>
}
</table>

The result lets customers search for terms such as “led,” which produces the output shown in Figure 5.2.

The simple search scenario you worked through demonstrates how easy it is to use HTML forms with ASP.NET MVC. The web browser collects the user input from the form and sends a request to an MVC application, where the MVC runtime can automatically pass the inputs into parameters for your action methods to respond.

Of course, not all scenarios are as easy as the search form. In fact, you've simplified the search form to the point where it is brittle. If you deploy the application to a directory that is not the root of a website, or if your route definitions change, the hard-coded action value might lead the user's browser to a resource that does not exist: Remember we've hard coded “Home/Search” into the form's action attribute.

<form action="/Home/Search" method="get">
    <input type="text" name="q" />
    <input type="submit" value="Search" />    
</form>

Searching for Music by Calculating the Action Attribute Value

A better approach would be to calculate the value of the action attribute, and fortunately, there is an HTML to do the calculation for you.

@using (Html.BeginForm("Search", "Home", FormMethod.Get)) {     
    <input type="text" name="q" />
    <input type="submit" value="Search" /> 
}

The BeginForm helper asks the routing engine how to reach the Search action of the HomeController. Behind the scenes it uses the method named GetVirtualPath on the Routes property exposed by RouteTable. If you did all this without an HTML helper, you'd have to write all the following code.

@{
    var context = this.ViewContext.RequestContext;
    var values = new RouteValueDictionary{
        { "controller", "home"}, { "action", "index"}
    };
    var path = RouteTable.Routes.GetVirtualPath(context, values);
}
<form action="@path.VirtualPath" method="get">
    <input type="text" name="q" />
    <input type="submit" value="Search2" />    

</form>

The last example demonstrates the essence of HTML helpers. They are not taking away your control, but they are saving you from writing lots of code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset