Book Image

Mastering ServiceStack

By : Andreas Niedermair
Book Image

Mastering ServiceStack

By: Andreas Niedermair

Overview of this book

Table of Contents (13 chapters)

The processing chains of ServiceStack


The ServiceStack services can be hosted in an HTTP and Message Queue context, hence there are two different processing chains, which will be covered in the following two sections.

We will also cover request and response filters and annotations later in the chapter, which allow you to apply late-bound changes to your requests and responses.

HTTP context

The following contexts and their base classes are all derived from ServiceStack.ServiceStackHost; they can be used for your HTTP hosted service:

  • ASP.NET

    • ServiceStack.AppHostBase

  • Self-hosted

    • ServiceStack.AppHostListenerBase for single-threaded processing

    • ServiceStack.AppHostListenerPoolBase, ServiceStack.AppSelfHostBase and ServiceStack.AppHostListenerSmartPoolBase for multithreaded processing, where the former is utilizing the .NET Thread Pool and the others Smart Thread Pool (https://smartthreadpool.codeplex.com/) for queuing their work items

The pipeline is the same for every scenario, as shown in the following diagram:

Before any request goes into the ServiceStack pipeline, the functions in your AppHost's RawHttpHandlers are executed and the result is in the favor of further processing in ServiceStack if the value is not null. The processing in ServiceStack is done in the following order:

  1. The path is checked against existing routes (by attribution and convention). If none is matching, the delegates added to the CatchAllHandlers property are used for probing.

  2. All the delegates added to the PreRequestFilters property are executed, which cannot access the RequestDTO yet though.

  3. The content (Query String, Form Data, POST payload …) is deserialized into the RequestDTO either by default binding or a custom RequestBinder predicate.

  4. All delegates added to the RequestConverters collection are executed.

  5. All the RequestFilterAttribute annotations with a Priority less than zero are executed.

  6. All the delegates added to the GlobalTypedRequestFilters property and GlobalRequestFilters property are executed.

  7. All the RequestFilterAttribute annotations with a Priority greater than or equal to zero are executed.

  8. All delegates added to the ResponseConverters collection are executed.

  9. Then the registered ServiceStack.Web.IServiceRunner object calls OnBeforeExecute, your service method, OnAfterExecute and HandleException.

  10. All the ResponseFilterAttribute annotations with a Priority less than zero are executed.

  11. All the delegates added to the GlobalTypedResponseFilter property and GlobalResponseFilters property are executed.

  12. All the ResponseFilterAttribute annotations with a Priority greater than or equal to zero are executed.

  13. Finally OnEndRequest and OnEndRequestCallback is called and the response is written to the HTTP stream.

Message Queue context

The following MQ server implementations are available (the packages are listed in brackets for easier searching on NuGet) for your ServiceStack service:

  • ServiceStack.RabbitMq.RabbitMqServer (ServiceStack.RabbitMq)

  • ServiceStack.Messaging.Redis.RedisMqServer (ServiceStack.Server)

  • ServiceStack.Messaging.Redis.RedisTransientMessageService (ServiceStack.Server)

  • ServiceStack.Messaging.Rcon.Server (ServiceStack.Server)

  • ServiceStack.Messaging.InMemoryTransientMessageService (ServiceStack)

Note

The specific messaging implementations are described in detail in Chapter 3, Asynchronous Communication between Components.

In contrast to the processing chain of an HTTP context, the steps in an MQ context are as follows:

  1. All delegates added to the RequestConverters collection are executed.

  2. First all the delegates added to the GlobalTypedMessageRequestFilters property and GlobalMessageRequestFilters property are executed.

  3. Then the registered ServiceStack.Web.IServiceRunner object calls OnBeforeExecute, your service method, OnAfterExecute and HandleException.

  4. All delegates added to the ResponseConverters collection are executed.

  5. All the delegates added to the GlobalTypedMessageResponseFilter property and GlobalMessageResponseFilters property are executed.

  6. Finally the response is returned to the MQ.

    Tip

    Some ServiceStack MQ server classes provide customized hooks to filter requests and responses, giving you specialized possibilities to customize your pipeline.

In contrast to this, you can easily combine an MQ service and an HTTP service and leverage a trimmed-down processing pipeline of the HTTP service. This is possible as one of the core concepts of ServiceStack is the Message Pattern, which comes quite handy in this scenario:

public class AppHost : ServiceStack.AppSelfHostBase
{
  public AppHost()
    : base ("Ticket Service",
            typeof (TaskService).Assembly)
  { }

  public override void Configure(Funq.Container container)
  {
    var messageService = container.Resolve<ServiceStack.Messaging.IMessageService>();
    messageService.RegisterHandler<FindTasks> (this.ServiceController.ExecuteMessage);
    messageService.Start();
  }
}

The preceding code relies on the registration of a ServiceStack.Interfaces.IMessageService implementation, which gets resolved inside the Configure method. Then all the plumbing is done to register the handlers and start the MQ client.

If you do not want to provide an HTTP endpoint but still use the internals of ServiceStack such as the powerful IoC-Container, which is an unusual common use-case, you can use the generic BasicAppHost for an extended processing pipeline such as:

var basicAppHost = new ServiceStack.Testing.BasicAppHost(typeof(TaskService.Assembly))
{
  ConfigureAppHost = host =>
  {
    var messageService = host.Container.Resolve <ServiceStack.Interfaces.IMessageService>();
    messageService.RegisterHandler <FindTasks>(host.ServiceController.ExecuteMessage);
    messageService.Start();
  }
};

This is especially helpful in testing scenarios, where you want to deal with the endpoints directly.

Note

The other hook to configure your service is ConfigureContainer, which is executed after ConfigureAppHost. You need to be aware of this order when you are trying to resolve any dependency, as configuring the container is done afterwards.

Tip

Downloading the example code

You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.