Book Image

ServiceStack 4 Cookbook

Book Image

ServiceStack 4 Cookbook

Overview of this book

Table of Contents (18 chapters)
ServiceStack 4 Cookbook
Credits
About the Authors
About the Reviewers
www.PacktPub.com
Preface
Index

Isolating web service routes from a web application


Until now, we've been talking about using ServiceStack in isolation, where it's the only thing handling all requests. It won't always be so simple, of course— sometimes you'll want to use ServiceStack in an existing MVC, WCF, or WebForms application. Here, we will learn different ways to isolate ServiceStack requests to ensure they don't get tangled up with requests from other frameworks.

Getting ready

For this example, let's keep building on ReidsonMessenger from the first recipe, but namespace the HTTP contract of our API by moving all of our service endpoints under a prefix. So, instead of making a GET call to /group/BestFriends to retrieve the messages from the BestFriends group, we'll be calling /api/group/BestFriends.

How to do It...

We'll need to configure the web server to facilitate our new prefix. We'll add the following to Web.config, just after the system.web section:

 <location path="api">
    <system.web>
      <httpHandlers>
        <add path="*" type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*" />
      </httpHandlers>
    </system.web>

    <system.webServer>
      <modules runAllManagedModulesForAllRequests="true" />
      <validation validateIntegratedModeConfiguration="false" />
      <handlers>
        <add path="*" name="ServiceStack.Factory" type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" />
      </handlers>
    </system.webServer>
  </location>

After making this change, running our application might return an error message as we continue visiting http://myserver/— remember to add the api path at the end to see the usual metadata page you're expecting. We'll need to change the URLs we post to use curl too, as follows:

curl http://myserver/api/group/BestFriends

While not strictly necessary, one benefit of using the location element is the ability to remove other handlers, ensuring that ServiceStack is the only thing running on this path.

If it makes more sense to make this change in code, ServiceStack allows this to be changed within your AppHost.Configure method, as follows:

public override void Configure(Funq.Container container)
{
  SetConfig(new HostConfig
  {
    HandlerFactoryPath = "api"
  }
}

In your organization, if developers have a lot of control over deployment of code, it might make sense to control this in code, as then it can be more easily tested, and you might find it more expressive. However, if another team deploys your code or manages your application in production or if you want to be able to tune this location often, it might be preferable to specify the path in the web config file, as then changing it won't require a complete compile, test, and deploy cycle.

How it works...

When using any HTTP handlers with ASP.NET, a path must be registered to tell IIS how to handle requests of a specific path. ServiceStack provides its HttpHandlerFactory implementation, which is the initial hook into the rest of the framework.

By either changing the path in web.config or setting the path when your application starts, we can make a clear separation between our web services and other resources. There are important differences between the two methods.

By changing the path within the configuration, you'll notice that when you start up your web project, you are greeted with this:

This is because ServiceStack is not actually handling your request and there is no default item within the solution that ASP.NET can serve.

By changing HostConfig and leaving web.config path as "*", ServiceStack is serving all your other resources as well. So, as soon as you run your application, ServiceStack will default to your new web services path as follows:

The following screenshot shows you the metadata page:

If you happen to be hosting files with uncommon file extensions, it's important to remember that if the ServiceStack handler path is configured as "*", ServiceStack needs to know what file types are able to be served.

For example, if you are writing your web client using something like Dart, which uses .dart files for it's source, both ASP.NET and ServiceStack need to know about this additional file type that is allowed. Perform the following steps towards this end:

  1. ASP.NET will need to know about the appropriate file extension and MIME type, for example:

        <staticContent>
          <remove fileExtension=".dart" />
          <mimeMap fileExtension=".dart" mimeType="application/dart" />
        </staticContent>
  2. ServiceStack will need to have the file extension added to the AllowFileExtensions property on HostConfig():

        var hostConfig = new HostConfig();
        hostConfig.AllowFileExtensions = {"dart"};
        hostConfig.HandlerFactoryPath = "api";
        SetConfig(hostConfig);

There's more...

ServiceStack can also be hosted in various environments including as a Windows service or even a simple console application. In this case, the initializer for the service is a call to the Start method on the AppHost, which accepts a parameter that represents the URL to bind to. If a prefix is required, it will need to be included into this urlBase parameter, as follows:

class Program
{
  const string ListeningOn = "http://*:1234/api/";
  static void Main(string[] args)
  {
    new AppHost()
    .Init()
    .Start(ListeningOn);

    Console.WriteLine("AppHost Created at {0}, " + "listening on {1}",DateTime.Now, ListeningOn);

    Console.ReadKey();
  }
}