v4.0.56 Released!

This is another release jam-packed with some killer features, the release notes are unfortunately quite longer than usual as the new features required more detail to describe what each does and understand how they work.

I’ll list the big points below to provide a quick overview, but if you can find the free time, please checkout the full
v4.0.56 Release Notes for the finer details of each feature.

ServiceStack VS Templates Update

React Desktop Apps received a major update with much faster Startup times on Windows that now features auto-updating support built-in courtesy of Squirrel Windows integration! Whilst the OSX App can now be built using Xamarin’s free Community Edition :smile:

We’re now all-in with React and TypeScript with both our VS.NET SPA React Templates modernized with TypeScript + JSPM. If you’re new to both, please checkout the comprehensive TypeScript + Redux walk through to get up and running quickly.

New AutoQuery Data

AutoQuery Data is an alternative implementation of AutoQuery for RDBMS but supports an Open Provider model which can be implemented to query multiple data source backends. The 3 data source providers available include:

  • MemorySource - for querying static or dynamic in-memory .NET collections, some of the included examples show querying a flat-file .csv file and a 3rd Party API that can also the throttled with configurable caching.
  • ServiceSource - a step higher than MemorySource where you can decorate the response of existing Services with AutoQuery’s rich querying capabilities.
  • DynamoDbSource - adds rich querying capabilities over an AWS DynamoDB Table making it much more productive than if you had to construct the query manually.

AutoQuery DynamoDB queries are also self-optimizing where it will transparently construct the most optimal query possible by looking at any Hash Id’s, Range Keys and Local Indexes populated in the Request to construct the most optimal DynamoDB QueryRequest or Scan Operation behind-the-scenes.

And since AutoQuery Services are just normal ServiceStack Services they get to take advantage of ServiceStack’s rich ecosystem around Services so with just the single AutoQuery DynamoDB Request DTO below:

[Route("/rockstar-albums")]
[CacheResponse(Duration = 60, MaxAge = 30)]
public class QueryRockstarAlbums : QueryData<RockstarAlbum>
{
    public int? Id { get; set; }         
    public int? RockstarId { get; set; }
    public string Genre { get; set; }
    public int[] IdBetween { get; set; }
}

We’ve declaratively created a fully-queryable DynamoDB AutoQuery Service that transparently executes the most ideal DynamoDB queries for each request, has it’s optimal representation efficiently cached on both Server and clients, whose Typed DTO can be reused as-is on the client to call Services with an end-to-end Typed API using any .NET Service Client, that’s also available to external developers in a clean typed API, natively in their preferred language of choice, accessible with just a right-click menu integrated inside VS.NET, Xcode, Android Studio, IntelliJ and Eclipse - serving both PCL Xamarin.iOS/Android as well as native iOS and Android developers by just Adding a ServiceStack Reference to the base URL of a remote ServiceStack Instance - all without needing to write any implementation!

HTTP Caching

HTTP Caching is another big feature we expect to prove extremely valuable which much improves story around HTTP Caching that transparently improves the behavior of existing ToOptimized Cached Responses, provides a typed API to to opt-in to HTTP Client features, introduces a simpler declarative API for enabling both Server and Client Caching of Services and also includes Cache-aware clients that are able to improve the performance and robustness of all existing .NET Service Clients - functionality that’s especially valuable to bandwidth-constrained Xamarin.iOS / Xamarin.Android clients offering improved performance and greater resilience.

Cache-aware Service Clients

You can now create cache-aware versions of all .NET Service Clients that respects any caching directives
returned by your Server using the .WithCache() extension methods, e.g:

IServiceClient client = new JsonServiceClient(baseUrl).WithCache(); 

IServiceClient client = new JsonHttpClient(baseUrl).WithCache();

Cache-aware Service Clients can dramatically improve performance by eliminating server requests entirely as well as reducing bandwidth for re-validated requests. They also offer an additional layer of resiliency as re-validated requests that result in Errors will transparently fallback to using pre-existing locally cached responses. For bandwidth-constrained environments like Mobile Apps they can dramatically improve the User Experience and as they’re available in all supported PCL client platforms.

@jezzsantos also wrote a comprehensive overview about HTTP Caching in general and goes through the process of how he developed an alternative caching solution within ServiceStack in his epic Caching Anyone post.

Service Gateway

The new IServiceGateway is another valuable capability that despite being trivial to implement on top of ServiceStack’s existing message-based architecture, opens up exciting new possibilities for development of loosely-coupled Modularized Service Architectures.

The Service Gateway is available from base.Gateway in both sync:

public object Any(GetCustomerOrders request)
{
    return new GetCustomerOrders {
        Customer = Gateway.Send(new GetCustomer { Id = request.Id }),
        Orders = Gateway.Send(new QueryOrders { CustomerId = request.Id })
    };
}

and async versions:

public async Task<GetCustomerOrdersResponse> Any(GetCustomerOrders request)
{
    return new GetCustomerOrdersResponse {
        Customer = await Gateway.SendAsync(new GetCustomer { Id = request.Id }),
        Orders = await Gateway.SendAsync(new QueryOrders { CustomerId = request.Id })
    };
}

The benefit of the Gateway is that the same above code will continue to function even if you later decided to split out your Customer and Order subsystems out into different Micro Services.

The Service Gateway also allows plugging in a Discovery Service for your Micro Services where you can happily just send Request DTO’s to call Services and the Discovery Service will transparently route it to the most available Service.

We’re extremely fortunate to have @Mac and @rsafier both jump in with Service Discovery solutions straight out-of-the-gate which you can find more about in their GitHub Project home pages:

Super CSV Support

We’ve now implemented CSV deserialization support so now all your Services can accept CSV payloads in addition to serializing to .csv. As a tabular data format it’s especially useful when your Service accepts Lists of POCO’s such as in Auto Batched Requests where it’s now the most compact text data format to send them with using either the new CsvServiceClient or .PostCsvToUrl() HTTP Utils extension method.

A feature that sets ServiceStack’s CSV support apart is that it’s built on the compact and very fast JSV Format which not only can deserialize a tabular flat file of scalar values at high-speed, it also supports deeply nested object graphs which are encoded in JSV and escaped in a CSV field.

Which opens a number of interesting use-cases as you can now maintain rich code or system data in .csv flat-files to easily query them in AutoQuery Services, making it a great option for structured logging as they’re now easily parsable, queryable with AutoQuery Data, analyzed with your favorite Spreadsheet or imported using CSV features or data migration tooling for your preferred RDBMS.

Given these useful properties we’ve developed a CSV Request Logger that can be registered with:

Plugins.Add(new RequestLogsFeature {
    RequestLogger = new CsvRequestLogger(),
});

To store request and error logs into daily logs to the following overridable locations:

  • requestlogs/{year}-{month}/{year}-{month}-{day}.csv
  • requestlogs/{year}-{month}/{year}-{month}-{day}-errors.csv

Error logs are also written out into a separate log file as it can be useful to view them in isolation.

Virtual FileSystem

To efficiently support Appending to existing files as needed by the CsvRequestLogger we’ve added new
AppendFile API’s and implementations for Memory and FileSystem Virtual File Providers:

interface IVirtualFiles
{
    void AppendFile(string filePath, string textContents);
    void AppendFile(string filePath, Stream stream);
}

OrmLite

New UpdateAdd API’s provides several Typed API’s for updating existing values:

//Increase everyone's Score by 3 points
db.UpdateAdd(new Person { Score = 3 }, fields: x => x.Score); 

//Remove 5 points from Jackson Score
db.UpdateAdd(new Person { Score = -5 }, x => x.Score, x => 
    where: x.LastName == "Jackson");

//Graduate everyone and increase everyone's Score by 2 points 
var q = db.From<Person>().Update(x => new { x.Points, x.Graduated });
db.UpdateAdd(new Person { Points = 2, Graduated = true }, q);

Deprecating Legacy OrmLite API’s

We’re going to gracefully deprecate OrmLite’s legacy API’s by first deprecating them in this release to notify which API’s are earmarked to move, then in a future release we’ll move the extension methods under the ServiceStack.OrmLite.Legacy namespace to move them out of OrmLite’s default namespace.

The deprecated API’s include those ending with *Fmt which uses C#'s old-style string formatting, e.g:

var tracks = db.SelectFmt<Track>("Artist = {0} AND Album = {1}", 
  "Nirvana", 
  "Nevermind");

Ideally they should be replaced with the parameterized API’s below:

var tracks = db.Select<Track>(x => x.Artist == "Nirvana" && x.Album == "Nevermind");

var tracks = db.Select<Track>("Artist = @artist AND Album = @album", 
    new { artist = "Nirvana", album = "Nevermind" });
    
var tracks = db.SqlList<Track>(
    "SELECT * FROM Track WHERE Artist = @artist AND Album = @album",
    new { artist = "Nirvana", album = "Nevermind" });

The other API’s that have been deprecated are those that inject an SqlExpression<T> e.g:

var tracks = db.Select<Track>(q => 
    q.Where(x => x.Artist == "Nirvana" && x.Album == "Nevermind"));

Which should be changed to passing in the SqlExpression<T> by calling db.From<T>, e.g:

var tracks = db.Select(db.From<Track>() 
    .Where(x => x.Artist == "Nirvana" && x.Album == "Nevermind"));

Poco Dynamo

ServiceStack’s POCO-friendly DynamoDB client has added support for DynamoDB’s UpdateItem which lets you modify existing attributes. The easiest API to use is to pass in a partially populated POCO with containing any non-default values you want updated:

db.UpdateItemNonDefaults(new Customer { Id = customer.Id, Age = 42 });

There’s also a more flexible API to support each of DynamoDB UpdateItem operations, e.g:

db.UpdateItem(customer.Id, 
    put: () => new Customer {
        Nationality = "Australian"
    },
    add: () => new Customer {
        Age = -1
    },
    delete: x => new { x.Name, x.Orders });

ServiceStack.Redis

Additional resiliency was added in ServiceStack.Redis which can now handle re-connections for broken TCP connections happening in the middle of processing a Redis Operation.

New API’s were added to remove multiple values from a Sorted Set:

interface IRedisClient {
    long RemoveItemsFromSortedSet(string setId, List<string> values);
} 

interface IRedisNativeClient {
    long ZRem(string setId, byte[][] values);
}

ServiceStack IDEA

The ServiceStack IDEA Android Studio plugin was updated to support Android Studio 2.0.

Community

There were a number of community plugins published in this release, check out their GitHub projects for
more info:

Other Features

  • Changed ServiceStack.Interfaces to Profile 328 adding support Windows Phone 8.1
  • New IHasStatusDescription can be added on Exceptions to customize their StatusDescription
  • New IHasErrorCode can be used to customize the ErrorCode used, instead of its Exception Type
  • New AppHost.OnLogError can be used to override and suppress service error logging
3 Likes

This topic is now pinned globally. It will appear at the top of its category and all topic lists until it is unpinned by staff for everyone, or by individual users for themselves.

This topic is now unpinned. It will no longer appear at the top of its category.