WCF Web API service with an Entity Framework data model (on an ASP.NET web site)
This post builds upon the content of the “getting started with WCF Web API” post. We will add an Entity Framework data model, and some methods that perform HTTP GET requests.
.
This post was most recently updated in October 2011.
It is the second post in a multipart series on WCF Web API, and is intended to be used by students in Seneca’s diploma- and degree-level software development programs, and any other entry- to mid-level developer.
.
Get ready to add a data model
There are some topics that you must know, or learn, to be successful in the next phase of the course. They are introduced next.
LINQ is a .NET Framework feature (for the C# language) that adds language-integrated query, set, and transform operations. As a language feature, it eliminates the need to go “out of band” (i.e. use SQL) to perform common operations on data stores.
To use LINQ effectively, you must learn query operators, and lambda expressions.
The following note will be useful as a refresher, or as a learning guide:
C# language features for working with data
A RESTful web service is resource-oriented, and URIs are very important. You will learn how to create URI templates for resource collections and their members.
.
Update your WCF Web API service “template”
In the getting started post, you were advised to create a “template”, which could be used for future WCF Web API services.
We will update the template now, so that we can support an Entity Framework data model.
.
Use NuGet to add packages
We need to add the new version, 4.1, of the Entity Framework classes. We will use NuGet to do so.
Right-click your project, and choose Manage NuGet Packages.
In the left-side navigation area, select Online, and then search for “entity” (using the upper-right search field). In the results list/pane, choose to install the EntityFramework package.

.
Add two new methods to Global.asax
You know (or have just learned) that a “context” is an important component for working with an Entity Framework data model. All operations – create, read, update, delete – are performed on an instance of the context.
This means that every method must create an instance of the context, configure it, and dispose of it after it performs its operations. If you have many methods, the same block of code is used to instantiate, configure, and dispose.
We want to avoid repeating the same block of code. Therefore, we will take advantage of the role of Global.asax, by adding two methods. One runs when the web service receives a new request, and the other runs after the web service fulfills the request.
(The following is appropriate for simple and entry-level web services. For high-volume web services that support concurrent requests, this strategy will not be suitable.)
Add the “Application_BeginRequest” method to Global.asax:
void Application_BeginRequest(object sender, EventArgs e)
{
// Replace the Object type with your own DbContext type
var context = new Object();
// Un-comment the following statement
//context.Configuration.ProxyCreationEnabled = false;
HttpContext.Current.Items["_context"] = context;
}
.
Now, add the “Application_EndRequest method to Global.asax:
void Application_EndRequest(object sender, EventArgs e)
{
// Replace the Object type with your own DbContext type
var context = HttpContext.Current.Items["_context"] as Object;
if (context != null)
{
// Un-comment the following statement
//context.Dispose();
}
}
.
These methods will need editing, after you add an Entity Framework data model. However, in their current form, they are syntax-correct, and will enable the web site to build (compile) correctly.
.
Add a “context” property to your service class
The “Application_BeginRequest” method (in Global.asax) created an object in the HttpContext.Current.Items dictionary. This enables any code in any class to fetch the object.
You will edit your Service.cs class, and add a static property. The property will return the object – the “context” – that was created in Global.asax. This will enable us to use the context in a syntax-efficient manner.
Add the following property to the top of your service class:
// Replace the Object type with your own DbContext type
public static Object context
{
// Replace the Object type with your own DbContext type
get { return HttpContext.Current.Items["_context"] as Object; }
}
.
Save your template
Save your updated template. Exit Visual Studio.
.
Copy-paste your “template” to create a new WCF Web API service
Now, copy-paste your updated template now, to create a new service.
In the sections that follow, you will be using your copies of the Northwind tables in your database.
.
Add and configure an Entity Framework data model
In this section, you will do the following:
- Add an Entity Framework data model
- Generate classes for your data model entities
- Modify the code generation template, and regenerate the classes
- Edit (update) Global.asax
- Edit (update) your service class, Service.cs
.
Add an Entity Framework data model
Add an Entity Framework data model, using “best practices”.
Remember to “build” (compile) your web site, after the data model has been generated, and before you continue.
.
Generate classes for your data model entities
An Entity Framework data model, by default, generates context and entity classes which support a large number of features which are not useful or important in a WCF Web API service. In addition, the XML serialization is too verbose, and not suited to our needs.
Therefore, we will generate context and entity classes which are better-suited to our needs.
Right-click an empty/open area of the data model design surface, and choose Add Code Generation Item. Choose “ADO.NET DbContext Generator”.
If you do not see “ADO.NET DbContext Generator”, then you must add it.
On the left-side navigator, choose Online Templates. Then, search for “dbcontext” in the upper-right search field. Choose “ADO.NET C# Web Site DbContext Generator”.
.
After the classes are generated, you will see a source code file structure that appears similar to the example on the right.
Model.Context.tt is the text template that the code generator uses to create the Model.Context.cs source code file, which contains the context class.
Model.tt is the text template that the code generator uses to create the Model.cs source code file, which contains the entity classes.
You should open the cs files, and look at the classes that were generated.
.
Modify the code generation template, and regenerate the classes
The generated classes are almost perfect for our use. However, we need to make a few changes.
When you inspect the entity classes in Model.cs, you will notice that the collection property is published as an ICollection. Its backing store is a HashSet. See the following code for the “nwCategory” class:
public partial class nwCategory
{
public nwCategory()
{
this.nwProducts = new HashSet<nwProduct>();
}
public int CategoryID { get; set; }
public string CategoryName { get; set; }
public string Description { get; set; }
public byte[] Picture { get; set; }
public virtual ICollection<nwProduct> nwProducts { get; set; }
}
.
The ICollection type will cause a problem with the WCF Web API serializer, which will not serialize an interface.
To fix the problem, we must change ICollection to a concrete type. We will also change the property’s backing store type to match.
The best place to make the change is in the text template. Close Model.cs. Open Model.tt, and make the following edits:
1) Search for “HashSet”, and replace with “List”. (It should appear only once.)
2) Search for “ICollection”, and replace with “List”. (It should appear only once.)
Save and close the template, and rebuild (compile) your web site. Open Model.cs, and you will see that the collection properties are now generic lists.
Note to readers from outside the Seneca College community:
The author acknowledges that this isn’t the best solution for in-production web services.
However, it enables the typical college student or new learner to get results by using a body of knowledge and experience that they currently possess.
A more robust and complete solution would typically use the data transfer object pattern, along with selected other patterns.
External readers are invited to comment on the post.
.
Edit (update) Global.asax
Open Model.Context.cs, and you will see the type name of your class. (It obviously should match the name you specified for your entity container, back when you created the data model.)
You will need the type name to edit Global.asax and your service class.
Open Global.asax. In the Application_BeginRequest and Application_EndRequest methods, follow the instructions in the code comments. (After successfully editing these methods, you can remove the code comments, if you wish.)
.
Edit (update) your service class, Service.cs
Open your service class. Edit the “context” property, by following the instructions in the code comments. (As above, you can remove the code comments, if you wish.)
.
Add a method to return a collection
In the getting started post, you created a method that returned a collection that was generated on-the-fly. Here, you will return a method that will return a collection from the Entity Framework data model. We’ll work with the nwCategories entity collection.
Create a method that looks like the one below:
[WebGet(UriTemplate = "categories")]
public IEnumerable<nwCategory> AllCategories()
{
return context.nwCategories.ToList();
}
.
When you run the web service, with the right URI, you should see the following results:

.
Add a method to return one object in the collection (“version 1″)
Create a method that will return one nwCategory. Note the following:
- The URI template includes a variable value, delimited with curly braces
- The method’s return value is nwCategory
- The method has an argument, which will be the category ID
- Matching names for the URI template variable name, and the argument name
.
It should look like the method below:
[WebGet(UriTemplate = "category/{id}")]
public nwCategory CategoryById(int id)
{
return context.nwCategories.Find(id);
}
.
Update the method to “version 2″ by adding error checking and recovery
The method above works fine, as long as the category ID exists. If it doesn’t, or if the value isn’t an integer, then the request will fail.
You need to add error checking, and the ability to recover from bad request data. The following approach is recommended. (You may modify this code to meet your needs.)
[WebGet(UriTemplate = "category/{id}")]
public nwCategory CategoryById(string id)
{
// Local variables
int _id;
nwCategory _object;
// If the argument is not an integer, return an error
if (!Int32.TryParse(id, out _id)) throw new HttpResponseException(HttpStatusCode.NotFound);
// Attempt to locate the object
_object = context.nwCategories.Find(_id);
// If the object is null, return an error
if (_object == null) throw new HttpResponseException(HttpStatusCode.NotFound);
return _object;
}
.
Note the following about the code:
- The method’s argument was changed to a string, to enable us to capture a non-integer error (the alternative is to leave it as an integer, and allow the server to return HTTP 500 for non-integer data, so you have to decide whether that’s OK with you)
- HttpResponseException() is used to return the appropriate error code
.
URI template design discussion
The design of your URI templates is important. The design tells users about the resources that you are publishing. It can also tell the user something about relationships between resources.
A good URI template design requires you to think about:
- The fixed (static) segments
- The variable segments
.
Now that you have seen how easy it is to write methods for your web service, we urge you to think about your URI templates before you write code, but still be prepared to experiment and revise your work.
As an illustration, let’s assume that we would like to return a collection of nwProduct objects that are in a specific category. You have at least two choices for a URI template:
- …/products/category/{id}
- …/category/{id}/products
.
Which makes more sense? Which form helps the user understand (more) about the resources you are publishing? How does the URI template suggest that other operations are possible?
The following is a sample implementation of the second choice:
[WebGet(UriTemplate = "category/{id}/products")]
public IEnumerable<nwProduct> ProductsByCategory(string id)
{
// Local variables
int _id;
List<nwProduct> _object;
// If the argument is not an integer, return an error
if (!Int32.TryParse(id, out _id)) throw new HttpResponseException(HttpStatusCode.NotFound);
// Attempt to locate the object
if (context.nwCategories.Find(_id) == null) throw new HttpResponseException(HttpStatusCode.NotFound);
_object = context.nwProducts.Where(c => c.CategoryID == _id).ToList();
// If the object is null, return an error
if (_object == null) throw new HttpResponseException(HttpStatusCode.NotFound);
return _object;
}
.
You may have noticed the additional test in the method above. Two questions:
- What should the method return if the category does not exist?
- What should the method return if the category exists, but there are no products in the category?
.
The suggested answer for Question 1 is to return a 404 (not found). The category does not exist, so there’s no point even asking for products in that category.
The suggested answer for Question 2 is to return 200, and an empty result set (which is a valid response).
.
Add a method (or two) to get suppliers from a specific country
To illustrate LINQ query operators and lambda expressions, we’ll add a method (or two) that enables the user to request suppliers from a specific country.
The URI template will look like this: /Suppliers/Country/{country}
The coding pattern will be similar to the above examples.
The following method uses a standard LINQ query expression.
[WebGet(UriTemplate = "suppliers/countryV1/{country}")]
public IEnumerable<nwSupplier> SuppliersByCountryV1(string country)
{
// An empty set is a valid result, so we will not use HttpResponseException
// (Country is a property, which is NOT associated with another entity)
// This method uses a standard LINQ query expression
var suppliers = from s in context.nwSuppliers
where s.Country.ToLower() == country.ToLower()
orderby s.CompanyName
select s;
return suppliers.ToList();
}
.
The following method uses a fluent method-based query, with lambda expressions.
[WebGet(UriTemplate = "suppliers/countryV2/{country}")]
public IEnumerable<nwSupplier> SuppliersByCountryV2(string country)
{
// An empty set is a valid result, so we will not use HttpResponseException
// (Country is a property, which is NOT associated with another entity)
// This method uses a fluent method-based query with lambda expressions
var suppliers = context.nwSuppliers
.Where(s => s.Country.ToLower() == country.ToLower())
.OrderBy(s => s.CompanyName)
.Select(s => s);
return suppliers.ToList();
}
.
On your own
On your own time, we recommend that you write methods that return objects or collections of objects for the other entities in your model.
You will also get more practice with Lab 2.
.
.
.
.

With regard to using data transfer object pattern with the original code that was generate in Model.cs file. Are you going to make another post about it?
I was curious how you will handle this in production website.
Steven.
Yes, I will do another post about this (soon).