v5.0.2 Update
Happy New 2018 All! We hope you’ve all had a long, relaxing break over the holidays and are re-energized for a productive start to the new year. We have a new v5.0.2 release ready for the start of the new year. A summary of the changes are included below, for the full details see the v5 Release Notes.
Future Versioning Updates
We intend to ship more frequent “Enhancement Updates” like this one in between major releases so we’re able to ship fixes to Customers sooner. Update releases will be primarily additive and minimally disruptive so they’re safe to upgrade.
To distinguish updates from normal releases we’ll use the {PATCH}
version to indicate an Enhancement Release and use the {MINOR}
version for normal major releases:
{MAJOR}.{MINOR}.{PATCH}
The {MAJOR}
is reserved for Major releases like v5 containing structural changes that may require changes to environment and/or project configurations like v5. A new {MINOR}
version will be used for normal “Major” releases which will have a {PATCH}
version of 0. An even {PATCH}
version number indicates an “Update” release published to NuGet whilst an odd version number indicates a “pre-release” version that’s only available on MyGet, e.g:
-
v5.0.0 - Current Major Release with structural changes
- v5.0.2 - Enhancement of Major v5.0.0 Release
- v5.0.3 - Pre-release packages published to MyGet only
- v5.0.4? - Enhancement of Major v5.0.0 Release (if any)
-
v5.1.0 - Next Major Release
- v5.1.1 - Pre-release packages published to MyGet only
- v5.1.2? - Enhancement of Major v5.1.0 Release (if any)
- …
- v6.0.0 - Next Major Release with structural changes
Run ASP.NET Core Apps on the .NET Framework
To support developing ASP.NET Core Apps on the .NET Framework we’ll continue publishing .Core
packages which contains only the .NET Standard 2.0 builds in order to force .NET Framework projects to use .NET Standard 2.0 builds which contains support for running ASP.NET Core Apps. The complete list of .Core
packages include:
- ServiceStack.Text.Core
- ServiceStack.Interfaces.Core
- ServiceStack.Client.Core
- ServiceStack.HttpClient.Core
- ServiceStack.Core
- ServiceStack.Common.Core
- ServiceStack.Mvc.Core
- ServiceStack.Server.Core
- ServiceStack.Redis.Core
- ServiceStack.OrmLite.Core
- ServiceStack.OrmLite.Sqlite.Core
- ServiceStack.OrmLite.SqlServer.Core
- ServiceStack.OrmLite.PostgreSQL.Core
- ServiceStack.OrmLite.MySql.Core
- ServiceStack.OrmLite.MySqlConnector.Core
- ServiceStack.Aws.Core
- ServiceStack.Azure.Core
- ServiceStack.RabbitMq.Core
- ServiceStack.Api.OpenApi.Core
- ServiceStack.Admin.Core
- ServiceStack.Stripe.Core
- ServiceStack.Kestrel
To make it as easy possible to get started we’ve created a new NetFrameworkCoreTemplates GitHub Organization containing popular starting templates for running ASP.NET Core Apps on .NET Framework (default v4.7) which as a convention all have the -corefx
suffix:
- web-corefx - .NET Framework ASP.NET Core Website
- selfhost-corefx - .NET Framework ASP.NET Core self-hosting Console App
- mvc-corefx - .NET Framework ASP.NET Core MVC Website
- razor-corefx - .NET Framework ASP.NET Core Website with ServiceStack.Razor
- templates-corefx - .NET Framework ASP.NET Core Templates Bootstrap Website
The latest @servicestack/cli
v1.0.2 has been updated to include this additional config source, including them in the list of available templates:
$ dotnet-new
Which will let you create an ASP.NET Core App running on the .NET Framework v4.7 with:
$ npm install -g @servicestack/cli
$ dotnet-new web-corefx AcmeNetFx
Which can then be opened in your preferred VS.NET or Project Rider C# IDE.
ServiceStack Mobile and Desktop Apps
The HelloMobile project has been rewritten to use the latest v5 .NET Standard 2.0 and .NET Framework clients and contains multiple versions of the same App demonstrating a number of different calling conventions, service integrations and reuse possibilities for each of the following platforms:
- WPF
- UWP
- Xamarin.Android
- Xamarin.iOS
- Xamarin.OSX
- Xamarin.Forms
- iOS
- Android
- UWP
ServiceStack Server App
The HelloMobile project also provides an example of ServiceStack’s versatility where the WebServices.cs implementation can be hosted on any of .NET’s popular HTTP Server hosting configurations:
Server.NetCore
The AppHost for hosting the ServiceStack Services in a ASP.NET Core 2.0 App:
public class AppHost : AppHostBase
{
public AppHost() : base(nameof(Server.NetCore), typeof(WebServices).Assembly) { }
public override void Configure(Container container) => SharedAppHost.Configure(this);
}
Server.NetCoreFx
The same source code can be used to run a ServiceStack ASP.NET Core App on the .NET Framework:
public class AppHost : AppHostBase
{
public AppHost() : base(nameof(Server.NetCoreFx), typeof(WebServices).Assembly) { }
public override void Configure(Container container) => SharedAppHost.Configure(this);
}
The difference between a .NET Framework v4.7 and a .NET Core 2.0 ASP.NET Core App is in Server.NetCoreFx.csproj where it references ServiceStack.Core NuGet package to force using the .NET Standard 2.0 version of ServiceStack that contains the support for hosting ASP.NET Core Apps.
Server.AspNet
The same source code is also used for hosting classic ASP.NET Web Applications:
public class AppHost : AppHostBase
{
public AppHost() : base(nameof(Server.AspNet), typeof(WebServices).Assembly) { }
public override void Configure(Container container) => SharedAppHost.Configure(this);
}
Server.HttpListener
Alternatively to host in a .NET Framework Self-Hosting HttpListener, the AppHost needs to inherit from AppSelfHostBase
:
public class AppHost : AppSelfHostBase
{
public AppHost() : base(nameof(Server.HttpListener), typeof(WebServices).Assembly) {}
public override void Configure(Container container) => SharedAppHost.Configure(this);
}
.NET Standard 2.0 Logging Providers
Whilst our recommendation is to use .NET Core’s Logging Abstraction some Customers prefer to avoid this abstraction and configure logging directly with ServiceStack. To support this we’ve included .NET Standard 2.0 builds to the following logging providers:
- ServiceStack.Logging.Serilog
- ServiceStack.Logging.Slack
Async Error Handling
This is an enhancement to our Expanded Async Support where there’s now the option to register async exception handlers, e.g:
this.ServiceExceptionHandlersAsync.Add(async (httpReq, request, ex) =>
{
await LogServiceExceptionAsync(httpReq, request, ex);
if (ex is UnhandledException)
throw ex;
if (request is IQueryDb)
return DtoUtils.CreateErrorResponse(request, new ArgumentException("AutoQuery request failed"));
return null;
});
this.UncaughtExceptionHandlersAsync.Add(async (req, res, operationName, ex) =>
{
await res.WriteAsync($"UncaughtException '{ex.GetType().Name}' at '{req.PathInfo}'");
res.EndRequest(skipHeaders: true);
});
If you were instead inheriting OnServiceException
or OnUncaughtException
in your AppHost they now return a Task
type.
AutoQuery DISTINCT
AutoQuery added support querying DISTINCT fields by prefixing the custom fields list with DISTINCT
, example using QueryString:
?Fields=DISTINCT Field1,Field2
Examle using C# Client:
var response = client.Get(new QueryCustomers {
Fields = "DISTINCT Country"
})
We can use this feature with Northwinds existing AutoQuery Request DTOs:
[Route("/query/customers")]
public class QueryCustomers : QueryDb<Customer> { }
To return all unique City and Countries of Northwind Customers with:
Or to just return their unique Countries they’re in:
OrmLite commandFilter
An optional Func<IDbCommand> commandFilter
has been added to OrmLite’s INSERT
and UPDATE
APIs to allow customization and inspection of the populated IDbCommand
before it’s run. This feature is utilized in the new Conflict Resolution Extension methods where you can specify the conflict resolution strategy when a Primary Key or Unique constraint violation occurs:
db.InsertAll(rows, dbCmd => dbCmd.OnConflictIgnore());
//Equivalent to:
db.InsertAll(rows, dbCmd => dbCmd.OnConflict(ConflictResolution.Ignore));
In this case it will ignore any conflicts that occurs and continue inserting the remaining rows in SQLite, MySql and PostgreSQL, whilst in SQL Server it’s a NOOP.
SQLite offers additional fine-grained behavior that can be specified for when a conflict occurs:
- ROLLBACK
- ABORT
- FAIL
- IGNORE
- REPLACE
ServiceStack.Text
The XmlSerializer.XmlWriterSettings
and XmlSerializer.XmlReaderSettings
for controlling the default XML behavior is now publicly accessible with DTD Processing now disabled by default.
Support for leading zeros in integers was restored.