Web API: HTTP Restful Endpoints, The WCF Way (Part III)   Leave a comment

Part I: Overview and Serialization
Part II: WCF Endpoints (This Post)

Part III: Implementing WCF Endpoints (This Post).

Our concern in this post is how to dynamically create RESTful HTTP endpoints.  Our design goals are:6676388189

  • host the Endpoints in IIS
  • create the endpoints at run time using C# code
  • zero annotations  added to web.config
  • ease and clarity of coding

The work here is based on code formats presented in Flanders’ RESTful .NET and code presented in the first two parts of this series.  Flaunder’s model code looks like this:

ServiceHost sh = new ServiceHost(typeof(HostingExample));

ServiceEndPoint se=sh.AddServiceEndPoint(typeof(HostingExample),new WebHttpBinding(),“http://localhost:8080/Hosting”);

se.Behaviors.Add(new WebHttpBehavior());

sh.Open();

This is pretty straight forward (thank you, Anders Hejlsberg). The down side is the tight binding between that seems to require a match between the class type used with the ServiceHost

new ServiceHost(typeof(HostingExample))

 and the type applied to the ServiceEndPoint

AddServiceEndPoint(typeof(HostingExample),new WebHttpBinding(),“http://localhost:8080/Hosting”)

Take on its face value this would require us to have a new ServiceHost for each endpoint we wanted to create, not good.  We, following, Flanders, can do better.  Watch carefully, its all done with mirrors.

Step 0: Define an Interface for each endpoint you wish to implement, in our case one of these would look like:

[ServiceContract]
public interface IGetTest
{
[OperationContract( )]
[WebGet( UriTemplate = “*” )]
Message AllURIs( Message msg );
}

Step 1: Declare your class as implementing the interface and as derived from the base class (ala Part II):6676386467

[ServiceContract]
[AspNetCompatibilityRequirements( RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed )]
public partial class GetTest : CGetBaseClass, IGetTest { }

Note here this is declared as a partial class, CGetBaseClass (see Part II) is the class from which this endpoint class is derive and IGetTest is the interface with GetTest implements.  The body of this class is left blank!

See here for notes on AspNetCompatibilityRequirementsMode.

Step 2: Define the contents of your new class:

public partial class GetTest
{
protected override object GetObject( IncomingWebRequestContext requestCTX, NameValueCollection queryParameters)
{
//Your working code goes here

        }
}6676385385

Step 3: Create a class which defines your interface:

public partial class CommonGetInterfaceClass : IGetTest
{
Message IGetTest.AllURIs( Message msg )
{

            GetTest getClass=new GetTest( );
return getClass.AllURIs( msg );
}
}

Note that is defined as a partial class (we will come back to this below). 

Step 4: Now you can dynamically create the your Endpoint as:

          ServiceHost = new WebServiceHost( typeof(CommonGetInterfaceClass) );
ServiceEndpoint se=ServiceHost.AddServiceEndpoint( typeof(IGetTest), new WebHttpBinding( ), “http://localhost/Endpoint/Test” );
ServiceEndPoint.Add( se );
ServiceHost.Open( );

Step 5: Repeat Steps 0 through Step 3 for each additional endpoint you which to define.  For this to work you must define a unique Interface for each class you which to implement as an endpoint.  Since we have defined CommonGetInterfaceClass as a partial class we can repeat step 3 as many times as we like in our code (with a different Interface annotation) and the Framework will pull these together for us. If you are unclear on partial class see this article.  Now our Step 4 looks like:

        ServiceHost = new WebServiceHost( typeof(CommonGetInterfaceClass) );
ServiceEndpoint se=ServiceHost.AddServiceEndpoint( typeof(IGetTest), new WebHttpBinding( ), “http://localhost/Endpoint/Test” );

        ServiceEndpoint se2=ServiceHost.AddServiceEndpoint( typeof(IGetTest2), new WebHttpBinding( ), “http://localhost/Endpoint/Test2” );
ServiceEndPoint.Add( se );

        ServiceEndPoint.Add( se2 );

        ServiceHost.Open( );

The only caveat here is that each endpoint must share a common root url.  In our example this ishttp://localhost/Endpoint/”. 

Run this code within global.asax in the Application_Start method and you are all set.

OK! This is good, RESTful endpoint creation looks more like a Bagel factory rather than a nerd fest.

Security

The only security issue we are required to touch on in this series is the security requirements needed for dynamic endpoint creation.  Since we are hosting our EndPoints with in IIS we are concerned with the security of the application pool associated with the running code.  Typically this will be the recommend identity “Network Service”, unfortunately, out of the box this identify does not have the authorization to run the code in Step 4.  What to do?  There are two choices: run the application pool in the “Local System” identity (not recommended) or reserve the base URL of our endpoints using httpcfg.exe (Windows Server 2003) or with netsh in Server 2008 or above.  Microsoft gives an overview of this process in this article.   Here dear reader is how to run this command for to reserve URL endpoints for dynamic use by “Network Service”:

httpcfg.exe set urlacl /u http://+:80/EndPoint/ /a O:AOG:DAD:(A;;RPWPCCDCLCSWRCWDWOGA;;;S-1-5-20)

On Windows Server 2008 (or above) the command is the simpler:

netsh http add urlacl url=http://+:80/EndPoint/ user=DOMAIN\user

Run this command while logged in with the equivalence of local System Administrator. Watch your return code you must get a zero value for this command to be a success.  Run this once only (you do not need to repeat this one successive reboots. (There is an unsupported GUI for this called httpconfig.exe you may want to look at).

OK! Was this fun or what?

6676381047

 

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

%d bloggers like this: