Implement a complex type in MVC4 and EF






When you create models in Entity Framework you have the possibility to generalize parts of it into reusable types by adding the ComplexType attribute.

To illustrate I have a made up example of an access definition type that can be used on many different user-to-something connections to define what kind of access the user has.

[ComplexType]
public class AccessType
{
  public bool ReadAccess { get; set; }
  public bool EditAccess { get; set; }
}

The model using this complex type is then defined as:

public class User
{
  [Key]
  public Int32 UserId { get; set; }
  public string Name { get; set; }
  public AccessType AccessType { get; set; }
}

Complex types are not stored in separate tables in the database even though they internally in the program are handled as objects like the other classes from the model. In the database the complex type name and its properties are concatenated to create new fields. This is shown in the example below.

CREATE TABLE [dbo].[Users] (
    [UserId]                INT            IDENTITY (1, 1) NOT NULL,
    [Name]                  NVARCHAR (MAX) NULL,
    [AccessType_ReadAccess] BIT            NOT NULL,
    [AccessType_EditAccess] BIT            NOT NULL,
    CONSTRAINT [PK_dbo.Users] PRIMARY KEY CLUSTERED ([UserId] ASC)
);

Rendering templates




A complex type isn’t rendered automatically in MVC as other types are (string, int, etc). Instead you need to create templates for how it should be handled. You could render it manually in each view using it but that would miss out the whole point of having reusable types like the one we’ve just created.

The templates need to have the same file name as the type we’re creating them for. In Views\Shared\DisplayTemplates we create the first template named AccessType.cshtml. This template will be used every time you call the @Html.DisplayFor() method in one of the views.

@model [path to complex type].AccessType
@Html.LabelFor(m => m.EditAccess,"Read access")
@Html.DisplayFor(m => m.ReadAccess) 
@Html.LabelFor(m => m.EditAccess, "Edit access")
@Html.DisplayFor(m => m.EditAccess)

The next step is to create a template for when calling @Html.EditorFor(). We name the file AccessType.cshtml here as well and put it in Views\Shared\EditorTemplates. The important difference in this second template is that the content is editable, compared to the display template where it isn’t.

@model [path to complex type].AccessType
@Html.LabelFor(m => m.ReadAccess,"Read access")
@Html.CheckBoxFor(m => m.ReadAccess) 
@Html.LabelFor(m => m.EditAccess, "Edit access")
@Html.CheckBoxFor(m => m.EditAccess) 

Rendering the user
Assuming you’ve created a user controller to work with the user model, there should also be a user view. To use the templates created above in the user view we can now add the following lines:

@Html.EditorFor(m => m.AccessType)

or

@Html.DisplayFor(m => m.AccessType)

depending on whether we’d like to edit or just display the content of the access type object.