v5.0.0 Released!

v5 Release Notes

The theme of this major v5 release is integration and unification with the newly released .NET Standard 2.0 which offers the broadest compatibility and stabilized API surface for .NET Core and the version we’ve chosen to standardize around.

We’ll do our best to summarize new features here but if you have time we encourage you to read the full v5 Release Notes, as this is a major version upgrade we recommend at least reviewing the v5 Changes and Migration Notes before upgrading. Whilst the user-facing source code impact is minimal, we’ve taken the opportunity of a major version window to perform some logical re-structuring and some potentially breaking changes from replacing PCL clients to use .NET Standard 2.0, moving .NET Framework implementations to different projects, making SOAP Support, Mini Profiler and Markdown Razor opt-in and to be able to utilize the latest NuGet package dependencies ServiceStack.RabbitMQ requires .NET v4.5.1 and ServiceStack.Azure requires .NET v4.5.2.

All .NET Standard builds have been upgraded to .NET Standard 2.0 where now both .Core and .Signed NuGet package variants have been unified into ServiceStack’s main NuGet packages - unifying them into a single suite of NuGet packages and release cadence. All .NET 4.5 builds are Strong Named by default using the servicestack.snk signing key that’s in the /src folder of each Project. The .NET Standard builds continue to remain unsigned so they can be built on each platform with .NET Core’s dotnet build command.

New .NET Core 2.0 and .NET Framework Project Templates!

ServiceStack’s maintains exceptional source compatibility between .NET Core and .NET Framework projects which is visible in our new .NET Core 2.0 and .NET Framework project templates where all templates utilize the same recommended Physical Project Structure, reference the same NuGet packages, share the same source code for its Server and Client App implementations as well as Client and Server Unit and Integration Tests.

v5 includes 11 new .NET Core 2.0 project templates for each of ServiceStack’s most popular starting templates. Each .NET Core 2.0 template has an equivalent .NET Framework template except for ServiceStack’s Templates WebApp which is itslef a pre-built .NET Core 2.0 App that lets you develop Web Applications and HTTP APIs on-the-fly without any compilation.

All .NET Core 2.0 Templates can be developed using your preferred choice of either VS Code, VS.NET or JetBrains Project Rider on your preferred Desktop OS. Given the diverse ecosystem used to develop .NET Core Applications, the new Project Templates are being maintained on GitHub and made available via our new dotnet-new command-line utility, installable from npm with:

$ npm install -g @servicestack/cli

This makes the dotnet-new command globally available which can be run without arguments to view all templates available:

That can be used to create new projects with:

$ dotnet-new <template-name> <project-name>

Example of creating a new Vue SPA project called Acme:

$ dotnet-new vue-spa Acme

The resulting Acme.sln can be opened in VS 2017 which will automatically restore and install both the .NET and npm packages upon first load and build.

If using JetBrains Rider the npm packages can be installed by opening package.json and clicking on the “npm install” tooltip on the bottom right. In VS Code you’ll need to run npm install manually from the command-line.

ServiceStackVS VS.NET Templates Updated

The VS.NET Templates inside ServiceStackVS have also been updated to use the latest .NET Framework templates which you can continue to use to create new projects within VS.NET. For all other IDEs and non-Windows Operating Systems you can use the cross-platform dotnet-new tooling to create new .NET Core 2.0 Projects.

.NET Core 2.0 TypeScript Webpack Templates

There’s a project template for each of the most popular Single Page Application JavaScript frameworks, including a new Angular 5.1 template built and managed using Angular’s new angular-cli tooling. All other SPA Templates (inc. Angular 4) utilize a modernized Webpack build system, pre-configured with npm scripts to perform all necessary debug, production and live watched builds and testing. The included gulpfile.js provides a Gulp script around each npm script so they can be run without the command-line, by running them using VS.NET’s built-in Task Runner Explorer GUI.

All SPA templates are configured to use Typed DTOs from TypeScript Add Reference with the generic @servicestack/client JsonServiceClient with concrete Type Definitions except for the Angular 5 template which uses Angular’s built-in Rx-enabled HTTP Client with ServiceStack’s ambient TypeScript declarations, as it’s often preferable to utilize Angular’s built-in dependencies when available.

All Single Page App Templates are available for both .NET Core 2.0 and ASP.NET Framework projects which can be live-previewed and used to create new projects using the template names below:

Angular 5 CLI Bootstrap Template

Angular 4 Material Design Lite Template

React 16 Webpack Bootstrap Template

Vue 2.5 Webpack Bootstrap Template

Aurelia Webpack Bootstrap Template

Optimal Dev Workflow with Hot Reloading

The Webpack templates have been updated to utilize Webpack’s DllPlugin which splits your App’s TypeScript source code from its vendor dependencies for faster incremental build times. With the improved iteration times our recommendation for development is to run a normal Webpack watched build using the dev npm (or Gulp) script:

$ npm run dev

Which will watch and re-compile your App for any changes. These new templates also include a new hot-reload feature which works similar to ServiceStack Templates hot-reloading where in DebugMode it will long poll the server to watch for any modified files in /wwwroot and automatically refresh the page. This provides a hot-reload alternative to npm run dev-server to run a Webpack Dev Server proxy on port http://localhost:3000

Deployments

When your App is ready to deploy, run the publish npm (or Gulp) script to package your App for deployment:

npm run publish

Which generates a production Webpack client build and dotnet publish release Server build to package your App ready for an XCOPY, rsync or MSDeploy deployment. We used rsync and supervisord to deploy each packaged Web template to our Ubuntu Server at the following URL:

http://<template-name>.web-templates.io

/wwwroot WebRoot Path for .NET Framework Templates

To simplify migration efforts of ServiceStack projects between .NET Core and .NET Framework, all SPA and Website Templates are configured to use .NET Core’s convention of /wwwroot for its public WebRoot Path. The 2 adjustments needed to support this was configuring ServiceStack to use the /wwwroot path in AppHost:

SetConfig(new HostConfig {
    WebHostPhysicalPath = MapProjectPath("~/wwwroot"),
});

Then instructing MSBuild to include all wwwroot\**\* files when publishing the project using MS WebDeploy which is contained in the Properties/PublishProfiles/PublishToIIS.pubxml of each project.

Website Templates

There are 3 templates for each of the different technologies that can be used with ServiceStack to develop Server HTML Generated Websites and HTTP APIs:

ASP.NET MVC

ServiceStack.Razor

ServiceStack Templates

Hot Reloading

Both razor and templates project enjoy Hot Reloading where in development a long poll is used to detect and reload changes in the current Template Page or static files in /wwwroot.

Empty Web and SelfHost Templates

Those who prefer starting from an Empty slate can use the web template to create the minimal configuration for a Web Application whilst the selfhost template can be used to develop Self-Hosting Console Apps. Both templates still follow our recommended physical project layout but are configured with the minimum number of dependencies.

Empty Web Template

Empty SelfHost Console App Template

.NET Core 2.0 ServiceStack WebApp Template

The only .NET Core 2.0 project template not to have a .NET Framework equivalent is templates-webapp as it’s a pre-built .NET Core 2.0 App that dramatically simplifies .NET Wep App development by enabling Websites and APIs to be developed instantly without compilation.

See templates.servicestack.net/docs/web-apps to learn the different use-cases made possible with Web Apps.

.NET Framework Templates

Likewise there are 2 .NET Framework Templates without .NET Core 2.0 equivalents as they contain Windows-only .NET Framework dependencies. This includes our React Desktop Template which supports packaging your Web App into 4 different ASP.NET, Winforms, OSX Cocoa and cross-platform Console App Hosts:

React Desktop Apps Template

Windows Service Template

You can use winservice-netfx to create a Windows Service but as this requires Visual Studio it’s faster to continue creating new Windows Service projects within VS.NET using the ServiceStack Windows Service Empty Project Template.

All Apps and Live Demos Upgraded

All existing .NET Core 1.x projects have been upgraded to .NET Core 2.0 and ServiceStack v5, including all .NET Core Live Demos, all .NET Core 2.0 Web Apps and all .NET Framework Live Demos.

ServiceStack WebApps

The .NET Core 2.0 Web Apps now use the default WebHost.CreateDefaultBuilder() builder to bootstrap WebApp’s letting you use ASPNETCORE_URLS to specify which URL and port to bind on, simplifying deployment configurations.

The ASPNETCORE_ENVIRONMENT Environment variable can also be used to configure WebApp’s to run in Production mode. If preferred you can continue using the existing bind, port and debug options in your web.settings to override the default configuration.

Multi-stage Docker Builds

The .NET Core Apps deployed using Docker now use the ASP.NET Team’s recommended multi-stage Docker Builds where the App is built inside an aspnetcore-build Docker container with its published output copied inside a new aspnetcore runtime Docker container:

FROM microsoft/aspnetcore-build:2.0 AS build-env
COPY src /app
WORKDIR /app

RUN dotnet restore --configfile ../NuGet.Config
RUN dotnet publish -c Release -o out

# Build runtime image
FROM microsoft/aspnetcore:2.0
WORKDIR /app
COPY --from=build-env /app/Chat/out .
ENV ASPNETCORE_URLS http://*:5000
ENTRYPOINT ["dotnet", "Chat.dll"]

The smaller footprint required by the aspnetcore runtime reduced the footprint of .NET Core Chat from 567MB to 126MB whilst continuing to run flawlessly in AWS ECS at chat.netcore.io.

.NET Core IAppSettings Adapter

Most .NET Core Templates are also configured to use the new NetCoreAppSettings adapter to utilize .NET Core’s new IConfiguration config model in ServiceStack by initializing the AppHost with .NET Core’s pre-configured IConfiguration that’s injected into the Startup.cs constructor, e.g:

public class Startup
{
    public IConfiguration Configuration { get; }
    public Startup(IConfiguration configuration) => Configuration = configuration;

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseServiceStack(new AppHost {
            AppSettings = new NetCoreAppSettings(Configuration)
        });
    }
}

PBKDF2 Password Hashing implementation

ServiceStack now uses the same PBKDF2 password hashing algorithm ASP.NET Identity v3 uses to hash passwords by default for both new users and successful authentication logins where their password will automatically be re-hashed with the new implementation.

This also means if you wanted to switch, you’ll be able to import ASP.NET Identity v3 User Accounts and their Password Hashes into ServiceStack.Auth’s UserAuth tables and vice-versa.

Retain previous Password Hashing implementation

If preferred you can revert to using the existing SaltedHash implementation with:

SetConfig(new HostConfig { 
    UseSaltedHash = true
});

This also supports “downgrading” passwords that were hashed with the new IPasswordHasher provider where it will revert to using the older/weaker SaltedHash implementation on successful authentication.

Digest Auth Hashes only created when needed

Digest Auth Hashes are now only populated if the DigestAuthProvider is registered. If you ever intend to support Digest access authentication in future but don’t want to register the DigestAuthProvider just yet, you can force ServiceStack to continue to maintain Digest Auth Hashes with:

new AuthFeature {
    CreateDigestAuthHashes = true
}

JWT AuthProvider

Previously in order to be able to utilize RefreshToken’s you would need to be also be using an Auth Repository as it’s the data source used to populate the JWT Token.

Now Users who are not using an IAuthRepository can instead implement the IUserSessionSource interface:

public interface IUserSessionSource
{
    IAuthSession GetUserSession(string userAuthId);
}

On either their Custom AuthProvider, or if preferred register it as a dependency in the IOC as an alternative source for populating Sessions in new JWT Tokens created using RefreshToken’s. The implementation should only return a populated IAuthSession if the User is allowed to sign-in, i,e. if their account is locked or suspended it should throw an Exception, e.g:

throw HttpError.Forbidden("User is suspended");

Send JWTs in HTTP Params

The JWT Auth Provider can opt-in to accept JWT’s via the Query String or HTML POST FormData with:

new JwtAuthProvider {
    AllowInQueryString = true,
    AllowInFormData = true
}

This is useful for situations where it’s not possible to attach the JWT in the HTTP Request Headers or ss-tok Cookie.

Runtime JWT Configuration

To allow for dynamic per request configuration as needed in Multi Tenant applications we’ve added a new IRuntimeAppSettings API which can be registered in your AppHost to return custom per request configuration.

E.g. this can be used to return a custom AuthKey that should be used to sign JWT Tokens for that request:

container.Register<IRuntimeAppSettings>(c => new RuntimeAppSettings { 
    Settings = {
        { nameof(JwtAuthProvider.AuthKey), req => (byte[]) GetAuthKey(GetTenantId(req)) }
    }
});

Registration

The JWT BearerToken and RefreshToken properties added to RegisterResponse are now populated on Registrations configured to AutoLogin=true.

Routes with Custom Rules

The new Matches property on [Route] and [FallbackRoute] attributes lets you specify an additional custom Rule that requests need to match. This feature is used in all SPA projects to specify that the [FallbackRoute] should only return the SPA index.html for unmatched requests which explicitly requests HTML, i.e:

[FallbackRoute("/{PathInfo*}", Matches="AcceptsHtml")]
public class FallbackForClientRoutes
{
    public string PathInfo { get; set; }
}

This works by matching the AcceptsHtml built-in RequestRules below where the Route will only match the Request if it includes the explicit text/html MimeType in the HTTP Request Accept Header. The AcceptsHtml rule prevents the home page from being returned for missing resource requests like favicon which returns a 404 instead.

The implementation of all built-in Request Rules.

Routes that contain a Matches rule have a higher precedence then Routes without. We can use this to define multiple idential matching routes to call different Service depending on whether the Path Segment is an integer or not, e.g:

// matches /users/1
[Route("/users/{Id}", Matches = "**/{int}")]
public class GetUser
{
    public int Id { get; set; }
}

// matches /users/username
[Route("/users/{Slug}")]
public class GetUserBySlug
{
    public string Slug { get; set; }
}

Other examples utilizing {int} Request Rules:

// matches /1/profile
[Route("/{UserId}/profile", Matches = @"{int}/**")]
public class GetProfile { ... }

// matches /username/profile
[Route("/{Slug}/profile")]
public class GetProfileBySlug { ... }

// matches /users/1/profile/avatar
[Route("/users/{UserId}/profile/avatar", Matches = @"path/{int}/**")]
public class GetProfileAvatar { ... }

// matches /users/username/profile/avatar
[Route("/users/{Slug}/profile/avatar")]
public class GetProfileAvatarBySlug { ... }

Another popular use-case is to call different services depending on whether a Request is from an Authenticated User or not:

[Route("/feed", Matches = "IsAuthenticated")]
public class ViewCustomizedUserFeed { ... }

[Route("/feed")]
public class ViewPublicFeed { ... }

This can also be used to call different Services depending if the Request is from a Mobile browser or not:

[Route("/search", Matches = "IsMobile")]
public class MobileSearch { ... }

[Route("/search")]
public class DesktopSearch { ... }

Instead of matching on a pre-configured RequestRule you can instead specify a Regular Expression using the format:

{Property} =~ {RegEx}

Where {Property} is an IHttpRequest property, e.g:

[Route("/users/{Id}", Matches = @"PathInfo =~ \/[0-9]+$")]
public class GetUser { ... }

An exact match takes the format:

{Property} = {Value}

Which you could use to provide a tailored feed for specific clients:

[Route("/feed", Matches = @"UserAgent = specific-client")]
public class CustomFeedView { ... }

ServiceStack Templates View Pages

ServiceStack Templates gains support for the last missing feature from ServiceStack.Razor with its new View Pages support which lets you use .html Template Pages to render the HTML for Services Responses.

Just like ServiceStack.Razor you can also specify to use different Views or Layouts by returning a custom HttpResult, e.g:

public object Any(MyRequest request)
{
    ...
    return new HttpResult(response)
    {
        View = "CustomPage",
        Template = "_custom-layout",
    };
}

Or add the [ClientCanSwapTemplates] Request Filter attribute to allow clients to specify which View and Template to use via the query string, e.g: ?View=CustomPage&Template=_custom-layout.

Additional examples of dynamically specifying the View and Template are available in TemplateViewPagesTests.

Logging with Context

Rolf Kristensen added support for contextual logging with the new ILogWithContext interface and PushProperty extension method which lets you attach additional data to log messages, e.g:

using (log.PushProperty("Hello", "World"))
{
    log.InfoFormat("Message");
}

Support for the additional context was added to Log4net, NLog and Serilog logging providers.

Validation

Our internal implementation of FluentValidation has been upgraded to the latest 7.2 version which will let you take advantage of new features like implementing Custom Validators, e.g:

public class CustomValidationValidator : AbstractValidator<CustomValidation>
{
    public CustomValidationValidator()
    {
        RuleFor(request => request.Code).NotEmpty();
        RuleFor(request => request)
            .Custom((request, context) => {
                if (request.Code?.StartsWith("X-") != true)
                {
                    var propName = context.ParentContext.PropertyChain.BuildPropertyName("Code");
                    context.AddFailure(new ValidationFailure(propName, error:"Incorrect prefix") {
                        ErrorCode = "NotFound"
                    });
                }
            });
    }
}

Validators in ServiceAssemblies auto-wired by default

The ValidationFeature plugin now scans and auto-wires all validators in the AppHost.ServiceAssemblies that’s injected in the AppHost constructor so you’ll no longer need to manually register validators maintained in your ServiceInterface.dll project:

//container.RegisterValidators(typeof(UserValidator).Assembly);

Expanded Async Support

To pre-emptively support .NET Core when they disable Sync Response writes by default in a future version, we’ve rewritten our internal implementations to write to Responses asynchronously.

New Async filters are now available to match existing sync filters. It’s very unlikely the classic ASP.NET Framework will ever disable sync writes, but if you’re on .NET Core you may want to consider switching to use the newer async API equivalents on IAppHost below:

GlobalRequestFiltersAsync
GlobalResponseFiltersAsync
GatewayRequestFiltersAsync
GatewayResponseFiltersAsync
GlobalMessageRequestFiltersAsync
GlobalMessageResponseFiltersAsync

Async Attribute Filters

Async Filter Attributes are available by inheriting the new RequestFilterAsyncAttribute or ResponseFilterAsyncAttribute base classes if you need to call async APIs within Filter Attributes.

All async equivalents follow the same Order of Operations and are executed immediately after any registered sync filters with the same priority.

Async Request and Response Converters

As they’re not commonly used, the RequestConverters and ResponseConverters were just converted to utilize an Async API.

Async ContentTypes Formats

There’s also new async registration APIs for Content-Type Formats which perform Async I/O, most serialization formats don’t except for HTML View Engines which can perform Async I/O when rendering views, so they were changed to use the new RegisterAsync APIs:

appHost.ContentTypes.RegisterAsync(MimeTypes.Html, SerializeToStreamAsync, null);
appHost.ContentTypes.RegisterAsync(MimeTypes.JsonReport, SerializeToStreamAsync, null);
appHost.ContentTypes.RegisterAsync(MimeTypes.MarkdownText, SerializeToStreamAsync, null);

Async HttpWebRequest Service Clients

The Async implementation of the HttpWebRequest based Service Clients was rewritten to use the newer .NET 4.5 Async APIs as the older APM APIs were found to have some async request hanging issues in the .NET Standard 2.0 version of Xamarin.iOS.

Minor Features

  • ToOptimizedResult() now supports HttpResult responses
  • Config.DebugMode is being initialized with env.IsDevelopment() in .NET Core
  • MapProjectPath() uses env.ContentRoot in .NET Core
  • MetadataDebugTemplate no longer has dependencies on jquip and ss-utils.js
  • IMeta, IHasSessionId and IHasVersion interfaces are now exported in Add ServiceStack Reference
  • Html.IncludeFile() API for embedding file contents in Razor views
  • VirtualFiles and VirtualFileSources properties added to base Razor View

@servicestack npm packages

ServiceStack’s npm packages are now being maintained in npm organization scoped @servicestack packages, if you were using the previous packages you should uninstall them and use the new scoped packages instead:

$ npm uninstall servicestack-client
$ npm install @servicestack/client

$ npm uninstall -g servicestack-cli
$ npm install -g @servicestack/cli

You’ll also need to update your source code references to use the new packages:

import { JsonServiceClient } from "@servicestack/client";

ServiceStack.OrmLite

Support for MySqlConnector ADO.NET Provider

@Naragato from the ServiceStack Community contributed a MySqlConnector for OrmLite providing a true async ADO.NET Provider option for MySql, from their website:

This is a clean-room reimplementation of the MySQL Protocol and is not based on the official connector.
It’s fully async, supporting the async ADO.NET methods added in .NET 4.5 without blocking (or using Task.Run to run synchronous methods on a background thread). It’s also 100% compatible with .NET Core.

To use it, install:

PM> Install-Package ServiceStack.Ormlite.MySqlConnector

Then initialize your DB Factory with:

var dbFactory = new OrmLiteConnectionFactory(connectionString, MySqlConnectorDialect.Provider);

using (var db = dbFactory.Open()) 
{
    ...
}

Parametrized IN Values

You can now provide a collection of values and OrmLite will automatically modify the SQL statement and split the values into multiple DB parameters to simplify executing parameterized SQL with multiple IN Values, e.g:

var ids = new[]{ 1, 2, 3};
var results = db.Select<Table>("Id in (@ids)", new { ids });

var names = new List<string>{ "foo", "bar", "qux" };
var results = db.SqlList<Table>("SELECT * FROM Table WHERE Name IN (@names)", new { names });

RowVersion Byte Array

To improve reuse of OrmLite’s Data Models in Dapper, @daleholborow
added support for allowing byte[] RowVersion as an alternative to OrmLite’s ulong RowVersion which lets you use OrmLite Data Models with byte[] RowVersion properties in Dapper queries.

OnOpenConnection Filter

The OnOpenConnection filter lets you run custom commands after opening a new DB Connection. This feature can be used to easily enable Write-Ahead Logging in SQLite:

var dbFactory = new OrmLiteConnectionFactory("sqlite.db", SqliteDialect.Provider);
SqliteDialect.Provider.OnOpenConnection = db => db.ExecuteSql("PRAGMA journal_mode=WAL;");

OpenAsync APIs

The new OpenDbConnectionAsync() and OpenAsync() alias APIs can be used to Open DB connections asynchronously.

ServiceStack.Aws

PocoDynamo was updated to utilize AWS’s recommended Exponential Backoff And Jitter algorithm.

This is also available to be used independently with:

Thread.Sleep(ExecUtils.CalculateFullJitterBackOffDelay(retriesAttempted));

await Task.Delay(ExecUtils.CalculateFullJitterBackOffDelay(retriesAttempted));

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.