Advanced Scaffolding

Chapter 4 overviewed the MVC 4 use of scaffolded views, which make it easy to create the controller and views to support create, read, update, and delete functionality just by setting options in the Add Controller dialog. As noted in Chapter 4, this scaffolding system is extensible. This section describes a few approaches for extending the default scaffolding experience.

Customizing T4 Code Templates

The default scaffolding provided by MVC is powered by T4 templates (T4 is a code-generation engine integrated with Visual Studio.) Assuming your Visual Studio installed directory was C:Program Files (x86)Microsoft Visual Studio 11.0, you would find these templates in the following locations:

  • C:Program Files (x86)Microsoft Visual Studio 11.0Common7IDEItemTemplatesCSharpWebMVC 4CodeTemplatesAddController
  • C:Program Files (x86)Microsoft Visual Studio 11.0Common7IDEItemTemplatesCSharpWebMVC 4CodeTemplatesAddView

MVC first looks for a CodeTemplates folder in your project, so if you want to customize new controllers, you can copy the CodeTemplates folder directly into the root of your project and add your own T4 templates.

Visual Studio will complain with the following message:

Compiling transformation: The type or namespace nameMvcTextTemplateHostcould not be found (are you missing a using directive or an assembly reference?)

The reason for this is that when adding a T4 file to a project, Visual Studio sets the value of the Custom Tool property for each template to the value TextTemplatingFileGenerator. For a standalone T4 file, this is what you want. But in the case of your view scaffolds, this value is not correct. To fix this issue, select all the T4 files and clear the Custom Tool property in the Properties window, as shown in Figure 15.9.

Better yet, you can install the Mvc4CodeTemplatesCSharp NuGet package (or Mvc4CodeTemplatesVB for Visual Basic) into your project. This copies the templates into your project; it also sets the build action correctly for these files so Visual Studio doesn't try to run them when you open them.

The Add View dialog will now give preference to the view scaffold T4 templates in your project over the default ones of the same name. You can also give some templates a new name. The Add View dialog will show your new templates as options in the Scaffold Template drop-down list.


Code Templates versus Helper Templates
It's easy to confuse these templates with the helper templates used within MVC views. The Editor and Display templates (discussed in the Templates section later in this chapter) are used to display model information within a view, while the T4 templates discussed in this section are used by Visual Studio when you are adding new code items to your project. You can think of the former as runtime (dynamic) scaffolding and the latter as design-time (static) scaffolding.

The MvcScaffolding NuGet Package

While the T4 approach in the previous section works, the scaffolding experience in ASP.NET MVC 4 is dramatically improved by the MvcScaffolding NuGet package.

Install-Package MvcScaffolding

This package is written by a member of the ASP.NET team, although it's not a Microsoft product or officially supported. It adds several great scaffolding features:

  • It adds a few more advanced template options to the Add Controllers dialog.
  • It allows you to really take command of the scaffolding experience using custom PowerShell commands from the Package Manager Console.
  • It automates the process of creating your own custom scaffolders.
  • As it is a NuGet package, it is possible to publish more frequent updates (outside of the ASP.NET MVC release cycle), which you can apply via NuGet.

For precisely that last reason, we're not going to document MvcScaffolding in great detail here — it would very likely be out of date by the time you read this. We'll give you an overview of how it works, and then point you toward web references so you can keep up with future updates.

Updated Add Controller Dialog Options

The MvcScaffolding package adds two new options to the Add Controller dialog, as shown in Figure 15.10.

  • MvcScaffolding: Controller with read/write actions and views, using EF data access code: This is very similar to the default controller with read/write actions and views, using the EF template. There are some minor improvements, such as the use of a common partial view for both create and update scenarios.
  • MvcScaffolding: Controller with read/write actions and views, using repositories: This is the more interesting template added by MvcScaffolding. We'll look at that next.

Using the Repository Template

To use the repository template, add a new controller and select the “MvcScaffolding: Controller with read/write actions and views, using repositories” template, as shown in Figure 15.11.

This example replaces the existing StoreManagerController in the MVC Music Store application with a new controller (and views). Instead of including Entity Framework data access code in the controller, as shown in the example in Chapter 4, this controller abstracts the data access code to a separate AlbumRepository class. The code for this class is shown as follows.

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Web;

namespace MvcMusicStore.Models
{
   public class AlbumRepository : IAlbumRepository
   {
       MusicStoreEntities context = new MusicStoreEntities();
       public IQueryable<Album> All
       {
           get { return context.Albums; }
       }

       public IQueryable<Album> AllIncluding(
            params Expression<Func<Album, object>>[] includeProperties)
       {
           IQueryable<Album> query = context.Albums;
           foreach (var includeProperty in includeProperties) {
               query = query.Include(includeProperty);
           }
           return query;
       }

       public Album Find(int id)
       {
           return context.Albums.Find(id);
       }

       public void InsertOrUpdate(Album album)
       {
           if (album.AlbumId == default(int)) {
               // New entity
               context.Albums.Add(album);
           } else {
               // Existing entity
               context.Entry(album).State = EntityState.Modified;
           }
       }

       public void Delete(int id)
       {
           var album = context.Albums.Find(id);
           context.Albums.Remove(album);
       }

       public void Save()
       {
           context.SaveChanges();
       }
   }

   public interface IAlbumRepository
   {
       IQueryable<Album> All { get; }
       IQueryable<Album> AllIncluding(
           params Expression<Func<Album, object>>[] includeProperties);
       Album Find(int id);
       void InsertOrUpdate(Album album);
       void Delete(int id);
       void Save();
   }
}

Separating the data access logic from the controller code provides a number of benefits. It's easier to test the controller code (as explained in more detail in Chapter 12, in the section titled “Keep Business Logic out of Your Controllers”). Additionally, it's now possible to reuse the repository code elsewhere in your project.

Adding Scaffolders

The MvcScaffolding system uses scaffolders to generate code. You can create your own scaffolders, and conveniently (but slightly funny in a mind-bending way) the easiest way to get started with the code for your custom scaffolders is to generate it — using CustomScaffolder, a scaffolder included in MvcScaffolding, of course.

Creating a new scaffolder to handle a new controller scenario, for instance, is as simple as typing the following in the package manager console:

Scaffold CustomScaffolder AwesomeController

This adds the required files for the AwesomeController scaffolder to a new folder in your project, CodeTemplatesScaffoldersAwesomeController. Of course it's up to you to edit the generated code for this scaffolder, but everything's set up for you so you can just focus on the code that makes your scaffolder unique.

Additional Resources

As promised, we've kept this discussion at a pretty high level because it's subject to change. The best source of information on MvcScaffolding at the time of this writing is found on Steven Sanderson's blog (as he is the primary author of MvcScaffolding): http://blog.stevensanderson.com/?s=scaffolding.

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

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