ServiceStack v4.0.34

Add TypeScript Reference!

The next typed client supported in Add ServiceStack Reference is TypeScript!

Add TypeScript Reference

TypeScript is a superset of JavaScript that enhances it with an optional type system for annotating JavaScript source code - bringing many of the code-analysis, insights and tooling benefits that we get to enjoy developing in a typed language like C#/VS.NET. We're excited to also be able to bring these benefits to TypeScript Client Apps consuming ServiceStack Services!

TypeScript DTO Interface Declarations

The TypeScript Native Types feature takes a non-invasive approach in that they're made available in the form of a .d.ts TypeScript declaration file. TypeScript declarations are pure static type annotations, i.e. they don't generate any code or otherwise have any effect on runtime behavior. This makes them useful as a non-invasive drop-in into existing JavaScript code where it's used to provide type annotations and intelli-sense on existing JavaScript objects, letting you continue using your existing data types and Ajax libraries.

TypeScript Reference Example

Lets walk through a simple example to see how we can use ServiceStack's TypeScript DTO annotations in our JavaScript clients. Firstly we'll need to add a TypeScript Reference to the remote ServiceStack Service by right-clicking on your project and clicking on Add > TypeScript Reference... (as seen in the above screenshot).

This will import the remote Services dtos into your local project which ends up looking similar to:

/* Options:
Date: 2014-12-08 17:24:02
Version: 1
BaseUrl: http://api.example.com

GlobalNamespace: dtos
//MakePropertiesOptional: True
//AddServiceStackTypes: True
//AddResponseStatus: False
*/

declare module dtos
{
    // @Route("/hello")
    // @Route("/hello/{Name}")
    interface Hello extends IReturn<HelloResponse>
    {
        // @Required()
        name:string;
        title?:string;
    }

    interface HelloResponse
    {
        result?:string;
    }

    interface IReturn<T> {}
    ...
}

Initially the single TypeScript module that contains all the DTO definitions will default to the C#/.NET ServiceModel namespace, but this can be made more readable in client apps by uncommenting in the header properties:

GlobalNamespace: dtos

Looking at the types we'll notice the DTO's are just interface type definitions with any .NET attributes added in comments using AtScript's proposed meta-data annotations format. This lets you view helpful documentation about your DTO's like the different custom routes available for each Request DTO.

By default DTO properties are optional but can be made a required field by annotating the .NET property with the [Required] attribute or by uncommenting MakePropertiesOptional: False in the header comments which instead defaults all properties as required.

Property names always reflect to match the remote servers JSON Serialization configuration, i.e. will use camelCase properties when the AppHost is configured with:

JsConfig.EmitCamelCaseNames = true;

Referencing TypeScript DTO's

Once added to your project, use VS.NET's JavaScript Doc Comments to reference the TypeScript definitions in your .ts scripts. The example below shows how to use the above TypeScript definitions to create a typed Request/Response utilizing jQuery's Ajax API to fire off a new Ajax request on every keystroke:

/// <reference path="MyApis.dtos.d.ts"/>
...

<input type="text" id="txtHello" data-keyup="sayHello" /> 
<div id="result"></div>

<script>
$(document).bindHandlers({
    sayHello: function () {
        var request: dtos.Hello = {};
        request.title = "Dr";
        request.name = this.value;
        
        $.getJSON(createUrl("/hello", request), request, 
            function (r: dtos.HelloResponse) {
                $("#result").html(r.result);
            });
    }
});

function createUrl(path: string, params: any): string {
    for (var key in params) {
        path += path.indexOf('?') < 0 ? "?" : "&";
        path += key + "=" + encodeURIComponent(params[key]);
    }
    return path;
}
</script>

Here we're just using a simple inline createUrl() function to show how we're creating the url for the GET HTTP Request by appending all Request DTO properties to the QueryString, resulting in a HTTP GET Request that looks like:

/hello?title=Dr&name=World

There's also a new $.ss.createUrl() API in ss-utils.js which also handles .NET Route definitions where it will populate any variables in the /path/{info} instead of adding them to the ?QueryString, e.g:

$(document).bindHandlers({
    sayHello: function () {
        var request: dtos.Hello = {};
        request.title = "Dr";
        request.name = this.value;
        
        $.getJSON($.ss.createUrl("/hello/{Name}", request), request, 
            function (r: dtos.HelloResponse) {
                $("#result").html(r.result);
            });
    }
});

Which results in a HTTP GET request with the expected Url:

/hello/World?title=Dr

ss-utils.d.ts

To coincide with the new TypeScript Reference support, we've also included a TypeScript declaration file for ss-utils.js. that's also available as an embedded resource in ServiceStack.dll at /js/ss-utils.d.ts.

Upgrade ServiceStackVS

To take advantage of Add TypeScript Reference feature, Upgrade or Install ServiceStackVS VS.NET Extension:

VS.NET Gallery Download

If you already have ServiceStackVS installed, uninstall it first from Tools -> Extensions and Updates... then in the Extensions dialog find ServiceStackVS -> Uninstall.

Auto Batched Requests

One of the best ways to improve performance, efficiency and reduce latency is to minimize the number of network requests required, which is one of the reasons we've always encouraged Coarse-grained API designs - which also lend themselves to better encapsulation and re-use.

Another common use-case that can be improved are clients making multiple requests to the same API, but due to the lack of a better alternative batched API or control over the server implementation, will default to making multiple N+1 web service requests - thanks to ServiceStack's message-based design, that better alternative now exists :)

All Services now support Batching!

With the introduction of Auto Batched Requests in this release, all ServiceStack Services now include implicit support for batching, automatically, without any additional effort - where multiple requests of the same type can be sent together in a single HTTP Request.

This is now enabled in all .NET Service Clients via the new SendAll() and SendAllOneWay() API's, e.g:

var client = new JsonServiceClient(BaseUrl);
var requests = new[]
{
    new Request { Id = 1, Name = "Foo" },
    new Request { Id = 2, Name = "Bar" },
    new Request { Id = 3, Name = "Baz" },
};

List<Response> responses = client.SendAll(requests);

The API works as you would expect where multiple requests can be sent together and the Service Client will return a list of all responses in the same order as the requests were sent.

And on the back-end, your Services are none the wiser, remaining focused on handling a single Request DTO. In the case below the Service does some work then stores the response in Redis before returning it:

public class MyServices : Service
{
    public object Any(Request request)
    {
        var response = DoWork(request);
        Redis.Store(response);
        return response;
    }
}

Request Execution Flow

From the Service's point of view nothing changes. Request DTO's still get executed one at a time, through all existing filters just as if they we're sent on their own. They're just delivered together within a single HTTP Request, in this case POST'ed as JSON to the /json/reply/Request[] pre-defined route:

Auto Batched Requests

Custom Batched Requests Implementations

If a client was previously calling the same API 100 times, the existing overhead of 100 HTTP Requests would be reduced to just 1 HTTP Request when batched. Although the above Service would still be calling Redis 100 times to store each Response.

If later this API has become really hot and you want to improve it even further, you can later add a custom implementation that accepts a Request[] and it will only get called once, with access to all the Request DTO's together. In this case we can use a custom implementation and take advantage of Redis's own batched API's and reduce this further to 1 Redis operation:

public class MyServices : Service
{
    public object Any(Request request)
    {
        var response = DoWork(request);
        Redis.Store(response);
        return response;
    }
    
    public object Any(Request[] requests)
    {
        var responses = requests.Map(DoWork);
        Redis.StoreAll(responses);
        return responses;
    }
}

So with this custom implementation we've gone from 100 HTTP Requests + 100 Redis Operations to 1 HTTP Request + 1 Redis Operation.

Another scenario where you may consider using a Custom Batched Implementation is if you wanted to execute all requests within a single RDBMS transaction, which with OrmLite would look something like:

public class MyServices : Service
{
	public object Any(Request request)
	{
	    var response = DoWork(request);
	    Db.Insert(request);
	    return response;
	}
	
	public object Any(Request[] requests)
	{
	    using (var trans = Db.OpenTransaction())
	    {
	        var responses = requests.Map(x => Any(x));	

	        trans.Commit();
	        return responses;
	    }
	}
}

Just like with normal Batched Requests, Custom Batched implementations are still executed one at a time through all request/response filters, taking advantage of any existing logic/validation. If you instead only wanted multiple Requests to be treated as a single Request through the entire pipeline you can create a new Request DTO that inherits from List<TRequest> which then gets treated as a normal Request DTO e, g:

public class Requests : List<Request> {}

public class MyServices : Service
{
	...
    public object Any(Requests requests)
    {
        var responses = requests.Map(DoWork);
        Redis.StoreAll(responses);
        return responses;
    }
}

More examples of Auto Batched Requests and its behavior can be found in the ReplyAllTests suite.

New ReactJS App Template!

The new ServiceStackVS ReactJS App template shares the same approach for developing modern Single Page Apps in VS.NET as the existing AngularJS App template by leveraging the node.js ecosystem for managing all aspects of Client App development utilizing the best-in-class libraries:

  • npm to manage node.js dependencies (bower, grunt, gulp)
  • Bower for managing client dependencies (angular, jquery, bootstrap, etc)
  • Grunt as the primary task runner for server, client packaging and deployments
  • Gulp used by Grunt to do the heavy-lifting bundling and minification

The templates conveniently pre-configures the above libraries into a working out-of-the-box solution, including high-level grunt tasks to take care of the full-dev-cycle of building, packaging and deploying your app:

  • 01-run-tests - Runs Karma JavaScript Unit Tests
  • 02-package-server - Uses msbuild to build the application and copies server artefacts to /wwwroot
  • 03-package-client - Optimizes and packages the client artefacts for deployment in /wwwroot
  • 04-deploy-app - Uses MS WebDeploy and /wwwroot_buld/publish/config.json to deploy app to specified server

React Chat

To help to get started with the ReactJS App VS.NET template and learn React, we've rewritten ServiceStack Chat ServerEvents demo using React:

React Chat

Intro to developing apps with React and Reflux

The React Chat GitHub Repository also includes a guide of Facebook's React library and Flux pattern and walks through how to use them to put together a React-based App - making use of the scripts in the ServiceStackVS template along the way to optimize, package and deploy React Chat.

Redis

Heartbeats enabled on RedisPubSubServer

RedisPubServer now maintains periodic heartbeats with Redis and will auto-reconnect when it detects a connection has dropped. Heartbeats can be disabled by setting HeartbeatInterval=null.

The new heartbeat support should also improve resiliency in components powered by RedisPubServer, including RedisMqServer and RedisServerEvents.

Updated RedisManagerPool Pooling Behavior

RedisManagerPool is our new streamlined version of PooledRedisClientManager with a simplified API courtesy of the configuration moving into the Redis Connection String. As an new and alternative Pooled Client Manager we've taken the opportunity to tweak the pooling behavior so that any connections required after the maximum Pool size has been reached will be created and disposed outside of the Pool.

This is different to PooledRedisClientManager which imposes a maximum connection limit and when its maximum pool size has been reached will instead block on any new connection requests until the next RedisClient is released back into the pool. If no client became available within PoolTimeout, a Pool Timeout exception will be thrown.

By not being restricted to a maximum pool size, the new pooling behavior in RedisManagerPool lets it maintain a smaller connection pool size at the cost of potentially having a higher opened/closed connection count.

Redis HTTP Request Logger

A new RedisRequestLogger is available in the ServiceStack.Server NuGet package to provide an alternative back-end for the Request Logs Feature to log HTTP Requests with Redis so they remain available after AppDomain restarts.

RequestLogsFeature can be configured to use the new RedisRequestLogger with:

Plugins.Add(new RequestLogsFeature {
    RequestLogger = new RedisRequestLogger(
	    container.Resolve<IRedisClientsManager>(), capacity:1000)
});

OrmLite

Multiple Self References

Supports for multiple Self References of the same type has been added where if there are multiple fields containing [References] to the same type, OrmLite will fallback to matching properties based on {PropertyName}Id property naming convention, e.g:

public class Customer
{
    [AutoIncrement]
    public int Id { get; set; }
    public string Name { get; set; }

    [References(typeof(CustomerAddress))]
    public int? HomeAddressId { get; set; }

    [References(typeof(CustomerAddress))]
    public int? WorkAddressId { get; set; }

    [Reference]
    public CustomerAddress HomeAddress { get; set; }

    [Reference]
    public CustomerAddress WorkAddress { get; set; }
}

Self References now also support mixing and matching of property names and DB Alias naming conventions

Support for CROSS JOIN's

New CrossJoin API's were added to SqlExpression that works similarly to other JOIN's, e.g:

var q = db.From<TableA>()
          .CrossJoin<TableB>()
          .OrderBy<TableB>(x => x.Id);

var results = db.Select<CrossJoinResult>(q);

OpenDbConnectionString()

A new OpenDbConnectionString API was added to open adhoc connection strings using the same OrmLiteConnectionFactory and DialectProvider instance. This makes creating Multi Tenant DB Factories a little easier, e.g:

public class MultiTenantDbFactory : IDbConnectionFactory
{
    private readonly IDbConnectionFactory dbFactory;

    public MultiTenantDbFactory(IDbConnectionFactory dbFactory)
    {
        this.dbFactory = dbFactory;
    }

    public IDbConnection OpenDbConnection()
    {
        var tenantId = RequestContext.Instance.Items["TenantId"] as string;
        return tenantId != null
            ? dbFactory.OpenDbConnectionString(GetConnectionString(tenantId))
            : dbFactory.OpenDbConnection();
    }

    public IDbConnection CreateDbConnection()
    {
        return dbFactory.CreateDbConnection();
    }
}

A complete Multi Tenant OrmLite example can be found in MultiTennantAppHostTests.cs

Oracle Provider returns to form

Thanks to @TroyDycavinu-AI efforts, the Oracle OrmLite Provider test suite is back in the green

Razor

RenderToAction()

The new RenderToAction() method lets you execute a Service in a Razor View and include it's rendered partial view using just a relative Url:

@Html.RenderAction("/products/1")

It also takes an optional view name if you want a different view than the default:

@Html.RenderAction("/products/1", "CustomProductView")

An alternative approach to include another Services View is with Html.Partial() specifying which view and model you want to render:

@Html.Partial("GetProduct", 
    base.ExecuteService<ProductService>(s => s.Any(new GetProduct { Id = 1 })))

Where ExecuteService is a shorthand wrapper around using ResolveService<T> in a using block:

@{
   Response response = null;
   using (var service = base.ResolveService<ProductService>())
   {
       response = service.Any(new GetProduct { Id = 1 });
   }
}
@Html.Partial("GetProduct", response)

Relative Content Partials

In addition to Shared Razor Views in /Views you can now include Partials relative to the containing Razor Content Page:

@Html.Partial("LocalPartial", model)
@Html.Partial("SubDir/NestedPartial", model)

AutoQuery

Unlimited Custom Table Joins

AutoQuery now supports joining any number of tables together by annotating the Request DTO with multiple IJoin<> interface markers e.g:

public class MyQuery : QueryBase<Table>, 
	IJoin<T1,T2>,
	IJoin<T2,T3>,
	IJoin<T3,T4>,
	//... 
{
}

Add ServiceStack Reference

  • DTO Interfaces are now included in all C#, F#, VB.NET and TypeScript Native Type providers.
  • F# developers can specify GlobalNamespace in their generated .dtos.fs

Authentication

The RavenDbUserAuthRepository now supports specialization so it can be used to persist extended custom UserAuth and UserAuthDetails types, e.g:

public class CustomRavenDbAuthRepository 
    : RavenDbUserAuthRepository<MyUserAuth, MyUserAuthDetails>
{
	//...
}

Sessions

If needed, Sessions can be injected or modified in ASP.NET hosts with:

HttpContext.Current.Items[ServiceExtensions.RequestItemsSessionKey] =
    new AuthUserSession { ... };

New Session API's added:

  • IRequest.RemoveSession(sessionId) - Remove the Session
  • IRequest.GetSessionTimeToLive() - Time remaining before current Session expires
  • ICacheClient.GetSessionTimeToLive(id) - Time remaining before specified Session expires

Other Features

  • SOAP no longer emits the UTF8 BOM by default, overridable in Config.XmlWriterSettings
  • CORS Support added in Server Events raw HTTP Handlers
  • C# Server Events Client auto restarts when Heartbeat has elapsed the Servers IdleTimeoutMs
  • Added workaround for supporting Mono with Redis SSL

Breaking Changes

PCL NuGet Packages Merged

The ServiceStack.Client.Pcl and ServiceStack.Stripe.Pcl NuGet packages have been merged into the main ServiceStack.Client and ServiceStack.Stripe NuGet packages and as a result will no longer receive future updates. If you're using them please update your NuGet references.

Refactored Redis Client API's

IRedisClient.GetTimeToLive() now returns a TimeSpan? will will return:

  • null if no key exists
  • TimeSpan.MaxValue if there is no expiry set on the key
  • or a TimeSpan value with the time remaining before the key is set to expire

KeepAliveRetryAfterMs has been renamed to WaitBeforeNextRestart in RedisPubSubServer and the classes that use it: RedisServerEvents and RedisMqServer.