NuGet #1: MVCScaffolding with MVC3 and an existing entity model
MVCScaffolding is a NuGet package. The name itself explains what the package does. It scaffolds your MVC applications. It generally generates all your CRUD functions. It uses the Entity Framework 4.1 and also works together with EFCodeFirst. With this combination you are no longer required to have your database setup. You can just make you classes and Visual Studio/.Net will generate the database for you. Whether it’s a file (SQL Compact) or SQL Server Express. In this post I will explain a “Database First” approach.
If you are interested in a “Code First” approach (it doesn’t differ all that much though) and background information on MVCScaffolding, you can have a look at Steve Sanderson’s blog:
Prerequisites
To be able to reproduce the demo shown below, these are the prerequisites.
ASP.NET MVC 3.0
The Model View Controller libraries for Windows and Visual Studio 2010.
http://www.asp.net/mvc/mvc3
Entity Framework 4.1
You need Entity Framework 4.1 to be able to work with DbContext, which is being used in MVCScaffolding.
http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=8363
NuGet Package Manager & Package Manager Console
Otherwise we will not be able to add and control our NuGet plugins.
http://www.nuget.org
Database scripts
I used the database model below (SQL Scripts). This adds a database containing Teams, Players and Positions. It’s almost the same model as being used by Steve Sanderson’s in his blogpost. I’ve only added Position, a lookup table.
http://www.qnhtechblog.nl/wp-content/uploads/2011/06/MVCScaffolding_SQL.txt
The mplementation
We will need a MVC application if we want to use MVCScaffolding (no one would have guessed that). For standard WebForms applications, there’s also a scaffolding package available, namely T4Scaffolding. The MVCScaffolding package is actually based (and dependent) on that last one.
I’ve added an MVC 3 application. I selected an Internet Application template, so I have a good layout to start with.
The Entity Data Model
I have used the SQL scripts above to create my database. It also holds some data, also for a quick start. Go ahead and add the EDM (under models) from our database with the three tables.
You will see that the three entities we’ve just selected were added to our model. To be able to combine our model with MVCScaffolding, we should generate a DbContext from our model. Rightclick on the model surface and select Add Code Generation Item…. Under Code you can now select ADO.NET DbContext Generator.
You will see two *.tt files have been generated. The files are template files, to be more precise, T4 templates. These can be used to generate code for our entities. If you expand the tt-files you will notice our entities and context can be found there. If you look at the code you will also notice it contains exactly the same attributes as present in our entity data model. De classes are musch simpler than they are represented in the edmx-file. This way it’s also easy to expand these classes.
Adding the NuGet package
And this is where the magic comes in. We will be adding the NuGet package “MVCScaffolding”. You can achieve this through two different ways.
1) Through the user interface… the “easy way”
Right click your project and choose Add Library Package Reference…. You can now search for “MVC” and easily find the package. Also notice the Dependencies on the right. If the dependencies are not present on your system, the NuGet system will automatically try to download and install them, before installing your selected package. Now, that’s just what we want. Now click install and you can use MVCScaffolding.
2) Using the Package Manager Console
This seems like the hard way, but it really isn’t. The Powershell automatically searches for available commandos if you use your tab-key. And if you often use these packages, you know their names, and then this is actually the fast way.
Using MVCScaffolding
You will need the Package Manager Console to use MVCScaffolding. I will only show you how to create your CRUD functions very quickly. If you want to learn more about the posibilities of MVCScaffolding, you can have a look at Steve Sanderson’s blog again: http://blog.stevensanderson.com/2011/01/13/mvcscaffolding-standard-usage/.
To have your controller and views generated, you can just use one command:
PM> Scaffold Controller Team
If you run this command, you can see MVCScaffolding at work, generating classes, controllers and views. It also generates a DbContext class. You can do the same for the other two classes Player and Position.
Adding the connectionstring
Because we are using an existing context and repository, we must change a little thing in the generated DbContext class, QNHExamplesMVCScaffoldingContext.cs. We will have to pass our connectionstring to the base class constructor. If you don’t do this, you will most likely come accross the next error. Go ahead and fire your application up if you don’t believe me (well, it only happens if you don’t have SQL Express installed and running or the SQL Compact Framework installed for this application).
A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 – Error Locating Server/Instance Specified)
So open the class and add this one line of code to correct this problem.
1 2 3 4 5 |
public class QNHExamplesMVCScaffoldingContext : DbContext { public QNHExamplesMVCScaffoldingContext() : base (ConfigurationManager.ConnectionStrings[ "MVCScaffoldingEntities" ].ConnectionString) { } (…) } |
The result
We are actually kinda done now. Go ahead and build the application, fire it up and navigate to /Teams, /Players or Position to discover all your CRUD functions have already been implemented for you and you didn’t even have to right more than 5 lines of code. It even asks you for a confirmation if you want to delete something. Isn’t that neat?! Also notice the dropdown boxes with teams and positions when you are editing or creating a player.
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
What else is there to know?
Two other things you might be interested in…
Keys and 1-to-many relations
The scaffolder automatically detects your 1-to-many relations and adds those drop-down boxes. But how does this work?
The most important thing is to confirm yourself to the naming conventions. A primary key must look like this: {Modelnaam}Id. A foreign key should also conform to this same convention! So a link between Team and Player should be name TeamId in both classes. E.g. one TeamId in table Team has more instances of TeamId in table Player. You can decouple this by renaming the fields in your EDM or even in your DbContext and then map them back. It’s up to you how you’d like to do this.
If the naming convention is not followed you could come across this error:
Get-PrimaryKey : Cannot find primary key property for type ‘ModelName’. No properties appear to be primary keys.
Validation
Another important feature is validation. It’s always that shitty job you doi at the end (hoping people and testers will forget this). Just like creating CRUD functions, you don’t want to be worrying about this. An int is an int, and a datetime is a datetime. This should be easier. And could you also just mark fields in your code to make them required?
If there’s no validation on your form, you get this:
… and that’s not what you want.
Validation is actually automatically added to your forms, but not the required fields. We have to mark them with the [Required] attribute. You will need to have System.ComponentModel.DataAnnotations referenced. So let’s mark the Name in Team as required.
1 2 3 4 5 |
public int TeamId { get ; set ; } [Required] public string Name { get ; set ; } public string City { get ; set ; } public Nullable<System.DateTime> Founded { get ; set ; } public virtual ICollection<Player> Players { get ; set ; } |
If we rebuild our application and refresh the webpage, we can try and submit an empty the Create Team form again, leaving Name empty and filling out 0 as the founded date and see what happens. I really like these features. This usually takes so much time when building applications. We don;t have to worry about validation anymore. And the looks, that’s something for later. We will just use some CSS to get the validation like we want.
But how does this exactly work? If we open up the sourcecode of the webpage, we can see some unknown attributes have been added to our input field. These attributes were added because our @Razor markups said validation should be added. The weird thing though… where does this validation happen? There’s no client side code to be seen, except for some jQuery add ins.
Unobtrusive validation
That’s what it is called. The javescript code just isn’t visible. It can be found in the jQuery code. The jQuery libraries (jquery.validate.js en jquery.validate.unobtrusive.js) check all form fields for the attributes which you’ve just seen in the sourcecode. If it finds these attributes, it will handle the validation for you.
You can tell your application whether to parse the @Razor code as unobtrusive or obtrusive in the web.config.
If you would set UnobtrusiveJavaScriptEnablede to false, we should notice the difference in the source code right? Let’s fire it up again, now with unobtrusive=false. Have a look at the source code and notice the validation client-side javascript has been added at the bottom of the page.
You may also notice that the attributes in our input field have been vanished and replaced by…, well actually by nothing. It’s totally different. Now the javascript above just makes the span visible if necessary.
You can find more information about unobtrusive validation over here:
http://bradwilson.typepad.com/blog/2010/10/mvc3-unobtrusive-validation.html
Conclusion
It seems like a lot of work, but once you get the hang of it, it only offers benefits, especially for the smaller “enterprise applicatons”. Every so often every programmer needs to develop some sort of client to access datastores and with this package it’s a piece of cake.
Go ahead and try some other NuGet packages. I will try and write something about some more packages.