making a WCF REST stand-alone service exe from scratch – part 1 of 4, creating the minimal bare service

If you search the online templates in VS2010, you’ll find a WCF REST template already there.

image

However, this template makes an ASP.NET-hosted (typically IIS-hosted) service for you.  For instance, it uses ASP.NET support for things like creating a route for the service:

public class Global : HttpApplication
{
    void Application_Start(object sender, EventArgs e)
    {
        RegisterRoutes();
    }

    private void RegisterRoutes()
    {
        // Edit the base address of Service1 by replacing the "Service1" string below
        RouteTable.Routes.Add(new ServiceRoute("Service1", new WebServiceHostFactory(), typeof(Service1)));
    }
}

It also adds in the modules bit for the url routing support, used above:

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    </modules>
  </system.webServer>

You can also see how its WCF config section (system.serviceModel) needs asp.net compat, although it’s VERY simple on the WCF config side since it just defines a simple WCF REST standard endpoint (webHttpEndpoint) and the ‘heavy lifting’ is done by the ServiceRoute and resulting WebServiceHostFactory, as per the RegisterRoutes method.  It’s also a bit simplified since the template has a single service class, but no service contract involved.

  <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
    <standardEndpoints>
      <webHttpEndpoint>
        <!-- 
            Configure the WCF REST service base address via the global.asax.cs file and the default endpoint 
            via the attributes on the <standardEndpoint> element below
        -->
        <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>
      </webHttpEndpoint>
    </standardEndpoints>
  </system.serviceModel>

All that’s fine if you’re ok hosting inside a web server, but what if you wanted to just host the service in your own exe (console app, windows service, winforms/wpf, whatever) that isn’t in a web server? (in particular, WCF won’t be using ASP.NET)

Creating our console WCF-service app

We’ll start off by creating a console app, not reusing anything from the existing WCF REST template or anything else:

image

Since we’re going to make a service, first thing we’ll want to do is switch over the framework to the ‘full’ framework instead of the client profile that console apps default to:

image

Using ‘Add Reference’ (the Pro Power Tools version), you can search on ServiceModel and just add the base, activation, channels, and web.

 image

While you can configure WCF programmatically (I might do a post about that), we’re going to stick with keeping our configuration in the config files so we can use the service config editor to make the changes.

Creating our bare-bones WCF service class

First, lets make a service to expose.  I’ll add a new class called MyService (can be called anything), mark it public (so the WCF framework can instantiate it) and add the [ServiceContract] attribute to mark it as, well, a service contract :)

I then add a method with a WebGet attribute to say this method should be callable via the http GET verb, and specify a template (this one passes a parameter, but templates are very flexible)

[ServiceContract]
public class MyService
{
    [WebGet(UriTemplate = "say/{something}")]
    public string AnswerBack(string something)
    {
        return "You said: " + something;
    }
}

Creating our service host

Now that we have a bare minimum service, let’s expose it with a service host in our Program.cs.  There’s generally 2 options for creating your service hosts – create them manually (invoke the constructor) or use one of factories (ServiceHostFactory, WebServiceHostFactory).

If you use the ctor manually, you have to specify either the type or the actual singleton instance of the service (the singleton path is pretty rare, the latter is what we will use)

image

If we wanted to avoid encoding the type here and would rather put it into the config, theoretically we could use one of the service host factories instead. Unfortunately, the ServiceHostFactory (and WebServiceHostFactory) are limited to working within ‘hosted’ environments (IIS, WAS) so trying that route throws an exception:

image

So, for now we’re stuck with making the ServiceHost instance ourselves and specifying the type.

image

We could even pass in the address(es) for the service if we wanted (as per the baseAddresses arg above), but for now we’ll stick with doing that in the config, so our Program.cs is as above.

Configuring our WCF service

If you try to run the service now (when we haven’t configured any addresses for it), you get an exception, as you would expect:

image 

Ok, so now we need to add some configuration for our service.  We’ll use the Service Config Editor on the app.config file that’s already in place:

We’ll let it create a new service for us:

image

Specify our type:

image

NOTE: if you’re on a 64-bit OS (and therefore you’re presumably running the 64-bit SvcConfigEditor and want ‘Browse’ to work and be able to open the console exe, you’ll need to make sure you changed the project platform target to Any CPU or x64 since the default (x86) won’t load in the (64-bit) SvcConfigEditor.  You’ll get an exception like:

image

While it kills edit-and-continue to switch away from 32-bit like this, I’m fine switching the app to Any CPU:

image

Then (after rebuilding the project) the browser can load the exe and see the type inside:

image

NOTE: this is just for the config editor app to be able to browse into the exe – it isn’t necessary for the actual runtime, as you can just specify the type name (or not use the config editor, obviously :)

Now for the service contract, we’re in the simple case of not having a separate service contract, so it’s the same type:

image

Communication mode is HTTP (the default)

image

And here’s the page I hate – pick your web service interop choice.  ‘None’ isn’t an option here, you’re stuck picking one or the other, so I just leave the default of Basic (knowing I’ll remove it when editing the config later)

image

Now pick an address – I like ‘localhost/testing’ but whatever is fine.  Note that it can be something on port 80 (or any other already-used port) because the http.sys support in the kernel lets you register for url’s “below” the normal application port-binding logic, so you could have any number of different apps all ‘listening’ on port 80 –based (or any other port) url’s.  This was really weird to me when I was first getting used to it a few years ago, but it’s very useful :)

image

Summary page tells us what we chose:

image

After Finish, we can see that it created a service for us, and the binding currently in place is (as we saw) a basicHttpBinding:

image

At this point, there’s 2 ways of getting to a working WCF REST configuration:

Option 1: switch the binding to webHttpBinding, AND add the webHttp behavior to the endpoint configuration

OR

Option 2: use the webHttpEndpoint standard endpoint which automatically includes the webHttp behavior.

Since there’s not really much to gain from doing the extra work of doing the binding and behavior manually, we’ll just go with Option 2 and use the standard endpoint.

Changing our existing endpoint to use the standard endpoint is very simple – just clear the Binding that’s there and then set the Kind:

image

image

And there we go – now when we run the app, the service is up and running and waiting for our REST calls – since we have this one GET call defined, we can just invoke it with a browser:

image

Looking at the config that was generated

We used the service config editor to create this config, but what was the actual generated config?  We can check it out just looking at the app.config, of course:

  <system.serviceModel>
    <services>
      <service name="SimpleWcfRestServiceConsoleApp.MyService">
        <endpoint 
          address="http://localhost/testing" 
          contract="SimpleWcfRestServiceConsoleApp.MyService"
          kind="webHttpEndpoint" />
      </service>
    </services>
  </system.serviceModel>

It’s pretty straightforward – thanks to being able to use the standard endpoint (the ‘kind’ attribute), it’s just the address and the service type.

About these ads

3 thoughts on “making a WCF REST stand-alone service exe from scratch – part 1 of 4, creating the minimal bare service

  1. Pingback: making a WCF REST stand-alone service exe from scratch – part 2 of 4, extract a service contract interface « James Manning's Blog

  2. Pingback: making a WCF REST stand-alone service exe from scratch – part 3 of 4, creating client configuration « James Manning's Blog

Comments are closed.