WCF RESTFul Service with Entity Framework CodeFirst

I’m going to try to kill two birds with one stone in my post today.  My first goal was to setup a WCF RESTful service – but spice it up a bit to show off some Entity Framework CodeFirst goodness at the same time.

This isn’t some sort of ‘best practices’ post – more of a quick (hopefully) and dirty sample walkthrough for anyone interested in doing this as well.

This sample will be done with Visual Studio 2010, .NET framework 4.0.

The first step is to setup a WCF REST Service Application.  I used, what I think, is an out of the box C# template, under ‘Web’:

image

I used the default name it provided (‘WcfRestService1’).

The default template will create some boilerplate code for us.  I recommend as well to goto the project settings for the service and set the port to be 2023. 

The WCF RESTFul service provides an operations help page to view the available endpoints:

http://localhost:2023/Service1/help

image

Clicking on the method ‘GET’ and/or ‘POST’ will highlight the services available.  You might see more than these two items at this time.  But first I’m going to make some changes and introduce Entity Framework Code-First.

Let’s go ahead and get our Code-First setup before we refactor the service.  Assuming you have Nuget installed (if not, go get it!), inside the Package Manager Console you can easily install Code-First.  Type into the console the following:  Install-Package EFCodeFirst.

As of this writing I’m using version 0.8.  You should see something similar to the following:

 

PM> Install-Package EFCodeFirst
Successfully installed 'EFCodeFirst 0.8'.
Successfully added 'EFCodeFirst 0.8' to WcfRestService1.

Great – we now have EFCodeFirst, it will add some assemblies to the mix. 

The default WCF RESTful template included a class ‘SampleItem’, so we will use that – it takes advantage of the Code-First convention over configuration by providing an ‘Id’ field – so it makes like easy for us.  If you don’t’ it, the class looks like the following:

public class SampleItem
    {
        public int Id { get; set; }
        public string StringValue { get; set; }
    }

[ServiceContract]
    public interface IService1
    {
        [WebGet(UriTemplate = "")]
        List<SampleItem> GetCollection();

        [WebGet(UriTemplate = "{id}")]
        SampleItem Get(string id);

        [WebInvoke(UriTemplate = "", Method = "POST")]
        SampleItem Create(SampleItem instance);

        [WebInvoke(UriTemplate = "{id}", Method = "PUT")]
        SampleItem Update(string id, SampleItem instance);

        [WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
        void Delete(string id);
    }

[ServiceContract]
    public interface IService1
    {
        [WebGet(UriTemplate = "")]
        List<SampleItem> GetCollection();

        [WebGet(UriTemplate = "{id}")]
        SampleItem Get(string id);

        [WebInvoke(UriTemplate = "", Method = "POST")]
        SampleItem Create(SampleItem instance);

        [WebInvoke(UriTemplate = "{id}", Method = "PUT")]
        SampleItem Update(string id, SampleItem instance);

        [WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
        void Delete(string id);
    }

[ServiceContract]
    public interface IService1
    {
        [WebGet(UriTemplate = "")]
        List<SampleItem> GetCollection();

        [WebInvoke(UriTemplate = "", Method = "POST")]
        SampleItem Create(SampleItem instance);
    }

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class Service1 : IService1
    {

        public List<SampleItem> GetCollection()
        {
            using (ItemContext context = new ItemContext())
            {
                return context.SampleItems.ToList();
            }
        }

        public SampleItem Create(SampleItem instance)
        {
            using (ItemContext context = new ItemContext())
            {
                context.SampleItems.Add(instance);
                context.SaveChanges();
            }
            return instance;
        }

        public SampleItem Get(string id)
        {
            using (ItemContext context = new ItemContext())
            {
                var item =
               (from c in context.SampleItems
                where c.Id == Int32.Parse(id)
                select c).FirstOrDefault();

                if (item == null)
                {
                    throw new WebFaultException(HttpStatusCode.NotFound);
                }

                return item;
            }
        }

        public SampleItem Update(string id, SampleItem instance)
        {
            using (ItemContext context = new ItemContext())
            {
                 SampleItem sampleItem =(from c in context.SampleItems
                 where c.Id == Int32.Parse(id)
                 select c).FirstOrDefault();
                sampleItem = instance;
                context.SaveChanges();
                return sampleItem;
            }
        }

        public void Delete(string id)
        {
            using (ItemContext context = new ItemContext())
            {
                SampleItem sampleItem = (from c in context.SampleItems
                                         where c.Id == Int32.Parse(id)
                                         select c).FirstOrDefault();
                context.SampleItems.Remove(sampleItem);
                context.SaveChanges();
            }
        }
    }

Just a quick overview here – we can use Linq style queries to handle all our query needs.  You can see from the GetCollection call above that the context exposes the SampleItems DbSet that is queryable. 

I added one piece to the above that is a nicety of working with REST.  I made a decision to throw a ‘404’ not found exception on the Get call.  If a value is passed in that is not valid, it should show a 404 response back.

ie.

throw new WebFaultException(HttpStatusCode.NotFound);

I hope this provides some insight into use the WCF RESTful services along with EF Code First.

Advertisements

One thought on “WCF RESTFul Service with Entity Framework CodeFirst

  1. Would you happen to have this project as a .zip that can be downloaded? Maybe with the latest EF4.1?

    Thanks,

    Jeff

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s