Category Archives: ServiceStack

Deploying our .NET 4.0 StackService service to IIS 6

Unfortunately the server I’m writing a ServiceStack service for is not only restricted to .NET 4.0 but also running IIS 6.0. I also need to deploy the service as a virtual directory off of the Default Web Site.

The first thing we want to do is publish/copy the files that make up our service to the IIS server.

Here’s the steps I took to get this working, obviously they may differ depending upon what access you have to the web server (and whether you deploy direct) etc.

  • From your ASP.NET/ServiceStack application, select the web service project and right mouse click.
  • Select Publish
  • Select Custom and set a profile name, mines “Files”, press OK
  • I’m going to copy the files across to the server myself, so for Publish Method, select File System and then enter a location to write your files to, click the next button
  • Leave the Configuration as Release
  • Press the Publish button

At this point the file location you selected will have the files required for the service.

Now if not already done as part of the publish steps, copy the files to the location you want to deploy them on your IIS 6.0 server. For example mine are in a folder named TestStack. Now we need to setup IIS to expose the service.

  • Open Internet Information Services (IIS) Manager or run %SystemRoot%\system32\inetsrv\iis.msc to open it
  • Expand the local computer node in the left hand tree view
  • Expand Web Sites
  • Right mouse click on the Default Web Site and select New | Virtual Directory
  • Press the Next button and enter an alias, i.e. TestStack in my case
  • Press Next and browse from IIS or enter the folder location of your service (you want the root, not the bin folder) in your browser and press next
  • Ensure Read and Run scripts (such as ASP) are checked and press Next
  • Click Finish

On the properties, Documents tab, uncheck the Enable default content page

Not sure the above is a requirement to get things working, but just happened to be something I set

On the Virtual Directory tab ensure the Execute Permissions is set to Scripts and Executables

On the ASP.NET page, ensure the ASP.NET version is 4.0.xxx

Now the virtual folder you be setup. If you’ve not got your service selected in the IIS Default Web Sites node, then select it and right mouse click, then select browse to see if all is working, or open your preferred browser and enter

http://<hostname>/StackService/metadata

If you are getting a 404 The page cannot be found error, then this might help

See Can’t get ServiceStack to work in IIS6 with HTTPS

The exact steps I took are listed below

  • Select the virtual directory in IIS, right mouse click and load the properties
  • From the Virtual Directory tab, press the Configuration button
  • Press Insert
  • From file explorer locate aspnet_isapi.dll for .NET 4.0, for example mine is located in %windir%\Microsoft.NET\Framework\v4.0.30319
  • Once located enter %windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll (replacing %windir% with you actual location) in the Executable textbox
  • Uncheck the Verify that file exists checkbox, then press OK
  • Press OK again and again until the properties dialog is closed

Now if you refresh or reload the URL for the virtual folder or again select Browse from IIS, the meta data from ServiceStack should be displayed.

Whilst this may be a fairly specific case, i.e. deployed to .NET 4.0 on IIS 6.0, I thought it might still be a useful post anyway.

.NET 4.0 compatible ServiceStack service

In my last post I outlined the creation of a ServiceStack web service, pretty much as per the current documentation on the ServiceStack website.

I’m now going to create a bare minimum service from scratch (i.e. not using the ServiceStack project templates). The reason for this is that I want to deploy a service to an old server box which doesn’t support .NET greater than 4.0. Out of the box the templates don’t work with older versions of .NET.

This post will concentrate on a .NET 4.0 compatible ServiceStack, but the same steps can be applied to a bare minimum .NET 4.6 service as well – obviously just change the .NET framework to suit.

We’ll recreate the Hello World implementation as per the ServiceStack templates in this example.

Note: I’m not aiming to create a “best practices” example of code, this literally will be the bare minimum set of code and projects to implement the demo Hello World service.

  • Create a ASP.NET Empty Web Application, setting the .NET framework to .NET 4 – my project is named TestStack
  • Using NuGet, install the ServiceStack packages – use the 4.0.24 versions. This version is required because of a PCL issue with subsequent versions supporting .NET 4.0 (see ServiceStack NuGet update 4.0.22 to 4.0.31 caused errors on deployment)
  • Add a C# class, named AppHost and include the following code
    using Funq;
    using ServiceStack;
    
    public class AppHost : AppHostBase
    {
       public AppHost()
          : base("TestStack", 
               typeof(MyServices).Assembly) 
       { 
       }
    
       public override void Configure(Container container)
       {
       }
    }
    
  • Now add another Class named MyServices and add the following code
    using ServiceStack;
    
    public class MyServices : Service
    {
       public object Any(Hello request)
       {
          return new HelloResponse 
          { 
             Result = "Hello, {0}!".Fmt(request.Name) 
          };
       }
    }
    
  • Add another Class name Hello and add the following code
    using ServiceStack;
    
    [Route("/hello/{Name}")]
    public class Hello : IReturn<HelloResponse>
    {
       public string Name { get; set; }
    }
    
  • Now add the last class, which is named HelloResponse and add the following code
    public class HelloResponse
    {
       public string Result { get; set; }
    }
    
  • Now add a Global Application Class, keep it named as Global and in the code behind, remove the existing class and methids and replace with the following
    public class Global : HttpApplication
    {
       protected void Application_Start(object sender, EventArgs e)
       {
          new AppHost().Init();
        }
    }
    
  • Finally we need to alter the Web.config to look like this
    <configuration>
      <system.web>
          <compilation debug="true" targetFramework="4.0" />
          <httpHandlers>
            <add path="*" type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*" />
          </httpHandlers>
          <pages controlRenderingCompatibilityVersion="4.0" />
        </system.web>
    
      <system.webServer>
        <modules runAllManagedModulesForAllRequests="true" />
        <validation validateIntegratedModeConfiguration="false" />
        <urlCompression doStaticCompression="true" doDynamicCompression="false" />
        <handlers>
          <add path="*" name="ServiceStack.Factory" type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" />
        </handlers>
      </system.webServer>
    
    </configuration>
    

Run the application via Visual Studio and you should see the metadata page showing the Hello operation. To double check the operation works simply change the URL in your preferred browser to

http://localhost:49810/Hello/World

Obviously change the port to the one supplied by iisexpress.

Implementing a client and services with ServiceStack

ServiceStack, is a lightweight framework for writing web services.

Getting Started

Let’s just create a “default” service and client first.

See Create your first WebService for information on creating your first service. I’ll replicate some of the steps here also…

  • Using Visual Studio, Tools | Extensions and Updated, search for ServiceStack templates and install (if not already installed)
  • Create a new ServiceStack ASP.NET Empty project (target .NET 4.6)
  • Build and run

By default this will create a service which accepts a Hello object and returns a HelloResponse (for reference, here’s those classes)

public class HelloResponse
{
   public string Result { get; set; }
}

[Route("/hello/{Name}")]
public class Hello : IReturn<HelloResponse>
{
   public string Name { get; set; }
}

Note: The Hello class “implements” IReturn (which actually is just a marker interface, i.e. no methods) to give our client the ability to pass Hello objects (and hence have type safety etc.) to the service and inform the client what response to expect.

We can test the service using our web browser, for example my server is running on the localhost on port 50251, so typing the URL http://localhost:50251/Hello/Bob (note: the Route attribute defines the “route” to the specific method etc. hence you can see how this maps to the URL we used) will result in the Hello class being run with the argument Bob as the Name. The response will be displayed in the browser, along the lines of Result Hello, Bob!. This is the same result we’ll be expecting from our client app.

But how did we get the result “Hello, World!” from the server? This is where the MyService implementation in the generated server code comes in. When the server’s AppHost starts up it looks for services. These are then used to intercept/generate calls and responses. See the code below (copied from the generated code)

public class MyServices : Service
{
   public object Any(Hello request)
   {
      return new HelloResponse 
      { 
         Result = "Hello, {0}!".Fmt(request.Name) 
      };
   }
}

Let’s create a client app.

  • Create a Console application
  • From the Package Manager Console, run Install-Package ServiceStack.Client
  • Copy the Hello and HelloResponse classes from the service to the client
  • In the Main method add the following
    var client = new JsonServiceClient("http://localhost:50251/");
    var resp = client.GetAsync(new Hello { Name = "Bob" })
       .Success(tsk =>
       {
          Console.WriteLine(tsk.Result);
       })
       .Error(e =>
       {
          Console.WriteLine(e.Message);
       });
    
    Console.ReadLine();
    

For the client Api we could have called the service using

var resp = client.GetAsync<HelloResponse>("/hello/World");

if preferred, and this will do away for the need for the Hello class in the client.