You are previewing Pro ASP.NET MVC 2 Framework.
O'Reilly logo
Pro ASP.NET MVC 2 Framework

Book Description

Author Steven Sanderson has seen the ASP.NET MVC Framework mature from the start, so his experience, combined with comprehensive coverage of all the new features, including those in the official MVC development toolkit, offers the clearest understanding of how this exciting new framework can improve your coding efficiency. With this book, you'll gain invaluable up-to-date knowledge of security, deployment, and interoperability challenges.

The ASP.NET MVC 2 Framework is the latest evolution of Microsoft's ASP.NET web platform. It introduces a radically new high-productivity programming model that promotes cleaner code architecture, test-driven development, and powerful extensibility, combined with all the benefits of ASP.NET 3.5.

In this book, the core model-view-controller (MVC) architectural concepts are not simply explained or discussed in isolation, but are demonstrated in action. You'll work through an extended tutorial to create a working e-commerce web application that combines ASP.NET MVC with the latest C# language features and unit-testing best practices. By gaining this invaluable, practical experience, you'll discover MVC's strengths and weaknesses for yourself—and put your best-learned theory into practice.

Table of Contents

  1. Copyright
  2. About the Author
  3. About the Technical Reviewer
  4. Acknowledgments
  5. Introduction
    1. You Don't Need to Know ASP.NET MVC 1 Already
    2. Which Technologies Are Used in This Book
    3. Code Samples
    4. Errata
    5. Contacting the Author
  6. I. Introducing ASP.NET MVC 2
    1. 1. What's the Big Idea?
      1. 1.1. A Brief History of Web Development
        1. 1.1.1. Traditional ASP.NET Web Forms
        2. 1.1.2. What's Wrong with ASP.NET Web Forms?
      2. 1.2. Web Development Today
        1. 1.2.1. Web Standards and REST
        2. 1.2.2. Agile and Test-Driven Development
        3. 1.2.3. Ruby on Rails
      3. 1.3. Key Benefits of ASP.NET MVC
        1. 1.3.1. MVC Architecture
        2. 1.3.2. Extensibility
        3. 1.3.3. Tight Control over HTML and HTTP
        4. 1.3.4. Testability
        5. 1.3.5. Powerful Routing System
        6. 1.3.6. Built on the Best Parts of the ASP.NET Platform
        7. 1.3.7. Modern API
        8. 1.3.8. ASP.NET MVC Is Open Source
      4. 1.4. Who Should Use ASP.NET MVC?
        1. 1.4.1. Comparisons with ASP.NET Web Forms
          1. 1.4.1.1. Migrating from Web Forms to MVC
        2. 1.4.2. Comparisons with Ruby on Rails
        3. 1.4.3. Comparisons with MonoRail
      5. 1.5. What's New in ASP.NET MVC 2
      6. 1.6. Summary
    2. 2. Your First ASP.NET MVC Application
      1. 2.1. Preparing Your Workstation
      2. 2.2. Creating a New ASP.NET MVC Project
        1. 2.2.1. Adding the First Controller
        2. 2.2.2. How Does It Know to Invoke HomeController?
      3. 2.3. Rendering Web Pages
        1. 2.3.1. Creating and Rendering a View
        2. 2.3.2. Adding Dynamic Output
      4. 2.4. A Starter Application
        1. 2.4.1. The Story
        2. 2.4.2. Designing a Data Model
          1. 2.4.2.1. Adding a Model Class
        3. 2.4.3. Linking Between Actions
          1. 2.4.3.1. Introducing Strongly Typed Views
        4. 2.4.4. Building a Form
          1. 2.4.4.1. Dude, Where's My Data?
        5. 2.4.5. Handling Form Submissions
          1. 2.4.5.1. Introducing Model Binding
          2. 2.4.5.2. Rendering Arbitrary Views and Passing a Model Object to Them
        6. 2.4.6. Adding Validation
          1. 2.4.6.1. Model Binding Tells Input Controls to Redisplay User-Entered Values
          2. 2.4.6.2. Highlighting Invalid Fields
        7. 2.4.7. Finishing Off
      5. 2.5. Summary
    3. 3. Prerequisites
      1. 3.1. Understanding MVC Architecture
        1. 3.1.1. The Smart UI (Anti-Pattern)
        2. 3.1.2. Separating Out the Domain Model
          1. 3.1.2.1. Model-View Architecture
        3. 3.1.3. Three-Tier Architecture
        4. 3.1.4. MVC Architecture
          1. 3.1.4.1. Implementation in ASP.NET MVC
          2. 3.1.4.2. History and Benefits
        5. 3.1.5. Variations on MVC
          1. 3.1.5.1. Where's the Data Access Code?
          2. 3.1.5.2. Putting Domain Logic Directly into Controllers
          3. 3.1.5.3. Model-View-Presenter
          4. 3.1.5.4. Model-View-View Model
      2. 3.2. Domain Modeling
        1. 3.2.1. An Example Domain Model
        2. 3.2.2. Ubiquitous Language
        3. 3.2.3. Aggregates and Simplification
          1. 3.2.3.1. Is It Worth Defining Aggregates?
        4. 3.2.4. Keeping Data Access Code in Repositories
        5. 3.2.5. Using LINQ to SQL
          1. 3.2.5.1. Implementing the Auctions Domain Model
          2. 3.2.5.2. Implementing the Auction Repositories
      3. 3.3. Building Loosely Coupled Components
        1. 3.3.1. Taking a Balanced Approach
        2. 3.3.2. Using Dependency Injection
          1. 3.3.2.1. An MVC-Specific Example
        3. 3.3.3. Using a DI Container
          1. 3.3.3.1. Meet Ninject
      4. 3.4. Getting Started with Automated Testing
        1. 3.4.1. Understanding Unit Testing
          1. 3.4.1.1. How DI Supports Unit Testing
          2. 3.4.1.2. TDD and the Red-Green-Refactor Workflow
          3. 3.4.1.3. To Unit Test or Not to Unit Test
        2. 3.4.2. Understanding Integration Testing
          1. 3.4.2.1. BDD and the Given-When-Then Model
          2. 3.4.2.2. Why This Book Demonstrates Unit Testing Rather Than Integration Testing
      5. 3.5. C# 3 Language Features
        1. 3.5.1. The Design Goal: Language-Integrated Query
        2. 3.5.2. Extension Methods
        3. 3.5.3. Lambda Methods
        4. 3.5.4. Generic Type Inference
        5. 3.5.5. Automatic Properties
        6. 3.5.6. Object and Collection Initializers
        7. 3.5.7. Type Inference
        8. 3.5.8. Anonymous Types
          1. 3.5.8.1. Putting It All Together
          2. 3.5.8.2. Deferred Execution
        9. 3.5.9. Using LINQ to Objects
        10. 3.5.10. Lambda Expressions
        11. 3.5.11. IQueryable<T> and LINQ to SQL
          1. 3.5.11.1. LINQ to Everything
      6. 3.6. Summary
    4. 4. SportsStore: A Real Application
      1. 4.1. Getting Started
        1. 4.1.1. Creating Your Solutions and Projects
      2. 4.2. Starting Your Domain Model
        1. 4.2.1. Creating an Abstract Repository
        2. 4.2.2. Making a Fake Repository
      3. 4.3. Displaying a List of Products
        1. 4.3.1. Adding the First Controller
        2. 4.3.2. Setting Up the Default Route
        3. 4.3.3. Adding the First View
      4. 4.4. Connecting to a Database
        1. 4.4.1. Defining the Database Schema
        2. 4.4.2. Setting Up LINQ to SQL
        3. 4.4.3. Creating a Real Repository
      5. 4.5. Setting Up DI
        1. 4.5.1. Creating a Custom Controller Factory
        2. 4.5.2. Using Your DI Container
      6. 4.6. Creating Unit Tests
      7. 4.7. Configuring a Custom URL Schema
        1. 4.7.1. Assigning a Default Parameter Value
        2. 4.7.2. Displaying Page Links
          1. 4.7.2.1. Making the HTML Helper Method Visible to All View Pages
          2. 4.7.2.2. Supplying a Page Number to the View
        3. 4.7.3. Improving the URLs
      8. 4.8. Styling It Up
        1. 4.8.1. Defining Page Layout in the Master Page
        2. 4.8.2. Adding CSS Rules
        3. 4.8.3. Creating a Partial View
      9. 4.9. Summary
    5. 5. SportsStore: Navigation and Shopping Cart
      1. 5.1. Adding Navigation Controls
        1. 5.1.1. Filtering the Product List
          1. 5.1.1.1. Implementing the Category Filter
        2. 5.1.2. Defining a URL Schema for Categories
        3. 5.1.3. Building a Category Navigation Menu
          1. 5.1.3.1. Creating the Navigation Controller
          2. 5.1.3.2. Selecting and Rendering a List of Category Links
            1. 5.1.3.2.1. Rendering a Partial View Directly from the Menu Action
          3. 5.1.3.3. Highlighting the Current Category
      2. 5.2. Building the Shopping Cart
        1. 5.2.1. Defining the Cart Entity
        2. 5.2.2. Adding "Add to Cart" Buttons
          1. 5.2.2.1. Multiple <form> Tags
        3. 5.2.3. Giving Each Visitor a Separate Shopping Cart
          1. 5.2.3.1. ASP.NET MVC Offers a Tidier Way of Working with Session Storage
          2. 5.2.3.2. Creating a Custom Model Binder
        4. 5.2.4. Creating CartController
          1. 5.2.4.1. Implementing AddToCart and RemoveFromCart
        5. 5.2.5. Displaying the Cart
        6. 5.2.6. Removing Items from the Cart
        7. 5.2.7. Displaying a Cart Summary in the Title Bar
      3. 5.3. Submitting Orders
        1. 5.3.1. Enhancing the Domain Model
        2. 5.3.2. Adding the "Check Out Now" Button
        3. 5.3.3. Prompting the Customer for Shipping Details
        4. 5.3.4. Defining an Order Submitter DI Component
        5. 5.3.5. Completing CartController
          1. 5.3.5.1. Adding a Fake Order Submitter
          2. 5.3.5.2. Displaying Validation Errors
          3. 5.3.5.3. Displaying a "Thanks for Your Order" Screen
        6. 5.3.6. Implementing EmailOrderSubmitter
      4. 5.4. Summary
    6. 6. SportsStore: Administration and Final Enhancements
      1. 6.1. Adding Catalog Management
        1. 6.1.1. Creating AdminController: A Place for the CRUD Features
        2. 6.1.2. Rendering a Grid of Products in the Repository
          1. 6.1.2.1. Implementing the List View
        3. 6.1.3. Building a Product Editor
          1. 6.1.3.1. Creating a Product Editor UI
          2. 6.1.3.2. Handling Edit Submissions
            1. 6.1.3.2.1. Displaying a Confirmation Message
          3. 6.1.3.3. Adding Validation
          4. 6.1.3.4. Enabling Client-Side Validation
        4. 6.1.4. Creating New Products
        5. 6.1.5. Deleting Products
      2. 6.2. Securing the Administration Features
        1. 6.2.1. Setting Up Forms Authentication
        2. 6.2.2. Using a Filter to Enforce Authentication
        3. 6.2.3. Displaying a Login Prompt
      3. 6.3. Image Uploads
        1. 6.3.1. Preparing the Domain Model and Database
        2. 6.3.2. Accepting File Uploads
          1. 6.3.2.1. A Little-Known Fact About HTML Forms
          2. 6.3.2.2. Saving the Uploaded Image to the Database
          3. 6.3.2.3. Handling Form Posts That Don't Include an Image
            1. 6.3.2.3.1. An Alternative: Serializing Data into Hidden Form Fields
        3. 6.3.3. Displaying Product Images
      4. 6.4. Summary
  7. II. ASP.NET MVC in Detail
    1. 7. Overview of ASP.NET MVC Projects
      1. 7.1. Developing MVC Applications in Visual Studio
        1. 7.1.1. Naming Conventions
        2. 7.1.2. The Initial Application Skeleton
        3. 7.1.3. Debugging MVC Applications and Unit Tests
          1. 7.1.3.1. Launching the Visual Studio Debugger
          2. 7.1.3.2. Attaching the Debugger to IIS
          3. 7.1.3.3. Attaching the Debugger to a Test Runner (e.g., NUnit GUI)
          4. 7.1.3.4. Remote Debugging
        4. 7.1.4. Using the Debugger
        5. 7.1.5. Stepping into the .NET Framework Source Code
        6. 7.1.6. Stepping into the ASP.NET MVC Framework Source Code
      2. 7.2. The Request Processing Pipeline
        1. 7.2.1. Stage 1: IIS
        2. 7.2.2. Stage 2: Core Routing
          1. 7.2.2.1. Routing Configurations
        3. 7.2.3. Stage 3: Controllers and Actions
          1. 7.2.3.1. Finding and Invoking Controllers
          2. 7.2.3.2. What Controllers Must Do
          3. 7.2.3.3. What Controllers Normally Do
        4. 7.2.4. Stage 4: Action Results and Views
          1. 7.2.4.1. Rendering a View
      3. 7.3. Summary
    2. 8. URLs and Routing
      1. 8.1. Putting the Programmer Back in Control
        1. 8.1.1. About Routing and Its .NET Assemblies
      2. 8.2. Setting Up Routes
        1. 8.2.1. Understanding the Routing Mechanism
          1. 8.2.1.1. The Main Characters: RouteBase, Route, and RouteCollection
          2. 8.2.1.2. How Routing Fits into the Request Processing Pipeline
          3. 8.2.1.3. The Order of Your Route Entries Is Important
        2. 8.2.2. Adding a Route Entry
          1. 8.2.2.1. URL Patterns Match the Path Portion of a URL
          2. 8.2.2.2. Meet RouteValueDictionary
          3. 8.2.2.3. Take a Shortcut with MapRoute()
        3. 8.2.3. Using Parameters
          1. 8.2.3.1. Receiving Parameter Values in Action Methods
        4. 8.2.4. Using Defaults
          1. 8.2.4.1. Creating Optional Parameters with No Default Value
        5. 8.2.5. Using Constraints
          1. 8.2.5.1. Matching Against Regular Expressions
          2. 8.2.5.2. Matching HTTP Methods
          3. 8.2.5.3. Matching Custom Constraints
        6. 8.2.6. Prioritizing Controllers by Namespace
        7. 8.2.7. Accepting a Variable-Length List of Parameters
        8. 8.2.8. Matching Files on the Server's Hard Disk
          1. 8.2.8.1. Using the RouteExistingFiles Flag
        9. 8.2.9. Using IgnoreRoute to Bypass the Routing System
      3. 8.3. Generating Outgoing URLs
        1. 8.3.1. Generating Hyperlinks with Html.ActionLink()
          1. 8.3.1.1. Passing Extra Parameters
          2. 8.3.1.2. How Parameter Defaults Are Handled
          3. 8.3.1.3. Generating Fully Qualified Absolute URLs
        2. 8.3.2. Generating Links and URLs from Pure Routing Data
        3. 8.3.3. Performing Redirections to Generated URLs
        4. 8.3.4. Understanding the Outbound URL-Matching Algorithm
        5. 8.3.5. Generating Hyperlinks with Html.ActionLink<T> and Lambda Expressions
        6. 8.3.6. Working with Named Routes
          1. 8.3.6.1. Why You Might Not Want to Use Named Routes
      4. 8.4. Working with Areas
        1. 8.4.1. Setting Up Areas
        2. 8.4.2. Routing and URL Generation with Areas
          1. 8.4.2.1. Linking to an Action in the Same Area
          2. 8.4.2.2. Linking to an Action in a Different Area
          3. 8.4.2.3. Linking to an Action in the Root Area
          4. 8.4.2.4. Areas and Explicitly Named Routes
        3. 8.4.3. Areas and the Ambiguous Controller Problem
        4. 8.4.4. Areas Summary
      5. 8.5. Unit Testing Your Routes
        1. 8.5.1. Testing Inbound URL Routing
          1. 8.5.1.1. Using Test Doubles
          2. 8.5.1.2. Using a Mocking Framework (Moq)
        2. 8.5.2. Testing Outbound URL Generation
          1. 8.5.2.1. Unit Testing Area Routes
      6. 8.6. Further Customization
        1. 8.6.1. Implementing a Custom RouteBase Entry
        2. 8.6.2. Implementing a Custom Route Handler
      7. 8.7. URL Schema Best Practices
        1. 8.7.1. Make Your URLs Clean and Human-Friendly
        2. 8.7.2. Follow HTTP Conventions
          1. 8.7.2.1. GET and POST: Pick the Right One
          2. 8.7.2.2. On Query Strings
          3. 8.7.2.3. Use the Correct Type of HTTP Redirection
        3. 8.7.3. SEO
      8. 8.8. Summary
    3. 9. Controllers and Actions
      1. 9.1. An Overview
        1. 9.1.1. Comparisons with ASP.NET Web Forms
        2. 9.1.2. All Controllers Implement IController
        3. 9.1.3. The Controller Base Class
      2. 9.2. Receiving Input
        1. 9.2.1. Getting Data from Context Objects
        2. 9.2.2. Using Action Method Parameters
          1. 9.2.2.1. Parameters Objects Are Instantiated Using Value Providers and Model Binders
          2. 9.2.2.2. Optional and Compulsory Parameters
          3. 9.2.2.3. Specifying Default Parameter Values
          4. 9.2.2.4. Parameters You Can't Bind To
        3. 9.2.3. Invoking Model Binding Manually in an Action Method
      3. 9.3. Producing Output
        1. 9.3.1. Understanding the ActionResult Concept
        2. 9.3.2. Returning HTML by Rendering a View
          1. 9.3.2.1. Rendering a View by Path
          2. 9.3.2.2. Passing a ViewData Dictionary and a Model Object
            1. 9.3.2.2.1. Treating ViewData As a Loosely Typed Dictionary
            2. 9.3.2.2.2. Sending a Strongly Typed Object in ViewData.Model
            3. 9.3.2.2.3. Combining Both Approaches
            4. 9.3.2.2.4. Passing a Dynamic Object As ViewData.Model
        3. 9.3.3. Performing Redirections
          1. 9.3.3.1. Redirecting to a Different Action Method
          2. 9.3.3.2. Redirecting to a Different URL
          3. 9.3.3.3. Using TempData to Preserve Data Across a Redirection
            1. 9.3.3.3.1. Where TempData Stores Its Data
            2. 9.3.3.3.2. Controlling the Lifetime of TempData Items
        4. 9.3.4. Returning Textual Data
          1. 9.3.4.1. Generating an RSS Feed
        5. 9.3.5. Returning JSON Data
        6. 9.3.6. Returning JavaScript Commands
        7. 9.3.7. Returning Files and Binary Data
          1. 9.3.7.1. Sending a File Directly from Disk
          2. 9.3.7.2. Sending the Contents of a Byte Array
          3. 9.3.7.3. Sending the Contents of a Stream
        8. 9.3.8. Creating a Custom Action Result Type
          1. 9.3.8.1. Example: Watermarking an Image (and the Concept of Unit Testability Seams)
      4. 9.4. Unit Testing Controllers and Actions
        1. 9.4.1. How to Arrange, Act, and Assert
        2. 9.4.2. Testing a Choice of View and ViewData
          1. 9.4.2.1. Testing ViewData Values
        3. 9.4.3. Testing Redirections
        4. 9.4.4. More Comments About Unit Testing
        5. 9.4.5. Mocking Context Objects
        6. 9.4.6. Reducing the Pain of Mocking
          1. 9.4.6.1. Method 1: Make a Reusable Helper That Sets Up a Standard Mock Context
          2. 9.4.6.2. Method 2: Access Dependencies Through Virtual Properties
          3. 9.4.6.3. Method 3: Receive Dependencies Using Model Binding
          4. 9.4.6.4. Method 4: Turn Your Dependencies into DI Components
          5. 9.4.6.5. Method 5: Factor Out Complexity and Don't Unit Test Controllers
      5. 9.5. Summary
    4. 10. Controller Extensibility
      1. 10.1. Using Filters to Attach Reusable Behaviors
        1. 10.1.1. Introducing the Four Basic Types of Filter
        2. 10.1.2. Applying Filters to Controllers and Action Methods
        3. 10.1.3. Creating Action Filters and Result Filters
          1. 10.1.3.1. Controlling the Order of Execution
          2. 10.1.3.2. Filters on Actions Can Override Filters on Controllers
          3. 10.1.3.3. Using the Controller Itself As a Filter
        4. 10.1.4. Creating and Using Authorization Filters
          1. 10.1.4.1. How Authorization Filters Interact with Output Caching
          2. 10.1.4.2. Creating a Custom Authorization Filter
        5. 10.1.5. Creating and Using Exception Filters
          1. 10.1.5.1. Using HandleErrorAttribute
          2. 10.1.5.2. Creating a Custom Exception Filter
        6. 10.1.6. Bubbling Exceptions Through Action and Result Filters
        7. 10.1.7. The [OutputCache] Action Filter
        8. 10.1.8. The [RequireHttps] Filter
        9. 10.1.9. Other Built-In Filter Types
      2. 10.2. Controllers As Part of the Request Processing Pipeline
        1. 10.2.1. Working with DefaultControllerFactory
          1. 10.2.1.1. Prioritizing Namespaces Globally Using DefaultNamespaces
          2. 10.2.1.2. Prioritizing Namespaces on Individual Route Entries
          3. 10.2.1.3. Limiting a Route Entry to Match Controllers in a Specific Set of Namespaces
        2. 10.2.2. Creating a Custom Controller Factory
          1. 10.2.2.1. Registering a Custom Controller Factory
        3. 10.2.3. Customizing How Action Methods Are Selected and Invoked
          1. 10.2.3.1. The Real Definition of an Action
          2. 10.2.3.2. Using [ActionName] to Specify a Custom Action Name
          3. 10.2.3.3. Method Selection: Controlling Whether a C# Method Should Agree to Handle a Request
            1. 10.2.3.3.1. Creating a Custom Action Method Selector Attribute
            2. 10.2.3.3.2. Using the [NonAction] Attribute
          4. 10.2.3.4. How the Whole Method Selection Process Fits Together
          5. 10.2.3.5. Handling Unknown Actions
        4. 10.2.4. Overriding HTTP Methods to Support REST Web Services
          1. 10.2.4.1. Submitting a Plain HTML Form with an Overridden HTTP Method
          2. 10.2.4.2. How HTTP Method Overriding Works
      3. 10.3. Boosting Server Capacity with Asynchronous Controllers
        1. 10.3.1. Introducing Asynchronous Requests
        2. 10.3.2. Using Asynchronous Controllers
          1. 10.3.2.1. Turning a Synchronous Action into an Asynchronous Action
          2. 10.3.2.2. Passing Parameters to the Completion Method
          3. 10.3.2.3. Controlling and Handling Timeouts
          4. 10.3.2.4. Using Finish() to Abort All Remaining Asynchronous Operations
          5. 10.3.2.5. Using Sync() to Transition Back to the Original HTTP Context
        3. 10.3.3. Adding Asynchronous Methods to Domain Classes
        4. 10.3.4. Choosing When to Use Asynchronous Controllers
          1. 10.3.4.1. Measuring the Effects of Asynchronous Controllers
          2. 10.3.4.2. Ensuring Your Server Is Configured to Benefit from Asynchronous Requests
      4. 10.4. Summary
    5. 11. Views
      1. 11.1. How Views Fit into ASP.NET MVC
        1. 11.1.1. The Web Forms View Engine
        2. 11.1.2. View Engines Are Replaceable
      2. 11.2. Web Forms View Engine Basics
        1. 11.2.1. Adding Content to a View
        2. 11.2.2. Five Ways to Add Dynamic Content to a View
      3. 11.3. Using Inline Code
        1. 11.3.1. Why Inline Code Is a Good Thing in MVC Views
      4. 11.4. Understanding How MVC Views Actually Work
        1. 11.4.1. Understanding How ASPX Pages Are Compiled
          1. 11.4.1.1. The Code-Behind Model
        2. 11.4.2. How Automatic HTML Encoding Works
          1. 11.4.2.1. How ASP.NET 4 Automatically Skips Encoding When Rendering HTML Helpers
          2. 11.4.2.2. Introducing the <%: ... %> Syntax
          3. 11.4.2.3. Working with MvcHtmlString
          4. 11.4.2.4. Using Custom Encoding Logic (Applies to .NET 4 Only)
        3. 11.4.3. Understanding ViewData
        4. 11.4.4. Extracting ViewData Items Using ViewData.Eval
      5. 11.5. Using HTML Helper Methods
        1. 11.5.1. The Framework's Built-In Helper Methods
          1. 11.5.1.1. Rendering Input Controls
            1. 11.5.1.1.1. Using Strongly Typed Input Controls
            2. 11.5.1.1.2. How Input Controls Get Their Values
            3. 11.5.1.1.3. Adding Arbitrary Tag Attributes
            4. 11.5.1.1.4. A Note About HTML Encoding
          2. 11.5.1.2. Rendering Links and URLs
          3. 11.5.1.3. Performing HTML and HTML Attribute Encoding
          4. 11.5.1.4. Rendering Drop-Down and Multiselect Lists
          5. 11.5.1.5. Bonus Helper Methods in Microsoft.Web.Mvc.dll
          6. 11.5.1.6. Other HTML Helpers
          7. 11.5.1.7. Rendering Form Tags
            1. 11.5.1.7.1. Forms That Post Back to the Same URL
            2. 11.5.1.7.2. Using Html.BeginForm<T>
        2. 11.5.2. Creating Your Own HTML Helper Methods
      6. 11.6. Using Partial Views
        1. 11.6.1. Creating and Rendering a Partial View
          1. 11.6.1.1. Rendering a Partial Directly to the Response Stream
          2. 11.6.1.2. Passing ViewData to a Partial View
          3. 11.6.1.3. Passing an Explicit Model Object to a Partial View
            1. 11.6.1.3.1. Rendering a Partial View for Each Item in a Collection
        2. 11.6.2. Rendering a Partial View Using Server Tags
          1. 11.6.2.1. Passing ViewData to the Control
          2. 11.6.2.2. Passing an Explicit Model Object to the Control
      7. 11.7. Summary
    6. 12. Models and Data Entry
      1. 12.1. How It All Fits Together
      2. 12.2. Templated View Helpers
        1. 12.2.1. Displaying and Editing Models Using Templated View Helpers
          1. 12.2.1.1. Using Model Metadata to Influence Templated View Helpers
          2. 12.2.1.2. Rendering Editors for Individual Properties
          3. 12.2.1.3. Rendering Labels for Individual Properties
          4. 12.2.1.4. The Built-in Editor Templates
            1. 12.2.1.4.1. Scaffolding Is Not Recursive
          5. 12.2.1.5. Displaying Models Using Templated View Helpers
        2. 12.2.2. Using Partial Views to Define Custom Templates
          1. 12.2.2.1. Creating a Custom Editor Template
          2. 12.2.2.2. Respecting Formatting Metadata and Inheriting from ViewTemplateUserControl<T>
          3. 12.2.2.3. Passing Additional View Data to Custom Templates
          4. 12.2.2.4. Working with HTML Field Prefixes and the TemplateInfo Context
      3. 12.3. Model Metadata
        1. 12.3.1. Working with Data Annotations
        2. 12.3.2. Creating a Custom Metadata Provider
          1. 12.3.2.1. The Full Set of Metadata Options
        3. 12.3.3. Consuming Model Metadata in Custom HTML Helpers
        4. 12.3.4. Using [MetadataType] to Define Metadata on a Buddy Class
      4. 12.4. Model Binding
        1. 12.4.1. Model-Binding to Action Method Parameters
        2. 12.4.2. Model-Binding to Custom Types
          1. 12.4.2.1. Specifying a Custom Prefix
          2. 12.4.2.2. Omitting a Prefix
          3. 12.4.2.3. Choosing a Subset of Properties to Bind
        3. 12.4.3. Invoking Model Binding Directly
          1. 12.4.3.1. Dealing with Model Binding Errors
        4. 12.4.4. Model-Binding to Arrays, Collections, and Dictionaries
          1. 12.4.4.1. Model-Binding Collections of Custom Types
          2. 12.4.4.2. Using Nonsequential Indexes
          3. 12.4.4.3. Model-Binding to a Dictionary
        5. 12.4.5. Creating a Custom Value Provider
        6. 12.4.6. Creating a Custom Model Binder
          1. 12.4.6.1. Configuring Which Model Binders Are Used
        7. 12.4.7. Using Model Binding to Receive File Uploads
      5. 12.5. Validation
        1. 12.5.1. Registering and Displaying Validation Errors
          1. 12.5.1.1. Using the Built-In Validation HTML Helpers
            1. 12.5.1.1.1. Controlling Where Validation Messages Appear
          2. 12.5.1.2. Distinguishing Property-Level Errors from Model-Level Errors
          3. 12.5.1.3. How the Framework Retains State After a Validation Failure
        2. 12.5.2. Performing Validation As Part of Model Binding
        3. 12.5.3. Specifying Validation Rules
          1. 12.5.3.1. Using Data Annotations Validation Attributes
            1. 12.5.3.1.1. Creating a Custom Data Annotations Validation Attribute
          2. 12.5.3.2. Using the IDataErrorInfo Interface
          3. 12.5.3.3. Creating a Custom Validation Provider
        4. 12.5.4. Invoking Validation Manually
        5. 12.5.5. Using Client-Side Validation
          1. 12.5.5.1. Using Client-Side Validation with a Validation Summary
          2. 12.5.5.2. Dynamically Highlighting Valid and Invalid Fields
          3. 12.5.5.3. Allowing Specific Buttons to Bypass Validation
          4. 12.5.5.4. How Client-Side Validation Works
          5. 12.5.5.5. Implementing Custom Client-Side Validation Logic
            1. 12.5.5.5.1. Reusing the Built-In Client-Side Validation Logic
        6. 12.5.6. Putting Your Model Layer in Charge of Validation
          1. 12.5.6.1.
            1. 12.5.6.1.1. What About Client-Side Validation?
      6. 12.6. Summary
    7. 13. User Interface Techniques
      1. 13.1. Wizards and Multistep Forms
        1. 13.1.1. Defining the Model
        2. 13.1.2. Navigation Through Multiple Steps
        3. 13.1.3. Collecting and Preserving Data
        4. 13.1.4. Completing the Wizard
        5. 13.1.5. Validation
      2. 13.2. Implementing a CAPTCHA
        1. 13.2.1. Creating an Html.Captcha() Helper
          1. 13.2.1.1. Rendering a Dynamic Image
          2. 13.2.1.2. Distorting the Text
        2. 13.2.2. Verifying the Form Submission
      3. 13.3. Using Child Actions to Create Reusable Widgets with Application Logic
        1. 13.3.1. How the Html.RenderAction Helper Invokes Child Actions
        2. 13.3.2. When It's Appropriate to Use Child Actions
        3. 13.3.3. Creating a Widget Based on a Child Action
        4. 13.3.4. Capturing a Child Action's Output As a String
        5. 13.3.5. Detecting Whether You're Inside a Child Request
        6. 13.3.6. Restricting an Action to Handle Child Requests Only
      4. 13.4. Sharing Page Layouts Using Master Pages
        1. 13.4.1. Using Widgets in MVC View Master Pages
          1. 13.4.1.1. Method 1: Have Your Controller Put a Control-Specific Data Item into ViewData
          2. 13.4.1.2. Method 2: Use an Action Filter to Put a Control-Specific Data Item into ViewData
          3. 13.4.1.3. Method 3: Use Child Actions
      5. 13.5. Implementing a Custom View Engine
        1. 13.5.1. A View Engine That Renders XML Using XSLT
          1. 13.5.1.1. Step 1: Implement IViewEngine, or Derive a Class from VirtualPathProviderViewEngine
          2. 13.5.1.2. Step 2: Implement IView
          3. 13.5.1.3. Step 3: Use It
          4. 13.5.1.4. Step 4: Register Your View Engine with the Framework
      6. 13.6. Using Alternative View Engines
        1. 13.6.1. Using the NVelocity View Engine
        2. 13.6.2. Using the Brail View Engine
        3. 13.6.3. Using the NHaml View Engine
        4. 13.6.4. Using the Spark View Engine
      7. 13.7. Summary
    8. 14. Ajax and Client Scripting
      1. 14.1. Why You Should Use a JavaScript Toolkit
      2. 14.2. ASP.NET MVC's Ajax Helpers
        1. 14.2.1. Fetching Page Content Asynchronously Using Ajax.ActionLink
          1. 14.2.1.1. Passing Options to Ajax.ActionLink
          2. 14.2.1.2. Running JavaScript Functions Before or After Asynchronous Requests
          3. 14.2.1.3. Detecting Ajax Requests
        2. 14.2.2. Submitting Forms Asynchronously Using Ajax.BeginForm
        3. 14.2.3. Invoking JavaScript Commands from an Action Method
        4. 14.2.4. Reviewing ASP.NET MVC's Ajax Helpers
      3. 14.3. Using jQuery with ASP.NET MVC
        1. 14.3.1. Referencing jQuery
          1. 14.3.1.1. Referencing jQuery on a Content Delivery Network
        2. 14.3.2. Basic jQuery Theory
          1. 14.3.2.1. Waiting for the DOM
          2. 14.3.2.2. Event Handling
          3. 14.3.2.3. Global Helpers
          4. 14.3.2.4. Unobtrusive JavaScript
        3. 14.3.3. Adding Client-Side Interactivity to an MVC View
          1. 14.3.3.1. Improvement 1: Zebra-Striping
          2. 14.3.3.2. Improvement 2: Confirm Before Deletion
          3. 14.3.3.3. Improvement 3: Hiding and Showing Sections of the Page
        4. 14.3.4. Ajax-Enabling Links and Forms
          1. 14.3.4.1. Unobtrusive JavaScript and Hijaxing
          2. 14.3.4.2. Hijaxing Links
            1. 14.3.4.2.1. Performing Partial Page Updates
            2. 14.3.4.2.2. Using live to Retain Behaviors After Partial Page Updates
          3. 14.3.4.3. Hijaxing Forms
        5. 14.3.5. Client/Server Data Transfer with JSON
          1. 14.3.5.1. A Note About JsonResult and GET Requests
        6. 14.3.6. Performing Cross-Domain JSON Requests Using JSONP
        7. 14.3.7. Fetching XML Data Using jQuery
        8. 14.3.8. Animations and Other Graphical Effects
        9. 14.3.9. jQuery UI's Prebuilt UI Widgets
          1. 14.3.9.1. Example: A Sortable List
        10. 14.3.10. Summarizing jQuery
      4. 14.4. Summary
  8. III. Delivering Successful ASP.NET MVC 2 Projects
    1. 15. Security and Vulnerability
      1. 15.1. All Input Can Be Forged
        1. 15.1.1. Forging HTTP Requests
      2. 15.2. Cross-Site Scripting and HTML Injection
        1. 15.2.1. Example XSS Vulnerability
          1. 15.2.1.1. Attack
          2. 15.2.1.2. Defense
        2. 15.2.2. ASP.NET's Request Validation Feature
          1. 15.2.2.1. Request Validation: Good or Bad?
          2. 15.2.2.2. Disabling Request Validation
          3. 15.2.2.3. Customizing Request Validation Logic
        3. 15.2.3. Filtering HTML Using the HTML Agility Pack
        4. 15.2.4. JavaScript String Encoding and XSS
      3. 15.3. Session Hijacking
        1. 15.3.1. Defense via Client IP Address Checks
        2. 15.3.2. Defense by Setting the HttpOnly Flag on Cookies
      4. 15.4. Cross-Site Request Forgery
        1. 15.4.1. Attack
        2. 15.4.2. Defense
        3. 15.4.3. Preventing CSRF Using the Anti-Forgery Helpers
      5. 15.5. SQL Injection
        1. 15.5.1. Attack
        2. 15.5.2. Defense by Encoding Inputs
        3. 15.5.3. Defense Using Parameterized Queries
        4. 15.5.4. Defense Using Object-Relational Mapping
      6. 15.6. Using the MVC Framework Securely
        1. 15.6.1. Don't Expose Action Methods Accidentally
        2. 15.6.2. Don't Allow Model Binding to Change Sensitive Properties
      7. 15.7. Summary
    2. 16. Deployment
      1. 16.1. Server Requirements
        1. 16.1.1. Requirements for Shared Hosting
      2. 16.2. Building Your Application for Production Use
        1. 16.2.1. Controlling Dynamic Page Compilation
        2. 16.2.2. Detecting Compiler Errors in Views Before Deployment
          1. 16.2.2.1. Detecting Compiler Errors in Views Only When Building in Release Mode
      3. 16.3. IIS Basics
        1. 16.3.1. Understanding Web Sites and Virtual Directories
        2. 16.3.2. Binding Web Sites to Hostnames, IP Addresses, and Ports
      4. 16.4. Deploying Your Application
        1. 16.4.1. Manually Copying Application Files to the Server
          1. 16.4.1.1. Where Should I Put My Application?
        2. 16.4.2. Bin-Deploying ASP.NET MVC 2
        3. 16.4.3. Deploying to IIS 6 on Windows Server 2003
          1. 16.4.3.1. Adding and Configuring a New MVC Web Site in IIS Manager
          2. 16.4.3.2. How IIS 6 Processes Requests
          3. 16.4.3.3. Making Extensionless URLs Work on IIS 6
            1. 16.4.3.3.1. Extensionless URLs on IIS 6 with .NET 3.5
            2. 16.4.3.3.2. Extensionless URLs on IIS 6 with .NET 4
            3. 16.4.3.3.3. Troubleshooting IIS 6 Errors
        4. 16.4.4. Deploying to IIS 7.x on Windows Server 2008/2008 R2
          1. 16.4.4.1. Installing IIS 7.x on Windows Server 2008/2008 R2
          2. 16.4.4.2. Adding and Configuring a New MVC Web Site in IIS 7.x
          3. 16.4.4.3. How IIS 7.x Processes Requests in Classic Pipeline Mode
          4. 16.4.4.4. How IIS 7.x Processes Requests in Integrated Pipeline Mode
            1. 16.4.4.4.1. How Integrated Mode Makes Extensionless URLs Easy
            2. 16.4.4.4.2. Why Extensionless URLs Work on IIS 7.x Integrated Pipeline Mode with .NET 3.5
            3. 16.4.4.4.3. Why Extensionless URLs Work in IIS 7.x Integrated Pipeline Mode with .NET 4
          5. 16.4.4.5. Further IIS 7.x Deployment Considerations
          6. 16.4.4.6. Troubleshooting IIS 7.x Errors
        5. 16.4.5. Deploying to IIS 7.5 on Windows Server 2008 R2 Core
      5. 16.5. Automating Deployments with WebDeploy and Visual Studio 2010
        1. 16.5.1. Transforming Configuration Files
        2. 16.5.2. Automating Online Deployments with One-Click Publishing
        3. 16.5.3. Automating Offline Deployments with Packaging
      6. 16.6. Summary
    3. 17. ASP.NET Platform Features
      1. 17.1. Windows Authentication
        1. 17.1.1. Preventing or Limiting Anonymous Access
      2. 17.2. Forms Authentication
        1. 17.2.1. Setting Up Forms Authentication
          1. 17.2.1.1. Handling Login Attempts
        2. 17.2.2. Using Cookieless Forms Authentication
      3. 17.3. Membership, Roles, and Profiles
        1. 17.3.1. Setting Up a Membership Provider
          1. 17.3.1.1. Setting Up SqlMembershipProvider
            1. 17.3.1.1.1. Using a SQL Server Express User Instance Database
            2. 17.3.1.1.2. Preparing Your Own Database for Membership, Roles, and Profiles
          2. 17.3.1.2. Managing Members Using the Web Administration Tool
          3. 17.3.1.3. Managing Members Using IIS 7.x's .NET Users Configuration Tool
        2. 17.3.2. Using a Membership Provider with Forms Authentication
        3. 17.3.3. Creating a Custom Membership Provider
        4. 17.3.4. Setting Up and Using Roles
          1. 17.3.4.1. Using the Built-In SqlRoleProvider
          2. 17.3.4.2. Securing Controllers and Actions by Role
          3. 17.3.4.3. Creating a Custom Roles Provider
        5. 17.3.5. Setting Up and Using Profiles
          1. 17.3.5.1. Using the Built-In SqlProfileProvider
          2. 17.3.5.2. Configuring, Reading, and Writing Profile Data
          3. 17.3.5.3. Creating a Custom Profile Provider
      4. 17.4. URL-Based Authorization
      5. 17.5. Configuration
        1. 17.5.1. Configuring Connection Strings
        2. 17.5.2. Configuring Arbitrary Key/Value Pairs
        3. 17.5.3. Defining Configuration Sections to Configure Arbitrary Data Structures
      6. 17.6. Data Caching
        1. 17.6.1. Reading and Writing Cache Data
        2. 17.6.2. Using Advanced Cache Features
      7. 17.7. Site Maps
        1. 17.7.1. Setting Up and Using Site Maps
        2. 17.7.2. Creating a Custom Navigation Control with the Site Maps API
        3. 17.7.3. Generating Site Map URLs from Routing Data
          1. 17.7.3.1. Using Security Trimming
      8. 17.8. Internationalization
        1. 17.8.1. Setting Up Localization
        2. 17.8.2. Tips for Working with Resource Files
        3. 17.8.3. Using Placeholders in Resource Strings
        4. 17.8.4. Internationalizing Validation
          1. 17.8.4.1. Globalizing Validation Rules
            1. 17.8.4.1.1. Using Ajax.GlobalizationScript()
        5. 17.8.5. Localizing Data Annotations Validation Messages
          1. 17.8.5.1. Localizing the Client-Side Number Validation Message
      9. 17.9. Performance
        1. 17.9.1. HTTP Compression
        2. 17.9.2. Tracing and Monitoring
        3. 17.9.3. Monitoring Page Generation Times
        4. 17.9.4. Monitoring LINQ to SQL Database Queries
      10. 17.10. Summary
    4. 18. Upgrading and Combining ASP.NET Technologies
      1. 18.1. Using ASP.NET MVC in a Web Forms Application
        1. 18.1.1. Upgrading an ASP.NET Web Forms Application to Support MVC
          1. 18.1.1.1. Changing the Project Type
          2. 18.1.1.2. Adding Assembly References
          3. 18.1.1.3. Enabling and Configuring Routing
          4. 18.1.1.4. Adding Controllers and Views
        2. 18.1.2. Interactions Between Web Forms Pages and MVC Controllers
          1. 18.1.2.1. Linking and Redirecting from Web Forms Pages to MVC Actions
          2. 18.1.2.2. Transferring Data Between MVC and Web Forms
      2. 18.2. Using Web Forms Technologies in an MVC Application
        1. 18.2.1. Using Web Forms Controls in MVC Views
        2. 18.2.2. Using Web Forms Pages in an MVC Web Application
        3. 18.2.3. Adding Routing Support for Web Forms Pages
          1. 18.2.3.1. Web Forms Routing on .NET 4
          2. 18.2.3.2. Web Forms Routing on .NET 3.5
          3. 18.2.3.3. A Note About URL-Based Authorization
      3. 18.3. Upgrading from ASP.NET MVC 1
        1. 18.3.1. Using Visual Studio 2010's Built-In Upgrade Wizard
          1. 18.3.1.1. Upgrading to .NET 4
        2. 18.3.2. Other Ways to Upgrade
        3. 18.3.3. A Post-Upgrade Checklist
          1. 18.3.3.1. Avoiding Anti-Forgery Token Problems Next Time You Deploy
            1. 18.3.3.1.1. Detecting and Fixing the Problem Automatically
      4. 18.4. Summary