Hope everyone enjoyed their X-mas holiday break and are re-energized for a productive 2017!
We have another wide exciting release with new features and improvements added throughout ServiceStack starting with new and simplified Single Page App templates, Swift 3 support, enhanced Swift and TypeScript clients, .NET Core and .NET 4.5 and performance improvements, .NET Core MySql, SQL Server Memory Optimized Tables and lots more.
New Angular2 Single Page App template!​
We're happy to introduce a modern VS.NET SPA template for Angular 2 in the latest version of ServiceStackVS. The new Angular2 template closely follows the existing npm-based TypeScript / JSPM / Gulp technology stack solidified in our other SPA templates with the main difference being that it's based on the Material Design Lite theme:
Whereas all other Single Page App templates are based on Bootstrap. We adopted Material Design Lite as we anticipate it's the more natural and popular choice for Angular Apps given they're both actively developed by Google.
Modular Layout​
The Angular2 template also takes advantage of Angular2's modular architecture with a physical structure optimal for small-to-medium sized projects where its modular layout is compartmentalized into multiple independent sub modules. Each sub module can then be further divided into "feature folders" encapsulating the components required to render each individual page so they're able to be maintained separately:
src/
main.module.ts - Register all Modules used in entire App
app.ts - Container component for entire App
dtos.ts - TypeScript Server DTOs
shared/ - Shared Components available to entire App
header.ts
footer.ts
modules/ - All Sub Modules used to construct App
app/ - Main App Module
home/ - Feature Folders
home.ts - The Home Page Tab Contents
hello.html - Hello Sub Component HTML Layout
hello.ts - Hello Sub Component TypeScript
products/
technology/
app.module.ts - All Dependencies + Routes used in Module
TypeScript Client Integration​
Like all SPA Templates, Angular2 includes deep integration with ServiceStack with a TypeScript Service client that's preconfigured to make end-to-end typed API calls out-of-the-box:
var client = new JsonServiceClient('/');
var req = new Hello();
req.name = newValue;
client.get(req).then(r => {
this.result = r.result
});
The TypeScript DTOs can then be easily updated by right-clicking on dtos.ts
to
Update the TypeScript reference
and generate the TypeScript DTOs for any new Services.
The new Angular2 template also benefits from the improvements added to all Single Page App templates in this release:
Simpler and Optimized Single Page App Templates​
Our goal with our Single Page App VS.NET templates is to provide access to the best tooling and development experience whilst keeping complexity and required knowledge to an absolute minimum, as such we're constantly researching how we can simplify our SPA templates by using the least moving parts and picking technologies that work seamlessly together whilst offering maximum value for minimal complexity. As the best SPA tooling mandates an npm-based workflow this becomes a delicate balance of trade-offs as the number of 3rd party JS components, tools, transpilers, scripts and plugins required for building on a modern SPA JS framework can quickly explode - something that influences each aspect of our defaults and we actively fight hard against to avoid.
SPA Template improvements​
In following with these goals we've made a number of improvements to the existing SPA Templates:
Upgraded to JSPM 0.17 beta​
All templates have been upgraded to the latest JSPM 0.17 beta which after a year in development gives us access
to JSPM's latest features like
Static Builds with Rollup Optimization
which we're now using for production deployments where your entire App is statically-linked into a single
optimized app.js
, eliminating the need for system.js
at runtime and removing the packaging overhead from
using modules.
Removed interim deps.tsx​
The interim deps.tsx
file used to minimize the number of requests required during development is no longer needed.
We're now able to generate a cache of 3rd party npm dependencies using your App's main .js file and your
dependencies listed in npm's package.json
.
The cached dependencies are still generated in deps.lib.js
but are now run on first install so it mostly becomes a
transparent implementation detail although after adding new package dependencies you can run the 00-update-deps
Gulp task to re-generate the local cache.
Simplified Typings​
The typings dependency manager has been removed leaving one less typings.json
that needs to be maintained. Templates now use
TypeScript's new @types definitions directly from npm
or when they exist, the definitions contained in each npm package that's referenced in devDependencies.
The only exception being es2015 which now references TypeScript's built-in es2015 declarations instead.
Upgraded to latest Bootstrap v4​
The React and Aurelia SPA Templates have been upgraded to use the just released Bootstrap v4 alpha-6.
Use camelCase by default​
In following with JS naming conventions all SPA Templates are now configured to use camelCase for JSON Web Services and their resulting generated Server DTOs.
Enhanced TypeScript Support​
The SPA Templates also benefit from our enhanced TypeScript support with improvements to both the generated
TypeScript DTOs and the JsonServiceClient
which now includes TypeScript Definitions published with the npm package.
Support for Basic Auth​
Basic Auth support is now implemented in JsonServiceClient
and follows the same API made available in the C#
Service Clients where the userName/password
properties can be set individually, e.g:
var client = new JsonServiceClient(baseUrl);
client.userName = user;
client.password = pass;
client.get(new SecureRequest())
.then(r => ...);
Or use client.setCredentials()
to have them set both together.
Raw Data Responses​
The JsonServiceClient
also supports Raw Data responses like string
and byte[]
which also get a Typed API
once declared on Request DTOs using the IReturn<T>
marker:
public class ReturnString : IReturn<string> {}
public class ReturnBytes : IReturn<byte[]> {}
Which can then be accessed as normal, with their Response typed to a JavaScript string
or Uint8Array
for
raw byte[]
responses:
client.get(new ReturnString())
.then(str => ...); //= str:string
client.get(new ReturnBytes())
.then(data => ...); //= data:Uint8Array
Swift 3​
Swift Add ServiceStack Reference has been upgraded to Swift 3 which is now available from Xcode 8 and later.
Upgraded Swift 3 JsonServiceClient​
The Swift JsonServiceClient
implementation was overhauled and upgraded to use the latest Swift 3
PromiseKit implementation. The earlier Swift 2 compiler bugs preventing AutoQuery Services from working
have now been resolved.
Unfortunately Swift still has a limitation requiring that the sub class of a generic class must also be a generic class which results in your AutoQuery Services (and any other Request DTOs inheriting from a generic class) needing to unnecessarily specify a generic Type arg when creating new instances, e.g:
let request = FindTechnologies<Technology>()
client.getAsync(request)
.then { r -> QueryResponse<Technology> in
//...
return r
}
swiftref OSX command-line utility​
In response to XcodeGhost, Apple has killed support for plugins in Xcode 8 disabling all existing 3rd party plugins from working, and along with it our Integration with Xcode built into ServiceStack Xcode Plugin. As of now the only workaround to get plugins in Xcode 8 working again is to unsign and overwrite the Xcode binary.
Whilst Apple are positioning Xcode extensions as an alternative to Xcode plugins they're extremely weak in comparison as they don't allow basic things like adding new files to a project - limiting their usefulness.
To enable the best development experience we can without using an Xcode plugin we've developed the swiftref OSX command-line utility to provide a simple command-line UX to Add and Update Swift ServiceStack References.
Install swiftref​
The easiest way to install swiftref
is to download the pre-built OSX binary into your /usr/local/bin
so it's available in your $PATH
:
sudo curl https://raw.githubusercontent.com/ServiceStack/swiftref/master/dist/swiftref > /usr/local/bin/swiftref
sudo chmod +x /usr/local/bin/swiftref
After which can be used from within a Terminal window at your Xcode project folder.
Add a new ServiceStack Reference:​
To Add a new ServiceStack Reference, call swiftref
with the Base URL to a remote ServiceStack instance:
swiftref {BaseUrl}
swiftref {BaseUrl} {FileName}
Where if no FileName is provided, it's inferred from the host name of the remote URL, e.g:
swiftref https://techstacks.io
Downloads the Typed Swift DTOs for techstacks.io and saves them to techstacks.dtos.swift
.
Alternatively you can have it saved to a different FileName with:
swiftref https://techstacks.io TechStacks
Which instead saves the DTOs to TechStacks.dtos.swift
.
swiftref
also downloads ServiceStack's Swift Client
and saves it to JsonServiceClient.swift
which together with the Server DTOs contains all the dependencies
required to consume Typed Web Services in Swift.
Update an existing ServiceStack Reference:​
To Update an existing ServiceStack Reference, call swiftref
with the Filename:
swiftref {FileName.dtos.swift}
As an example, you can Update the Server DTOs added in the previous command with:
swiftref TechStacks.dtos.swift
Which also includes any Customization Options that were manually added.
All Swift Example Apps upgraded to Swift 3​
Our existing Swift Example Apps have all been upgraded to use ServiceStack's new Swift 3 Support:
The latest TechStacks iPhone/iPad App and AutoQuery Viewer for iPad are also available to download on the App Store.
101 Swift LINQ Samples​
A great resource for learning Swift from a C# background is the 101 LINQ Samples in Swift 3 which shows the equivalent Swift 3 code alongside C# for each of MSDN's 101 LINQ Examples.
Swift Package Manager Apps​
In its quest to become a popular mainstream language, Swift now includes a built-in Package Manager to simplify the maintenance, distribution and building of Swift code. Swift Package Manager can be used to build native statically-linked modules or Console Apps but currently has no support for iOS, watchOS, or tvOS platforms.
Nevertheless it's simple console and text-based programming model provides a great way to quickly develop prototypes or Console-based Swift Apps like swiftref using your favorite text editor. To support this environment we've packaged ServiceStack's Swift Service clients into a ServiceStackClient package so it can be easily referenced in Swift PM projects.
Swift TechStacks Console App​
Together with Swift Add ServiceStack Reference we now have a productive development workflow for building statically-linked native executables that consume Typed ServiceStack Services as seen in the new step-by-step guide below showing how to create a simple Swift TechStacks Console App.
First we have to reference the ServiceStackClient dependency in a plain-text Package.swift
manifest file:
import PackageDescription
let package = Package(
name: "TechStacks Console App",
dependencies: [
.Package(url: "https://github.com/ServiceStack/SwiftClient", majorVersion: 1)
]
)
Then create a Folder under /Sources
to store the App source code:
mkdir -p Sources/App && cd Sources/App
Now download the Typed DTOs from the remote ServiceStack Service you want to access, e.g:
curl https://techstacks.io/types/swift?DefaultImports=Foundation,ServiceStackClient > TechStacks.dtos.swift
The above url includes a modified import in the generated DTOs by appending the
?DefaultImports=Foundation,ServiceStackClient
query string to the Swift Types endpoint so it references the
Service Client from ServiceStackClient package.
Now we have everything we need to make typed end-to-end API calls to TechStacks Services, all that's missing
is writing the App that consumes them, which is added in main.swift
:
import ServiceStackClient;
let client = JsonServiceClient(baseUrl:"https://techstacks.io")
let request = GetTechnology()
request.slug = "ServiceStack"
let response = try client.get(request)
print(response.technologyStacks[0].toJson());
This gives us a working App that can be built with:
swift build
Which instructs Swift PM to download and install any dependencies listed in Package.swift
that it builds and
links with your App in /Sources/App
, the result is a statically-linked executable that can be run directly
from the .build
directory:
.build/debug/App
Where executing the App downloads Technology Stacks using ServiceStack, serializes the 1st Result to JSON, then prints the JSON output to the Console.
Service Fabric Example​
Another Example project developed during this release is Hello ServiceFabric to show a Hello World example of running a ServiceStack Self Hosted Service inside Microsoft's Service Fabric platform.
Service Fabric is a distributed systems platform that enables wrapping self-hosted Services inside a managed package, allowing them to be treated like Containers where they can be scaled on a cluster and managed independently using Service Fabric's orchestration tooling.
App Clusters for Service Fabric can be created anywhere​
You can create clusters for Service Fabric in many environments, including Azure or on premises, on Windows Server, or on Linux. In addition, the development environment in the SDK is identical to the production environment, and no emulators are involved. For more information on creating clusters on-premises, read creating a cluster on Windows Server or Linux or for Azure creating a cluster via the Azure portal.
Changes from Service Fabric Application VS.NET template​
The main difference of this project from the default Service Fabric Application VS.NET Template is the
SelfHostCommunicationListener.cs
adapter class which implements Service Fabric's ICommunicationListener
interface for managing the life-cycle of a ServiceStack Self-Host Service.
When creating a new Service Fabric Self Hosted Service from a VS.NET template, you can copy:
Into your project then change your StatelessSelfHost
to use this class configured with your ServiceStack AppHost, e.g:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
var endpoints = Context.CodePackageActivationContext.GetEndpoints()
.Where(endpoint => endpoint.Protocol==EndpointProtocol.Http || endpoint.Protocol==EndpointProtocol.Https)
.Select(endpoint => endpoint.Name);
return endpoints.Select(endpoint => new ServiceInstanceListener(
serviceContext => new SelfHostCommunicationListener(
new AppHost(), serviceContext, ServiceEventSource.Current, endpoint), endpoint));
}
Performance Improvements​
Our first support for .NET Core was primarily focused on compatibility and deep integration with .NET Core's Pipeline, Modules and Conventions. In this release we focused on performance and memory usage which we kicked off by developing a benchmarking solution for automatically spinning up Azure VM's that we use to run benchmarking and load tests against.
We've decided to run Benchmarks against a Cloud VM to give some resemblance of real numbers you can get when running on a popular commodity server environment.
A simple JSON Service running our initial .NET Core support in v4.5.4 release yields:
Benchmark | Requests/Sec Average | StdDev | StdDev/Average (%) |
---|---|---|---|
.NET Core 1.1 | 26179 | 74 | 0.28 |
mono 4.6.2 (nginx+hyperfasctcgi) | 6428 | 84 | 1.30 |
Running on Standard_F4s azure instance (4 Core, 8GB RAM) using the following wrk benchmarking tool command:
wrk -c 256 -t 8 -d 30 http://benchmarking_url
Using 8 threads, keeping 256 concurrent HTTP Connections open, Running for 30s.
With the profiling and performance improvements added in this release, the same service now yields:
Benchmark | Requests/Sec Average | StdDev | StdDev/Average (%) |
---|---|---|---|
.NET Core 1.1 | 37073 | 271 | 0.73 |
mono 4.6.2 (nginx+hyperfasctcgi) | 6840 | 63 | 0.93 |
Which is over a 40% improvement for this benchmark since last release.
Running the same ServiceStack Service on the same VM also shows us that .NET Core is 5.4x faster than our recommended Mono, nginx + HyperFastCGI configuration for running ASP.NET Web Applications on Mono.
Upgraded to .NET Core 1.1​
We're closely following .NET Core's progress and continue to upgrade ServiceStack libraries and their test suites to run on the latest stable .NET Core release which as of this release is .NET Core 1.1.
Client/Server Request Compression​
Previously compression was limited to optimized cached Server Responses which are also supported by default in all Service Clients.
You can now also elect to compress HTTP Requests in any C#/.NET Service Clients by specifying the Compression Type you wish to use, e.g:
var client = new JsonServiceClient(baseUrl) {
RequestCompressionType = CompressionTypes.GZip,
};
var client = new JsonHttpClient(baseUrl) {
RequestCompressionType = CompressionTypes.Deflate,
};
var response = client.Post(new Request { ... });
Where sending any HTTP Request containing a Request Body (e.g. POST/PUT) will send a compressed Request body to the Server where it's now able to be transparently decompressed and deserialized into your Request DTO.
FileSystem Mapping​
Custom FileSystem mappings can now be easily registered under a specific alias by overriding your AppHost's
GetVirtualFileSources()
and registering a custom FileSystemMapping
, e.g:
public override List<IVirtualPathProvider> GetVirtualFileSources()
{
var existingProviders = base.GetVirtualFileSources();
existingProviders.Add(new FileSystemMapping(this, "img", "i:\\images"));
existingProviders.Add(new FileSystemMapping(this, "docs", "d:\\documents"));
return existingProviders;
}
This will let you access File System Resources under the custom /img
and /doc
routes, e.g:
- http://host/img/the-image.jpg
- http://host/docs/word.doc
SQL Server Features​
Kevin Howard has continued enhancing the SQL Server Support in OrmLite
with access to advanced SQL Server features including
Memory-Optimized Tables where you can tell
SQL Server to maintain specific tables in Memory using the [SqlServerMemoryOptimized]
attribute, e.g:
[SqlServerMemoryOptimized(SqlServerDurability.SchemaOnly)]
public class SqlServerMemoryOptimizedCacheEntry : ICacheEntry
{
[PrimaryKey]
[StringLength(StringLengthAttribute.MaxText)]
[SqlServerBucketCount(10000000)]
public string Id { get; set; }
[StringLength(StringLengthAttribute.MaxText)]
public string Data { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime? ExpiryDate { get; set; }
public DateTime ModifiedDate { get; set; }
}
The [SqlServerBucketCount]
attribute can be used to
configure the bucket count for a hash index
whilst the new [SqlServerCollate]
attribute can be used to specify an SQL Server collation.
The new Memory Optimized support can be used to improve the performance of SQL Server OrmLiteCacheClient
by configuring it to use the above In Memory Table Schema instead, e.g:
container.Register<ICacheClient>(c =>
new OrmLiteCacheClient<SqlServerMemoryOptimizedCacheEntry>());
PostgreSQL Data Types​
To make it a little nicer to be define custom PostgreSQL columns, we've added [PgSql*]
specific attributes
which will let you use a typed [PgSqlJson]
instead of previously needing to use [CustomField("json")]
.
Other attributes available include:
public class MyPostgreSqlTable
{
[PgSqlJson]
public List<Poco> AsJson { get; set; }
[PgSqlJsonB]
public List<Poco> AsJsonB { get; set; }
[PgSqlTextArray]
public string[] AsTextArray { get; set; }
[PgSqlIntArray]
public int[] AsIntArray { get; set; }
[PgSqlBigIntArray]
public long[] AsLongArray { get; set; }
}
.NET Core support for MySql​
You can now use OrmLite with MySQL in .NET Core using the new
ServiceStack.OrmLite.MySql.Core NuGet package.
As it's dependent on the MySql.Data 7.0.6-IR31
Pre-release NuGet package, it needs to be installed using the -Pre
flag:
PM> Install-Package ServiceStack.OrmLite.MySql.Core -Pre
We'll update the OrmLite MySql package as soon as the first official MySql.Data is released.
Create Tables without Foreign Keys​
You can temporarily disable and tell OrmLite to create tables without Foreign Keys by setting:
OrmLiteConfig.SkipForeignKeys = true;
Which can be useful when performing Migrations, Imports or within integration tests.
Custom SqlExpression Filter​
The generated SQL from a Typed SqlExpression
can now be customized using the new .WithSqlFilter()
, e.g:
var q = db.From<Table>()
.Where(x => x.Age == 27)
.WithSqlFilter(sql => sql + " option (recompile)");
var q = db.From<Table>()
.Where(x => x.Age == 27)
.WithSqlFilter(sql => sql + " WITH UPDLOCK");
var results = db.Select(q);
Custom SQL Fragments​
The new Sql.Custom()
API lets you use raw SQL Fragments in Custom .Select()
expressions, e.g:
var q = db.From<Table>()
.Select(x => new {
FirstName = x.FirstName,
LastName = x.LastName,
Initials = Sql.Custom("CONCAT(LEFT(FirstName,1), LEFT(LastName,1))")
});
Other Features​
Cached API Key Sessions​
You can reduce the number of I/O Requests and improve the performance of API Key Auth Provider Requests by
specifying a SessionCacheDuration
to temporarily store the Authenticated UserSession against the API Key
which will reduce subsequent API Key requests down to 1 DB call to fetch and validate the API Key + 1 Cache Hit
to restore the User's Session which if you're using the default in-memory Cache will mean it only requires 1 I/O
call for the DB request.
This can be enabled with:
Plugins.Add(new AuthFeature(...,
new IAuthProvider[] {
new ApiKeyAuthProvider(AppSettings) {
SessionCacheDuration = TimeSpan.FromMinutes(10),
}
}));
Config.AllowFilePaths​
The new Config.AllowFilePaths
allows finer-grained file access that lets you use a Glob wildcard pattern
to allow access to matching file paths, e.g:
SetConfig(new HostConfig {
AllowFilePaths = new List<string> {
"jspm_packages/**/*.json"
}
})
Which will tell ServiceStack to allow access to any *.json
file under the /jspm_packages
folder
to avoid having to add "json" to AllowFileExtensions
which would open up access to every *.json
file.
This feature makes use of the new .GlobPath()
extension method which may be useful to use in your own Apps, e.g:
"dir/a/b/c/d/e/file.json".GlobPath("dir/**/*.json") == true