Introduction to WCF Web API - New REST Face of .NET

This blog post will give you an introduction to WCF Web API and show you how to get started with WCF Web API along with Dependency Inject support with Ninject.
2011-11-21 10:09
Tugberk Ugurlu


24 February 2012

WCF Web API is now ASP.NET Web API and has changed a lot. The beta version is now available. For more information: Getting Started With ASP.NET Web API - Tutorials, Videos, Samples.

imageMicrosoft Web Platform is evolving. I mean really evolving. Scott Hanselman, Phil Haack, Glenn Block and Damian Edwards are the main actors for this evolution.

One of the biggest frustration we had as web developers was to face with the endless configurations with WCF. I mean, WCF is great but hasn’t been embraced the REST since the WCF Web API framework. There was something called REST Starter Kit but it ended up dead.

Yes, WCF Web API. WCF Web API is the new way of exposing and consuming APIs over http in .NET. The unofficial (not sure, maybe the official one) slogan of WCF Web API is this:

"Making REST a first class citizen in .NET"

I stole (or quoted would be nicer) the real sentences which explain the WCF Web API from the official WCF Web API page (I hope they don’t mind):

What is WCF Web API?

Applications are continually evolving to expose their functionality over the web for example social services like Flickr, Twitter and Facebook. Aside from social applications, organizations are also looking to surface their core enterprise business functionality to an ever expanding array of client platforms. WCF Web API allows developers to expose their applications, data and services to the web directly over HTTP. This allows developers to fully harness the richness of the HTTP as an application layer protocol. Applications can communicate with a very broad set of clients whether they be browsers, mobile devices, desktop applications or other backend services. They can also take advantage of the caching and proxy infrastructure of the web through providing proper control and entity headers. We are designing specifically to support applications built with a RESTful architecture style though it does not force developers to use REST. The benefits of REST for your applications include discoverability, evolvability and scalability.

The project is still at the preview stage and we are swimming in the dark sea. There are lots of rumors going around about it and most of them are nearly certain to be true. One of them is that WCF Web API and ASP.NEt MVC will be blood brothers in near future. In plain English, they will be merged together. This will be exciting and we won’t feel ourselves in a fork in the road when we need to pick ASP.NET MVC or WCF Web API in order to expose our data over http.

Cut the crap and show me the code

Well, when I first saw the WCF Web API, I told myself that this’s it! Why I told that? Because it is extremely easy to get started and going from there. I am interested in WCF as well but its configuration is endless so I haven’t been able to develop a decent project with WCF so far (maybe the problem is me, who knows!). Be careful here though, WCF is not gone! It is still the way to go with for SOAP based services.

Let’s see how we get started developing a Web API with WCF Web API (this sentence is like a poem Smile).

First of all, open up your VS and create a new ASP.NET Empty Web Application (this one is real empty guys unlike ASP.NET MVC 3 Empty Web Application):

imageimage

I told you it is real empty. Anyway, let’s stick to the point hereSmile Now, bring up the NuGet PMC (Package Manager Console) and install the package called WebApi.All:

image

image

Let’s look what we got:

image

All the packages we have pulled is individual packages. For example, if you are consuming web services on the server side, HttpClient package will help you a lot. I think all of those packages will be baked-in for .NET 4.5 so we will see a lot samples for those.

One thing that I looked when I first bring up this package is Web.Config file because I wondered how giant it was. It comes to me as a shock and it will for you, too:

image 

3 lines of code which is special to WCF Web API. This is awesome. So, where do we configure the stuff. First of all, if you would like to get started you do not need to make any configuration. We will see how in a minute. Web API comes with default configuration and this can be overridden in any steps. You can set your default configuration. One of your APIs needs different configuration? Don’t change the default one. Configure it separately. So, it is really a convention. Best part is that it is all done with code, I mean inside Global.asax.

For the sake of this demo, I created a dummy data to play with. It is really simple as follows (I will put up the source code online, you can check out what is in there):

image

I implemented the repository pattern here with an interface. I did that because I would like to show you how easy is to get going along with Dependency Injection (DI) here.

In order to create our API, we need to create a separate class. I put it under People folder and named it PeopleApi but where it stands and what name it carries don’t matter here.

I would like to go with the simplest approach firstly. Here is how PeopleApi class looks like:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Web;
using VeryFirstWcfWebAPI.People.Infrastructure;
using VeryFirstWcfWebAPI.People.Models;

namespace VeryFirstWcfWebAPI.People {

    [ServiceContract]
    public class PeopleApi {

        private readonly IPeopleRepository _repo = new PeopleRepository();

        [WebGet]
        public HttpResponseMessage<IQueryable<Person>> Get() {

            var model = _repo.GetAll();

            var responseMessage = new HttpResponseMessage<IQueryable<Person>>(model);
            responseMessage.Content.Headers.Expires = new DateTimeOffset(DateTime.Now.AddHours(6));

            return responseMessage;
        }

    }
}

When we observe this class a little bit carefully, we see some staff going on there:

  • You API class needs to be annotated with ServiceContractAttribute. This is must to do (@gblock said at the //Build conference that we are still in love with attributes but we are trying to get rid of them...).
  • The methods inside your class needs to have some special attributes like WebGetAttribute and WebInvokeAttribute. If you put them without UriTemplate property, it assumes that the method is for root of the URL.

Also, another thing to notice here is we are returning our model by wrapping it up with HttpResponseMessage class. You don’t have to do that. You can just return your object but if you need to add some special headers or response message code, it is nice way to do it that way as we set here our expires header.

As I mentioned before, there is no configuration at all in the web.config but we still need to do some configuration to tell the system to figure out what to do.

Add a Global Application Class under the root of your project:

image

Inside the Application_Start method, here is our initial set up to get going:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;
using System.Web.Security;
using System.Web.SessionState;

namespace VeryFirstWcfWebAPI {

    public class Global : System.Web.HttpApplication {

        protected void Application_Start(object sender, EventArgs e) {

            RouteTable.Routes.SetDefaultHttpConfiguration(new Microsoft.ApplicationServer.Http.WebApiConfiguration() { 
            });

            RouteTable.Routes.MapServiceRoute<People.PeopleApi>("Api/People");
        }

    }
}

What we do here is so simple:

  • We are initializing the WCF Web API with default configuration.
  • We specifically register our API with a base URL structure as route prefix.

As we have folder called People under the root of out application, if you put People as route prefix there, you will see that your API won’t work and you will get 404. I am nearly sure that it is related to routing.

I haven’t figured out how to solve this issue and I tried to Ignore that folder but it didn’t work either.

We are ready to run:

image

This is good for a start. We didn’t suffer much. Now, it is time for us to think of the possible enhancements.

Dependency Injection and IoC Container Support

As you probably noticed, I "newed" up the repository inside our API class:

private readonly IPeopleRepository _repo = new PeopleRepository();

This thing made my application tightly-coupled and it is not good. Here I have a static data resource and it is not much of a problem but if we had database related data structure here, this would make it hard for us to unit test our application.

In order to get around for this, we need to figure out a way to new up the resource outside of our context and WCF Web API offers really good extensibility point here. I won’t really extend and customize our configuration much here in order to stick with the basics but I will probably blog about that either.

First of all, let’s make our API class a little DI friendly:

    [ServiceContract]
    public class PeopleApi {

        private readonly IPeopleRepository _repo;

        public PeopleApi(IPeopleRepository repo) {
            _repo = repo;
        }

        [WebGet]
        public HttpResponseMessage<IQueryable<Person>> Get() {

            var model = _repo.GetAll();

            var responseMessage = new HttpResponseMessage<IQueryable<Person>>(model);
            responseMessage.Content.Headers.Expires = new DateTimeOffset(DateTime.Now.AddHours(6));

            return responseMessage;
        }

    }

What we do here enables someone else to provide the resource so our API class is now loosely-coupled. I would like to see what happens when we run the app like this:

image

We got an error:

The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor. To fix the problem, add a default constructor to the type, or pass an instance of the type to the host.

The system needs a parameter-less constructor as default. Let’s see how we get around with this.

Now, we need to provide those resources outside of our context but where? Let’s first bring down a IoC container. I am fan of Ninject so I will use it here as well:

image

After we install Ninject through NuGet, I added the following code inside my Global.asax file:

private IKernel GetKernel() { 
    
    IKernel kernel = new StandardKernel();

    kernel.Bind<People.Infrastructure.IPeopleRepository>().
        To<People.Models.PeopleRepository>();

    return kernel;
}

This will provide us the resources we need. Now, we need to tell WCF Web API to use this provider to create instances. Believe it or not, it is extremely easy to do that. Remember our default configuration object, WebApiConfiguration class? We will register our IoC container there:

RouteTable.Routes.SetDefaultHttpConfiguration(new Microsoft.ApplicationServer.Http.WebApiConfiguration() { 
    CreateInstance = (serviceType, context, request) => GetKernel().Get(serviceType)
});

We are passing a delegate here for CreateInstance property of our WebApiConfiguration class. When we run the application, we should see it working:

image

So nice to do something like that without much effort.

There is so much to show but I think this is enough for an intro (which I write on the stage of preview 5, I am little late Confused smile). I am sure that you get the idea here.

You can find the full code on GitHub: https://github.com/tugberkugurlu/VeryFirstWcfWebAPI



Comments

Glenn Block
by Glenn Block on Tuesday, Feb 14 2012 05:22:22 +02:00

Nice post Tugberk. Turns out you don't need [ServiceContract] in Preview 6. And I kept my word, in ASP.NET Web API (yes it's coming) you don't need attributes at all!

Tugberk
by Tugberk on Tuesday, Feb 14 2012 10:08:49 +02:00

@GlennBlock

Yes, I am very excited by the some changes which have been made at preview 6: getting rid of sync methods & ServiceContract attribute.

Couple of days ago, I had a glimpse of ASP.NET MVC 4 Beta and I saw how well Web API is integrated with ASP.NET MVC. I am looking forward to playing with it.

AR
by AR on Monday, Feb 20 2012 13:12:12 +02:00

hi i tried your application but i was not able to pass the id via the ajax call nor when i paste the url in the browser address bar, i always end up with 500 internal server error... i placed a debugger that never got hit

Tugberk
by Tugberk on Monday, Feb 20 2012 20:13:08 +02:00

@Ad

@AR

See my next post on WCF Web API to get the full exception in your hands: http://www.tugberkugurlu.com/archive/wcf-web-api-plays-nice-with-elmah-a-quick-introduction-to-wcf-web-api-httperrorhandler

AR
by AR on Tuesday, Feb 21 2012 11:27:38 +02:00

@Tugberk

 

thanks i'll enable the elmah logging and get back to you if its not resolved :), i hope by @Ad you meant @AR ;)

Tugberk
by Tugberk on Tuesday, Feb 21 2012 11:50:52 +02:00

@AR

Sorry, yes I meant @AR:)

AR
by AR on Tuesday, Feb 21 2012 20:07:27 +02:00

Hi,

 

i tried the elmah logging, it gave me the error

 

System.InvalidOperationExceptionThere are multiple operations with HTTP method 'GET' and a UriTemplate that is equivalent to '{id}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages.

i tried to modify the GetAll method to accept a parameter

[WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "{did}")]
        public HttpResponseMessage<IList<Models.Notification>> Get(int id)
        {
            var model = _repo.GetAll();

Tugberk
by Tugberk on Friday, Feb 24 2012 12:40:52 +02:00

@AR

WCF Web API is now ASP.NET Web API and has changed a lot. The beta version is now available. For more information: Getting Started With ASP.NET Web API - Tutorials, Videos, Samples.

AR
by AR on Monday, Feb 27 2012 17:54:12 +02:00

@Tugberk tnx for taking the time and replying to my comments, just one more thing can you guide me how can i publish the web service to my local host ... i am using iis7, i have tried publishing it throgh VS2010 but it gave me some "path" error

Tugberk
by Tugberk on Monday, Feb 27 2012 19:17:54 +02:00

@AR

If you use IIS for hosting, you can use the publish feature of VS 2010.

You also have a self hosting option: http://www.asp.net/web-api/overview/hosting-aspnet-web-api/self-host-a-web-api

AR
by AR on Monday, Feb 27 2012 21:21:56 +02:00

@Tugberk

 

thanks a ton!

James Burgaz
by James Burgaz on Thursday, Mar 01 2012 10:43:43 +02:00

Very informative Post so far I've read online. I would like to appreciate you, please keep going and keep writing. I've found some article related to this topic at searching time which also explained very well so I want to share link of that post...
http://www.mindstick.com/Articles/0e246b74-e99c-41bb-95ea-92d5b4aad4d0/?Introduction%20to%20WCF

and

http://wcftutorial.net/Introduction-to-WCF.aspx

At lastly! I would say to thanks everyone for yours nice post.

Tugberk
by Tugberk on Thursday, Mar 01 2012 11:47:55 +02:00

@James

Keep in mind that WCF Web API is now ASP.NET Web API and has changed a lot. The beta version is now available. For more information: Getting Started With ASP.NET Web API - Tutorials, Videos, Samples.

SerdarK
by SerdarK on Tuesday, Dec 18 2012 14:52:06 +02:00

 Hi Tugberk,

I did not ask a question via mail.

You do not love. :)

http://10.9.0.9/PersonelListesiWcf/PersonelList.svc WCF service published.

I added a WCF service reference.

How do,WCF service in the of using WebAPI(MVC4)

kiquenet
by kiquenet on Wednesday, Oct 22 2014 18:21:48 +00:00
Maybe useful Difference between WCF and Web API and WCF REST and Web Service http://www.dotnet-tricks.com/Tutorial/webapi/JI2X050413-Difference-between-WCF-and-Web-API-and-WCF-REST-and-Web-Service.html _IMHO, more complete with all differences about protocols and technologies using for building services: SOAP, ODATA, XML, JSON, REST, RESTful, WCF, WCF DataServices, ASP.NET WEB API, ASP.NET MVC, .._

Tags