SOAP XML Web Services on WCF – with EF data model
This post will teach you to add an Entity Framework data model to a WCF Service (SOAP XML Web Service).
It is the second in a two-part series. This document was most recently updated in December 2011.
In the previous post, you learned how to create a simple SOAP XML Web Service, by using the WCF Service item template. Here, you will learn how to add an Entity Framework data model to a service.
The scope of this post is modest. We will NOT be presenting a general-purpose n-tier approach. Part of the reason is that we cover this topic – SOAP XML Web Services – as a minor part of the overall course, in about three class and lab sessions.
We will, however, take advantage of the overall design and approach to modern SOAP XML Web Services development. The protocol and the standards, combined with the tooling, make it surprisingly easy to get good results with a reasonable amount of learning and effort.
Configuration of our solution
We will use a copy of the Northwind database in our solution.
For this task, we will also organize our work by using “projects”. (In past tasks, we have used the “web site” as the container.) We need a project feature – the ability to easily hard-code a port number for the ASP.NET Development Server – to simplify our learning task.
The image to the right shows the desired result for this section of the post.
To get started, create a new project, which will simply be a solution “container”:
File > New > Project…
On the left-side navigator, under Installed Templates, choose:
Visual C# > Other Project Types > Visual Studio Solutions
In the center panel, choose Blank Solution. At the bottom of the dialog, enter an appropriate name (e.g. “WebServiceSolution”), and select a location (which will be a file system location).
The solution’s folder/directory will be a container for two projects:
- A web service
- A client that will call the web service
Continue by creating the web service. In Solution Explorer, right-click the solution, then choose Add > New Project…
On the left-side navigator, under Installed Templates, choose Visual C#.
In the center panel, choose WCF Service Application. At the bottom of the dialog, enter an appropriate name (e.g. “WebService”), and make sure its location is the solution folder/directory from above.
Next, we need to configure a static port for the web service. This will ease our development process. Right-click the project, and choose Property Pages. On the Web tab, choose/select a fixed/static port. Save (Ctrl+S) your changes.
Continue by creating the client. In Solution Explorer, right-click the solution, then choose Add > New Project…
On the left-side navigator, under Installed Templates, choose Visual C# > Web.
In the center panel, choose ASP.NET Empty Web Application. At the bottom of the dialog, enter an appropriate name (e.g. “Requestor”), and make sure its location is the solution folder/directory from above.
Next, we should configure a static port for the client. As above, this will ease our development process. Right-click the project, and choose Property Pages. On the Web tab, choose/select a fixed/static port. Save (Ctrl+S) your changes.
Before continuing, compare your work to the image shown above. Build/compile, to make sure that there are no errors or warnings.
Note about build/compile:
The build/compile step is important for a “project”. If you change your markup or your code, you must do a build/compile. If you don’t, your changes will not be implemented in the exe/dll.
This is different from a “web site”, which has a build/compile-on-demand feature.
Important WCF Service principles
You have learned some basic principles of a WCF Service, and how it implements a SOAP XML Web Service:
- The “A” in “ABC”, address, is the publicly-accessible endpoint of your service.
- The “B”, binding, is (obviously) HTTP, as a SOAP XML Web Service.
- The “C”, contract is defined in the service interface, and implemented in the service class. A service contract will define the service’s operations, and a data contract will define the shape of the data that the service works with.
There are a number of other principles that affect our design and coding decisions, covered next.
For custom types (e.g. our own types, and/or the types that describe the Northwind entities, like Product, Supplier, Category, etc.), you must define a data contract. This enables the serializer, DataContractSerializer, to do its work. A data contract requires you to mark a class with attributes.
If the type defines a circular reference, then the data contract attribute must be:
However, the framework will also support unmarked types. This enables us to use POCO (Plain Old CLR Objects) types, such as those generated by the Entity Framework editor’s code generator.
To use POCO types with an Entity Framework data model, the entity names much match.
Each property must match up too (names and types). A property’s POCO type must be concrete (i.e. it cannot be an Interface). A property cannot use the “virtual” modifier.
Incidentally, for your information, the support for unmarked types is an example of “coding by convention“. This software design paradigm is present in other areas of WCF Service development.
For best results, you must configure the context to disable (i.e. set to false) proxy generation, and lazy loading. (If you need eager loading, then use Include() in the query.)
In a client, when a Service Reference is created, the client has a definition of the web service class, and all of its operations. From the client’s perspective, return types can include:
- Scalar / primitive types
- Generic dictionary
- Entity types (more on this in the next section)
- Collections, which are materialized as arrays (of… whatever type the web service sends)
Implementing these principles
Now that the principles have been established, we can begin our implementation. Here is a preview of our work:
In the web service project, we will create an Entity Framework data model.
Next, we will generate entity classes. These classes must be edited, to follow the “unmarked types” principles above.
Then, we will define and implement service operations (i.e. methods).
In the client project, we will add a Service Reference. This will create a proxy of the web service. What’s interesting is that the client will have a definition for the web service class, and all of its operations, and it will have definitions for the entity types.
We emphasize here again: As a result of the Service Reference creation, the client will have definitions for the entity types. This will enable the client to work with instances (and collections) of entity types. Put another way, the client will be able to (for example) fetch a specific “Product” or “Employee”, enable the browser user to edit it, and return/save the changes, all while knowing the object’s properties and structure.
Scope of our in-class efforts
As noted above, we will work with a copy of the Northwind sample database. The Entity Framework data model will include three entities: Product, Category, Supplier.
The web service will include these operations:
- Return the number of products in the data store (as an integer)
- Return a list of supplier names (as strings)
- Return a collection of categories
- Return a specific category
- Accept and save an edited/changed category
Data model and generated classes
In the web service project, create an Entity Framework data model. Include only these database tables in the data model:
Build/compile your work before continuing. Note that you may have to use the NuGet Package Manager to get the EntityFramework package.
Next, generate entity classes. Use the DbContext generator. Note that you may have to download this generator template.
Then, edit the entity classes. Follow the “unmarked types” principles above:
- Properties must be concrete types (not interfaces)
- Properties cannot be virtual
Suggestion: The Category class includes a Picture property. In our example today, we will not need it. Therefore, mark that property with the [IgnoreDataMember] attribute.
(You can delete/remove the text templates – the .tt files – if you wish. If you need to re-generate your classes later, you can always do so.)
Work on the web service
As the comment suggests, you may want to re-factor your code, to change “Service1″ to “Service” (i.e. without the digit “1″).
In your web service interface, define the service operations (methods).
Next, implement the methods in the web service class. Pay attention to the return types. Use the general approach and technique you used while working on your WCF Web API services.
Build/compile your work before continuing, and ensure that the results are clean (no errors or warnings). Run the service, to ensure that you see the service start page.
Work on the client
Add a Service Reference to the project. A suggested name is “RemoteService”. The process will create a namespace – RemoteService – and classes for the web service itself (ServiceClient), as well as the entity classes.
Add an ASP.NET Web Form (Default.aspx) to the project. You will use this page to show the results of web service requests, and/or as a launcher to other pages that do the work.
Build/compile your work before continuing, and ensure that the results are clean (no errors or warnings). View the page in a browser after you do this.
Summary and wrap-up
The .NET Framework, and Visual Studio, work together to enhance your productivity when creating a SOAP XML Web Service.
Get more practice by completing Lab 5.