I have been using MVC for multiple projects, and one of the really powerful tool is the ability to Scaffold your project from templates. The one I like the most is when creating an admin page, you can generate the full CRUD (Create/Read/Update/Delete) in just a few clicks for Entity Framework.
However, there is one problem with scaffolding provided by Microsoft: it does not handle the relations between models. This is why I have been working on a NuGet package to handle this.
Installation
Simply run “Install-Package RelationScaffolding” on your project to get started. This will install the required DLLs, a few files in /Shared/DisplayTemplates and /Shared/EditorTemplates and one file in /Scripts/relation.js
Model example
We will start with a basic example of relations. Let’s use a Student/Teacher/Course example:
Most of the classes come with an “Id” and a “Name”. These are the main property we will use to link and display them.
Make a relation
To connect one model with another one, we use the [Relation]
attribute on the desired property:
[RelationScaffolding.Relation]
public virtual Teacher Teacher { get; set; }
This indicates to use the DisplayTemplates or EditorTemplates that have been installed with the NuGet package. You can read more about templates on Hanselman’s post.
Relations work also with collections:
[RelationScaffolding.Relation]
public virtual ICollection<Course> Courses { get; set; }
Which property to display
To indicate what to show when using a template, we will use the following attribute:
[RelationScaffolding.RelationDisplay]
public string Name { get; set; }
Using the template
By default, the scaffolding does not output the properties that are linked to another model. You can add them in your CSHTML as such:
Read
Teacher: @Html.DisplayFor(m => m.Course.Teacher)
Courses: @Html.DisplayFor(m => m.Teacher.Courses)
Write
Teacher: @Html.EditorFor(m => m.Course.Teacher, new { List = Model.AvailableTeachers })
Courses: @Html.EditorFor(m => m.Teacher.Courses, new { List = Model.AvailableCourses })
Now you might notice a custom attribute when using the write template: List.
By providing a list with all available items, the combo box or the checkbox list will contain the possible selectable options.
Customize edit
Default value in combo box
Common scenarios are to write a default value with no ID in a combo box. To do so, use the attribute RelationSingle
instead of the attribute Relation
. Then use the following parameter:
[RelationScaffolding.RelationSingle(Empty = "Select a teacher.")]
public virtual Teacher Teacher { get; set; }
Different name property
When displaying the combo box, you might want to tweak the name where the selection is being written. Let’s say you have the following properties:
public int TeacherId { get; set; }
public virtual Teacher Teacher { get; set; }
Entity Framework will understand that TeacherId
is actually mapped to your database. It also loads the entity directly into the virtual property matching the name.
By using the EditorTemplate on Teacher
, the name will be Teacher.Id
. If you want to use the TeacherId
property instead, use “ShortcutProperty = true
” as such:
@Html.EditorFor(m => m.Course.Teacher, new { ShortcutProperty = true })
If your property key does not happen to follow this convention, you can use PropertyName = "TeacherId"
instead.
Adding to a collection
If you want to be able to add to a collection, you can use the attribute RelationMultiple
instead of the Relation
attribute. Set the property CanAdd
to true
. A text box will be available under the checkbox list. To indicate which property should be used when creating that new object, use the attribute RelationEdit
.
See an example on Course.cs
More to come!
I have other ideas on how to make this package easier to use.
- Model Binder
- Make “CanAdd” more generic
- Support Many 2 Many
- Add a new Scaffolding template T4
- Better support of styles
- I18n
- Unit Tests
If you like this project, don’t hesitate to participate on GitHub!