14 Days Free Technical Video Training from WintellectNOW

  

Ready, set, scaffold! Build ASP.NET MVC 3 applications quickly with MvcScaffolding

Tags: ASP.NET, ASP.NET MVC, Razor, Entity Framework, MvcScaffolding

If you're building ASP.NET MVC 3 applications, you'll want to know about the MvcScaffolding project on CodePlex. Software scaffolding is a way to template software applications so that you can easily get a site up and running, with complete CRUD functionality. 

What is MvcScaffolding and why use it?

MvcScaffolding is tool available to ASP.NET MVC developers using Visual Studio that generates customizable controllers and views for any number of entities in your data model. In other words, MvcScaffolding is a way to quickly create an application layout based on data. This means there are less routine tasks that developers need to do, for example, creating your own controllers/views, CRUD methods, and validation, and more time spent on solving business problems.

MvcScaffolding generates the files as plain old .cs and .cshtml code files, with no designer files, so you're free to modify them as you want. You can scaffold controllers, views, repositories, etc... for CRUD operations in an app with a few commands, and have a fully functional application to work with. Combine the power of MvcScaffolding with Entity Framework's Code First feature, and you can start knocking out web apps much faster than before.

You can further customize the scaffolding itself using T4 templates, so that the generated output suits the needs of your application, in case you need to regenerate the scaffolding occasionally during development. 

Getting Started with MvcScaffolding

Since a NuGet package exists for MvcScaffolding, you'll want to use "Package Manager Console" to install and use MvcScaffolding. Of course, you'll need NuGet first, which you can get by choosing "Extensions Manager" from the Tools menu.

SNAGHTMLfae0ee0

Once NuGet is installed, you can then open the Package Manager Console.

image

The PMC is a Visual Studio 2010 PowerShell command line tool that allows you to manipulate NuGet packages and run commands. To install MvcScaffolding, just enter the following command at the PM> command line:

Install-Package MvcScaffolding

SNAGHTML20416bd5

Scaffolding (and possible dependencies) are now ready to use. Keep the Package Manager Console window open, as you'll need it to run some commands to create the scaffolding itself after preparing the data model.

Preparing the data model for scaffolding

Because MvcScaffolding looks at the data model to determine what needs to be generated, you must have a data model in place, such as a set of POCOs in an EF Code First model. During the scaffolding process, MvcScaffolding takes the model's relationships, constraints, and validation into account when building the controllers and views.

Below is an annotated EF Code First data model with POCOs that represent products and categories in a database. Most of the code is basic C# classes, with the FourthCoffeeWebContext inheriting from the DbContext class which gives it the capabilities to perform ORM style tasks. The Products and Categories properties of the FourthCoffeWebContext class are type parameters for the DbSet class. This means the DbSet class allows the Products and Categories to interact with the DbContext and the database.

For a detailed look at this data model see my post on building a data model with EF Code First .

public class FourthCoffeeWebContext : DbContext
{
    public DbSet<Category> Categories { get; set; }
    public DbSet<Product> Products { get; set; }
}
public class Category
{
    public int Id { get; set; }
 
    [DisplayName("Category")]
    [Required(ErrorMessage = "The product category is required.")]
    public string Name { get; set; }
 
    public virtual ICollection<Product> Products { get; set; }
}
public class Product
{
    public int Id { get; set; }
 
    public int CategoryId { get; set; }
    public virtual Category Category { get; set; }
 
    [DisplayName("Delicious Treat")]
    [Required(ErrorMessage = "The product name field is required.")]
    public string Name { get; set; }
 
    [Required(ErrorMessage = "The product description field is required.")]
    public string Description { get; set; }
 
    [DisplayName("Sale Price")]
    [Required(ErrorMessage = "The Sale Price field is required.")]
    public decimal Price { get; set; }
 
    [DisplayName("Made fresh on")]
    [Required(ErrorMessage = "The Freshly Baked On field is required.")]
    public DateTime CreationDate { get; set; }
 
    [DisplayName("Don't Sell After")]
    [Required(ErrorMessage = "The Expiration Date field is required.")]
    public DateTime ExpirationDate { get; set; }
 
    [DisplayName("Qty Available")]
    [Required(ErrorMessage = "The Qty Available field is required.")]
    [Range(0, 120, ErrorMessage = "The Qty Available must be between 0 and 120.")]
    public int QtyOnHand { get; set; }
 
    [DisplayName("Product Image")]
    public string ImageName { get; set; }
}

Seeding the database with data

Now that the data model is ready, you can seed it with data as well. Seeding will take place at runtime, when you first run the application after writing the code. You'll need a class that inherits from either the DropCreateDatabaseIfModelChanges or the DropDatabaseAlways classes, with your DbContext class as the type parameter. You'll also need to override the Seed method to be able to add data to the database. Below, some sample code demonstrates how to seed the database, based on the model.

public class FourthCoffeeWebContextContextInitializer : DropCreateDatabaseIfModelChanges<FourthCoffeeWebContext>
{        
    protected override void Seed(FourthCoffeeWebContext context)
    {
        new List<Category> {
            new Category() 
            { 
                Name="Cakes & Cupcakes",
                Products = new List<Product> {
                        new Product 
                        { Name="Assorted Cupcakes", Description="Delectable vanilla and chocolate cupcakes", 
                            CreationDate=DateTime.Today, ExpirationDate=DateTime.Today.AddDays(7), 
                            ImageName="cupcakes.jpg", Price=5.99M, QtyOnHand=12, Id=1},
                        new Product 
                        { Name="Chocolate Cake", Description="Rich chocolate frosting cover this chocolate lover’s dream", 
                            CreationDate=DateTime.Today, ExpirationDate=DateTime.Today.AddDays(7), 
                            ImageName="chocolate_cake.jpg", Price=9.99M, QtyOnHand=12, Id=1},
                        new Product 
                        { Name="Carrot Cake", Description="scrumptious mini-carrot cake encrusted with sliced almonds", 
                            CreationDate=DateTime.Today, ExpirationDate=DateTime.Today.AddDays(7), 
                            ImageName="carrot_cake.png", Price=8.99M, QtyOnHand=12, Id=1}
                },                                                                  
            },                        
            new Category() 
            { 
                Name="Pies & Tarts",
                Products = new List<Product> {
                        new Product 
                        { Name="Lemon Tart", Description="A delicious lemon tart with fresh meringue cooked to perfection", 
                            CreationDate=DateTime.Today, ExpirationDate=DateTime.Today.AddDays(7), 
                            ImageName="lemon_tart.jpg", Price=10.99M, QtyOnHand=12, Id=1},
                        new Product 
                        { Name="Pear Tart", Description="A glazed pear tart topped with sliced almonds and a dash of cinnamon", 
                            CreationDate=DateTime.Today, ExpirationDate=DateTime.Today.AddDays(7), 
                            ImageName="pear_tart.jpg", Price=8.99M, QtyOnHand=12, Id=1}       
                },                                                                  
            }
        }.ForEach(c => context.Categories.Add(c));
 
        base.Seed(context);
    }
}

The above code creates a list of categories and adds two category objects to it. As it creates each category, the code also creates and adds a related set of products. The code above takes advantage of object initializers of C# 3.0 to setup the objects. With the model and seed data in place, we can move onto scaffolding the app.

Off to Scaffold!

By entering the Get- PowerShell command and supplying DefaultScaffoler as an argument, you can see a list of currently available scaffolding commands. As you can see, there's more than controllers and views, as you can scaffold MVC applications extensively.

SNAGHTML10c0d907

Here in the Package Management Console window you can use the Scaffold command with one of the default scaffolds listed in the above images to generate the files

Scaffold Controller Categories -force

The Controller scaffold creates both the controllers and views from the model. The -force argument ensures a regeneration of all scaffolds for the Categories, however the related Products still need to be shown, as shown below.

Scaffold Controller Products

You can watch the output in the Package Manager Console to view the files the scaffolding is creating, in real time. Once it is done scaffolding, run the application and access the /Products controller to see results in the browser similar to the image below.

image

The Edit view of a product reveals that MvcScaffolding created the relationships between the products and categories in the form of a dropdown list.

image

If you'd like, you can change the dropdown list to a 3rd party dropdown helper or use your own custom code, perhaps incorporating the jQueryUI. As you investigate the files generated by MvcScaffolding, you'll notice that they follow all convention over configuration, so it's easy to see where things are wired up.

Summary

MvcScaffolding is a great tool to get apps rolled out much faster than before with ASP.NET MVC. Now that you've seen what MvcScaffolding can do, you're probably ready to scaffold everything on earth - and you can (just about)! MvcScaffolding also contains commands to scaffold repositories, unit tests, and even create your own custom scaffolding. MvcScaffolding also generates clean, easily maintainable code. The code regeneration options such as scaffolding individual files only or using the -force switch to overwrite the files increase ease of maintenance by selecting the smallest possible amount of code to regenerate and re-test.

NOTE: Although this post has covered MvcScaffolding at the command line, the recently released MVC 3 Tools Update allows you to do create scaffolding with some of these options (blog post on using the MVC 3 tools update coming soon).

Get the code!

21 Comments

  • Richard said

    "... the Get- PowerShell command and supplying DefaultScaffoler as an argument ..."

    There is no "Get-" command; the command is "Get-DefaultScaffolder", which you are calling without arguments.

  • Rick Hodder said

    Love the mvcscaffolding stuff- you mention repositories, a really cool feature is if you scaffold a controller, you can use -Repository and it will create a repository, and generate a controller whose methods call to the repository.

    Ex.

    Scaffold controller customer -repository -force

    Very cool stuff!

  • Rachel said

    I doubt you'll see scaffolding in those technologies. I haven't heard anything on that front, so likely there will just be tools to help make SL/WPF/WF better though that work differently.

  • Rachel said

    @Richard,

    See this link, there is a Get command
    http://technet.microsoft.com/en-us/library/ee176842.aspx

    This is what I meant. The Get commands can be used in the PM console, and it's built on PowerShell, so it's the same stuff.

  • Rick Hodder said

    @Luciano - the mvc scaffolding is based on the T4 scaffolding Nuget package - you might be able to use it to create your own scaffolds for them.

    You would have to learn T4 to create the templates for the generated output.

  • Michael Henriques said

    Using this commmand I get The following:

    PM> Scaffold Controller Products
    Invoke-Scaffolder : Não é possível localizar um parâmetro posicional que aceite o argumento 'Products'.
    Em linha:1 caractere:9
    + Scaffold <<<< Controller Products
    + CategoryInfo : InvalidArgument: (:) [Invoke-Scaffolder], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,T4Scaffolding.Cmdlets.InvokeScaffolderCmdlet

    Can you help me?

  • Rachel said

    @Michael,

    Double check your installation, and make sure EF is installed as well. Additionally, MvcScaffolding is still not 100% finished yet, and there could be some bugs to work out. If I find anything on this, I'll keep you posted, but for now, haven't seen that.

  • Rafael Merlin said

    I think I've installed everything correctly.

    When I try the Category page, It works well, but when I try to Create a New Product (I have no products registered on my table until now, I wanted to register using the page, not the code) and when I click on Create New, when It tries to load the combobox, this error happens: "Value cannot be null.
    Parameter name: source" at System.Linq.Enumerable.Select[TSource,TResult](IEnumerable`1 source, Func`2 selector)
    at ASP.views_product_createoredit_ascx.__Render__control1(HtmlTextWriter __w, Control parameterContainer) in d:\Desenv\exemplos\Scafolding\Scafolding\Views\Product\CreateOrEdit.ascx:line 63

    Can someone help me, plz?

  • Rafael Merlin said

    I'm trying to do this, but without Seeding the tables. I'm able to use the Category page, but when I try to create a new Product this error happens:

    Value cannot be null. arameter name: source at System.Linq.Enumerable.Select[TSource,TResult](IEnumerable`1 source, Func`2 selector)
    at ASP.views_product_createoredit_ascx.__Render__control1(HtmlTextWriter __w, Control parameterContainer) in d:\Desenv\exemplos\Scafolding\Scafolding\Views\Product\CreateOrEdit.ascx:line 63

    Can someone help me? I tried on Razor and on Asp.Net and it doesn't work!

  • Rachel said

    @Raphael,

    Make sure what you're returning in the controller actually has data in it, it appears to be null by the time it's getting to the view.

  • yousaid said

    The "Get the code!" link is broken.
    Throws this exception:
    The IControllerFactory 'Orchard.Mvc.OrchardControllerFactory' did not return a controller for the name 'downloads'

  • John said

    Does anyone know why all of the views that the scaffold creates do not use the value that is specified in the DisplayName attribute? This seems odd to me that they only show up on the edit view.

  • Rachel said

    John,

    Still looking this over. I'm looking to see if there were a bug at the time of the writing or known issue. Will post as soon as I can get an update.

  • G said

    Rachel,
    This is great. A couple of questions. I see you are using orchard for this blog. I am trying to build an orchard module, and for some reason cannot see the scaffolding options when I right click to add a new item. So I found this post. I try to do it from the Package Manager window and it creates the files but is not picking up the model, so it creates an empty shell.
    is there a way I can pass the model to the scaffold command?
    Again, I am in orchard, after I codegen the module, the module project appears like a class library, not a web app, and I don't know if that is the reason why it is not picking up the T4 templates.

    Thanks for your help!

  • Rachel said

    G,

    Try getting the MvcScaffolding package from Nuget once you have your module project open, then try from the console or dialog. It's also a good idea to have the MVC3 tools update, there's a lot more options available.

    When you try the console, make the 3rd argument the name of the model. You can use the -force option to delete and recreate the views associated with the model.

    Scaffold Controller Categories -force

    Both the UI (add new item) or command shell allow you to pass the model, but you're having issues that aren't letting you get that far. When using the UI, there's a dropdown list where you can select the model.

Comments have been disabled for this content.