Upgrade to ASP.NET Core 3.0 considerations

Before you change .NET Core framework from 2.x to 3.0/3.1, expect for those solutions, issues. More than 1.x to 2.x.

I’ll mention some things to consider.

JSON Serialisation

JSON serialisation is up to 4 times faster due to Microsoft implementing utf8 streams, which is more efficient. Newtonsoft now is an ‘option’.

However, if you have REST Endpoints that work with JObject as argument will not simply work. The suggested JsonElement alternative by MS will require you to do inefficient things. If this is the case, set Newton as default, until .NET supports JsonDocument instead of JObject.

If your POCO objects, used by your REST Api, have self-refering references, System.Text.Json.JsonSerializer cannot handle this.

You need this in startup:

      services.AddNewtonsoftJson(options =>
                        var opt = options.SerializerSettings;                
                        opt.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

Synchronous operations are disallowed

If any of your code is still using Xml serialisation, like using XDocument, this will fail if it uses the synchoneous version. Like ‘XDocument.Save’  or even ‘ XDocument.SaveAsync’ That fails with “Synchronous operations are disallowed. Call WriteAsync or set AllowSynchronousIO to true instead”

Fix that with:

var xmlWriter = XmlWriter.Create(context.HttpContext.Response.Body, settings: new XmlWriterSettings { Async = true });

await Xml.WriteToAsync(xmlWriter, default);
  await xmlWriter.FlushAsync();

Dont forget to flush. It took me 1 hour to find out. (Yep, no unit tests, extern solution).

However, some libraries are out of your control, so you might need these too.

services.Configure(options =>
                 options.AllowSynchronousIO = true; //to get metaweblogcontroller working
             services.Configure(options =>
                 options.AllowSynchronousIO = true;


If you work with Razor, you might be using UrlHelper. In previous .NET core versions you could inject IUrlHelper using IActionContextAccessor. You need an extra line using IUrlHelperFactory.

services.AddScoped(x => {
                var actionContext = x.GetService().ActionContext;
                var factory = x.GetRequiredService();
                return factory.GetUrlHelper(actionContext);

    blog comments powered by Disqus