|
This article is based on Entity Framework 4 in Action by Stefano Mostarda, Marco
De Sanctis, and Daniele Bochicchio, to be published December 2010. It is being
reproduced here by permission from Manning Publications. Manning early access books and ebooks are sold exclusively through Manning. Visit
the book's page for more information.
You can get an instant 40% discount on this MEAP edition by simply clicking on the
link above, and use promo code egghead40 |
As part of a chapter on integrating Entity Framework with ASP.NET, this excerpt explores
what Dynamic Data Controls offer, demonstrating how to generate rich data-editing
interfaces by leveraging Data Annotations to further enhance the generated interface.
ASP.NET Dynamic Data Controls is a feature initially introduced in ASP.NET 3.5 Service
Pack 1, and further enhanced in version 4. The idea behind this technology is
to simplify the typical actions related to data: displaying, filtering, and altering
data.
Dynamic Data Controls ships with ASP.NET, and supports both Entity Framework, and
LINQ to SQL, using the aforementioned respective DataSource controls. It is based
on a simple assumption: since the ObjectContext has the same features, given
different mappings, its calls can be generically created. In fact, using a bit
of generics and reflection, the typical operations performed by the ObjectContext
can be standardized. The same principles are valid for LINQ to SQL, of course.
Dynamic Data Controls in depth
Dynamic Data Controls work with a special kind of project, which can be found near
the other ASP.NET projects. You can find it highlighted in figure 1.

Figure 1 Dynamic Data Entities Web application is the template project to start
using Dynamic Data Controls with Entity Framework. Do not choose any other template,
or it will not work.
Dynamic Data Controls is composed by a set of templates and pages, under the "DynamicData"
directory. In this directory, you can find the templates used to represent different
kind of types, such as strings, integers, Booleans, and so on.
Register the model
To start, you only need to define the model to work against, and the magic will be
performed by using the information already present in it. In fact, the model
contains the list of entities, and each entity can describe itself: the result
is that each set of entity can be represented, and edited, automatically. The
model and routes are registered in listing 1.
Listing 1 The model and routes registration.
VB
Public Class Global_asax
Inherits System.Web.HttpApplication
Private Shared s_defaultModel As New MetaModel()
Public Shared ReadOnly Property DefaultModel() As MetaModel
Get
Return s_defaultModel
End Get
End Property
Public Sub Application_Start(ByVal sender as Object, ByVal e as EventArgs)
' model registration
Dim config As New ContextConfiguration()
config.ScaffoldAllTables = True #2
DefaultModel.RegisterContext(GetType(OrderITEntities), config) #1
' routes
RouteTable.Routes.Add(New DynamicDataRoute("{table}/{action}.aspx")
With {
.Constraints = New RouteValueDictionary(New With {
.Action = "List|Details|Edit|Insert"}),
.Model = DefaultModel})
End Sub
End Class
C#
public class Global : System.Web.HttpApplication
{
private static MetaModel s_defaultModel = new MetaModel(); public static MetaModel DefaultModel
{
get
{
return s_defaultModel;
}
}
void Application_Start(object sender, EventArgs e)
{
// model registration
DefaultModel.RegisterContext(typeof(OrderITEntities), #1
new ContextConfiguration() { ScaffoldAllTables = true }); #2
// routes
RouteTable.Routes.Add(new DynamicDataRoute("{table}/{action}.aspx")
{
Constraints = new RouteValueDictionary(new {
action = "List|Details|Edit|Insert" }),
Model = DefaultModel
});
}
}
#1 the ObjectContext used as model
#2 scaffolding is enabled
We are explicitly setting the scaffold feature on, so every single entity is automatically
displayed in the start page. If you prefer to control this list, you must set
it to off. Using the routing features from ASP.NET 4.0, the resulting URL will
be similar to "/Customers/List.aspx", where "Customers" is
the EntitySet to be managed, and "List" is the action. Other actions,
as you can see from the above snippet, are "Details", "Edit",
and "Insert", to manage the respective statuses.
Working with Data Annotations
In figure 2 you can see the default results when you display the "Customer"
list from our model.

Figure 2 Dynamic Data Controls are capable to display any mapped entity. As we can
see in this figure, the display can be customized.
By default, the display template is inferred from the type, but it can be specified
too. Generally, this is accomplished by creating a new class, specifically designed
for this scenario, which extends the entity using the MetadataTypeAttribute attribute.
Dynamic Data Controls, in fact, work with Data Annotations, a feature introduced
in .NET Framework 3.5 SP1, and further enhanced in version 4. In our example,
we are using POCO entities, so the annotations are directly generated using the
T4 engine. If you are using the default entity
generation engine, you can use partial class and the aforementioned MetadataTypeAttribute.
More information on this topic is available from MSDN: http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.metadatatypeattribute.aspx.
In our sample, we added some custom login to the default generation engine, by altering
the CDSL inside the edmx, to generate the exact code used to represent these
additional properties. Data Annotations, in fact, are working with attributes,
as you can see in listing 2, which contains an entity generated with this mechanism.
Listing 2 POCO entities generated by a template with Data Annotations.
VB
Public MustInherit Partial Class Company
Implements INotifyPropertyChanged
Implements IEditableObject
…
<DisplayName("Company name")> #1
<Required(ErrorMessage := "Company name is required ")> #1
<DataType("MultilineText")> #1
<RegularExpression("[\w]{2,}", ErrorMessage := "At least 2 chars.")> #1
Public Overridable Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
NotifyPropertyChanged("Name")
End Set
End Property
End Class
C#
public abstract partial class Company : INotifyPropertyChanged, IEditableObject
{
…
[DisplayName("Company name")] #1
[Required(ErrorMessage = "Company name is required")] #1
[DataType("MultilineText")] #1
[RegularExpression("[\\w]{2,}",ErrorMessage = "At least 2 chars.")] #1
public virtual string Name
{
get { return _name; }
set { _name = value; NotifyPropertyChanged("Name"); }
}
}
#1 attributes for Data Annotations
The annotations will influence the way the property is displayed, and its value validated:
the DisplayNameAttribute attribute is used to set a more friendly name to be
displayed; the RequiredAttribute attribute lets us define the property as required,
associating an error message to be displayed; we are specifying a new template
using the DataTypeAttribute attribute; finally, a regular expression for validation
is used, using the RegularExpressionAttribute. You can take a look at how Dynamic
Data Controls will handle these attributes in figure 3.

Figure 3 The Data Annotations attributes will modify the way the property is displayed,
and its value handled. By using them you can influence what the engine is performing.
Data Annotations are a very important way to leverage Entity Framework in ASP.NET,
and its use is not only limited to Dynamic Data Controls, but can be further
expanded to ASP.NET MVC model validation. You can find more information on the
available attributes on MSDN: http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx.