Using Domain Service with ASP.NET Dynamic Data

Last week .NET RIA services was released. In the release the Asp.NET team has released the Domain Data source control and Dynamic Data support for RIA services.Both the control and Dynamic Data support are the part of the toolkit release of RIA services.

In this post I am going to cover the steps on how to get started with a functional Dynamic Data application with Domain Service. The names RIA services and Domain service refer to the same service class.

Where to get it and install it?

The Domain Data Source control and Dynamic Data support is shipped as part of the toolkit release of .NET RIA Services toolkit. You would need to install the following to use Dynamic Data.

Steps on getting a functional Dynamic Data app working with Domain Service

1. Creating a Dynamic Data application

After you install the toolkit you would see the “ASP.NET Dynamic Data Domain Service Web Application” Project templates in Visual Studio. There are both C# and VB versions of the template.

image

2. Add a LinqToSql or Entity Framework data Model

For this sample I added an Entity Framework model against Northwind database and I added the Products table.

Since Domain Service can work with either a LinqToSql or Entity Framework model and the ASP.NET Domain Data source control talks to the Domain Service class, there is only one Dynamic Data project template that works for both Linq and Entity Framework models.Unlike earlier releases Dynamic Data had different templates for Linq and Entity Framework since they had different data sources(Linq and Entity data source) to talk to different data models.

3. Compile the project

Make sure that you compile the project. The reason you want to do this is because in the next step when we create the Domain Service class, the Domain Service class reflects over the data model to figure out information about the tables in the model. Without compiling the project the Domain service would not be able to reflect over the model.

4. Add a Domain Service class

You can add the Domain Service by “Adding a New Item” to the project. “Domain Service class”  can be found in the “Web” Node of “Add New Item” dialog.

You can change the default name of the Domain Service to what you want. For this post I am naming it Northwind

image

You can select the Entities in the “Add New Domain Service” dialog that would come up after you add Domain Service. Following are the suggestions on how to configure this dialog and it should look like the one in the image below

1. Uncheck “Enable Client access” and “Expose OData endpoint”, since they are only used when you are building a RIA services application for a Silverlight client

2. Check “Enable Editing”,it will generate Insert, Update and Delete methods in the Domain Service class for the entity

3. Check “Generate associated class for metadata”, it generates partial classes for the entit(y/ies) selected.You can define metadata attributes on the entity/columns of the entity

4. Available DataContext/ObjectContext classed: This drop down shows the data model classes that you have in your project. Since for this sample you must have added only one the drop down shows that class.

image

Your Domain Service class should look something like this

 public class Northwind : LinqToEntitiesDomainService<NorthwindEntities>
     {
  
         // TODO:
         // Consider constraining the results of your query method.  If you need additional input you can
         // add parameters to this method or create additional query methods with different names.
         // To support paging you will need to add ordering to the 'Products' query.
         public IQueryable<Product> GetProducts()
         {
             return this.ObjectContext.Products;
         }
  
         public void InsertProduct(Product product)
         {
             if ((product.EntityState != EntityState.Detached))
             {
                 this.ObjectContext.ObjectStateManager.ChangeObjectState(product, EntityState.Added);
             }
             else
             {
                 this.ObjectContext.Products.AddObject(product);
             }
         }
  
         public void UpdateProduct(Product currentProduct)
         {
             this.ObjectContext.Products.AttachAsModified(currentProduct, this.ChangeSet.GetOriginal(currentProduct));
         }
  
         public void DeleteProduct(Product product)
         {
             if ((product.EntityState == EntityState.Detached))
             {
                 this.ObjectContext.Products.Attach(product);
             }
             this.ObjectContext.Products.DeleteObject(product);
         }
     }

 

 

If you are using Entity Framework as the data model then you would have to update your query method for every entity. You need to add the ordering clause. The reason that you need to do this is because by default the query method is not ordered and in Dynamic Data project templates, paging is enabled for the List and List details templates. In the case if you do not order the result of your query method and use paging you will get the following exception when you access the entity in List/List details template

The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 'OrderBy' must be called before the method 'Skip'.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NotSupportedException: The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 'OrderBy' must be called before the method 'Skip'. 

 

You can order the result of GetProducts() method shown in code above as follows. This would return the list of products ordered by ProductID

 public IQueryable<Product> GetProducts()
         {
             return this.ObjectContext.Products.OrderBy(p=>p.ProductID);
         }

 

 

 

5. Registering Domain Service with Dynamic Data

Open Global.asax.cs and uncomment the following line. Replace YourDomainServiceType with the name of Domain Service that you created eg. “Northwind” and set ScaffoldAllTables=true

 DefaultModel.RegisterContext(new DomainModelProvider(typeof(Northwind)), new 
 ContextConfiguration() { ScaffoldAllTables = true });
6. Run the app

You should now be able to build your app and run it. When you run it Default.aspx page would be launched and will show you all the entity types that have a Query Method defined.