ServiceStack 4 Cookbook
上QQ阅读APP看书,第一时间看更新

Utilizing the original HTTP request

There are a few types of situations when you might need to access the original ASP.NET HttpRequest. You might be migrating to ServiceStack from a large existing WCF code base or another framework where this object was used a lot. You might be required to integrate with a legacy or custom services/clients that are unable to be changed, and your web service endpoints must adhere to a specific set of requests and responses. In this recipe, we will go over some of the options you have when using the ServiceStack framework—the access and use of the original HTTP request object as well as some ways you can leverage how ServiceStack binds values to your request data transfer objects.

Getting ready

You'll need to have your ServiceStack project up and running; please see Creating a ServiceStack solution with VisualStudio and NuGet in Appendix A, Getting Started.

How to do it…

Accessing the original ASP.NET HttpRequest is very simple to do as it's exposed from your web service that inherits from Service, as follows:

var originalRequest = this.Request.OriginalRequest as HttpRequest;

As you can see, it's really straightforward to get access to the underlying ASP.NET HttpRequest. This could make transitioning or integration with some existing applications easier, but something important to note is the Request object itself in the previous code.

How it works…

The IRequest object that Service exposes in the Service base class wraps and exposes many of the same properties with some helpful extension methods to try and make your life a bit easier. If you need to deal with the specific implementation of the original Request object, it can be used as shown previously, but the type of the original request might not always be an HttpRequest object. ServiceStack helps with this abstraction by providing useful methods that work with the different original requests.

The following are some really simple examples of common tasks you might perform, most of which are the same or very close to how developers interact with the original request. This makes picking up ServiceStack more straightforward for developers who are well-versed at writing classic ASMX HTTP handlers or WCF services, as follows:

string queryStringValue = this.Request.QueryString["CustomQueryString"];
string formData = this.Request.FormData;
string body = this.Request.GetRawBody();
string headerValue = this.Request.Headers["CustomHeader"];
IHttpFile[] files = this.Request.Files;

If you do have some experience with dealing with the ASP.NET HttpRequest object, most of the preceding code should look pretty familiar. If you don't and, for example, just the data in bolded lines is inserted in your custom request DTO, you're in luck!

If your request DTO has property names that match that of the query string, form data entry, or key/value pair in the body of a request, ServiceStack will automatically bind these values.

For example, if there was an unchangeable requirement that every request object can only be populated by query string values, as long as those keys match, ServiceStack will automatically bind these values, as follows;

public class LegacyHelloWorld : Service
{
    public object Get(LegacyHelloWorldRequest request)
    {
        return "Hello, " + request.Name;
    }
}
[Route("/hello")]
[Route("/hello/{Name}")]
public class LegacyHelloWorldRequest
{
    public string Name { get; set; }
}

If we perform a GET request in a browser to hit this service, /hello/Reader will result in the expected value of Hello, Reader. However, since we have added the Route("/hello") route, it will process the same request with /hello?Name=Reader, and we will get the same Hello, Reader message back. This is the same for FormData as well! If we were processing a POST request, the body of the request would also be processed to populate this value.

You might be in the situation that the query strings, form data, or the body of the request might have characters you really don't want to have in your code. For example, if the same request and service has to bind to a HttpRequest with a JSON request that had users_friendly_name_1 as the Name property value, and you can't change what the client is sending, you can let ServiceStack know the name to bind to through the .NET DataContract and DataMember attributes, as follows:

[Route("/hello")]
[Route("/hello/{Name}")]
[DataContract]
public class LegacyHelloWorldRequest
{
    [DataMember(Name = "user_friendly_name_1")]
    public string Name { get; set; }
}

Now, if we send {"user_friendly_name_1":"Reader"} via Postman, we get Hello, Reader back, which we were expecting!

Note

Postman is a free extension for the Chrome browser, which can be easily used with ServiceStack thanks to the PostmanFeature() plugin. Postman allows developers to easily create HTTP requests to test web services. The ServiceStack plugin exposes an endpoint for Postman to automatically import all the types of valid requests that can be used with your services.

Postman is available from the Chrome Web Store.

The following screenshot depicts an example of the Postman feature plugin:

How it works…

Note

When using the DataContract and DataMember attributes, remember that you have to use both and that the original Name property still binds. Even though this allows you to potentially support new and old clients, be aware of possible collisions with other property names.

There's more…

If you do need access to IIS and Windows-specific properties like LogonUserIdentity for example, you will also need to make sure the service to which your host AppPool is configured is done correctly and ServiceStack has been enabled to resolve this correctly.

See also

The Accessing Windows identity information from ServiceStack for an intranet application recipe in Chapter 7, Security and Authentication.