How to use output formatters in ASP.Net Core

Learn how to build a custom output formatter in ASP.Net Core to exchange data in formats other than JSON, XML, and plain text

How to use output formatters in ASP.Net Core
Guirong Hao / Valery Brozhinsky / Getty Images

ASP.Net Core provides built-in support for data exchange in the JSON and XML formats. If you want your ASP.Net Core application to transmit data over HTTP in a format that isn’t supported by one of these built-in formatters, then you will need to create a custom output formatter.

As an example, you might want to build a custom output formatter if you want to exchange data with clients using the more efficient Protobuf format. This article presents a discussion of what output formatters are, why they are needed, and how we can build a custom output formatter in ASP.Net Core.

Create an ASP.Net Core Web API project

First off, let’s create an ASP.Net Core Web API project in Visual Studio. If Visual Studio 2017 is up and running in your system, follow the steps given below to create an ASP.Net Core Web API project.

  1. Launch the Visual Studio 2017 IDE.
  2. Click on File > New > Project.
  3. Select “ASP.Net Core Web Application (.Net Core)” from the list of templates displayed.
  4. Specify a name for the project.
  5. Click OK to save the project.
  6. A new window “New .Net Core Web Application…” is shown next.
  7. Select .Net Core as the runtime and ASP.Net Core 2.1 or later from the drop-down list at the top of the window.
  8. Select “API” as the project template. 
  9. Ensure that the check boxes “Enable Docker Support” and “Configure for HTTPS” are unchecked as we wn’t be using those features here. 
  10. Ensure that “No Authentication” is selected as we won’t be using authentication either. 

This will create a new ASP.Net Core project in Visual Studio. We’ll use this project to work with output formatters.

What is an output formatter? Why is it needed?

An output formatter is a class that can convert the data to be sent over the wire into a different format. So, if you would like your ASP.Net Core Web API to be able to send data in Excel format (.xlsx) over HTTP, you would need to build a custom output formatter for it.

The client takes advantage of content negotiation to decide the format in which it will receive the data and specifies the content type in the Accept-Header. Note that content negotiation is the process of inspecting the structure of an incoming HTTP request to determine the best representation of a resource from multiple representations of the resource. Content negotiation allows you to use the same URL to serve the same content in different formats for different clients.

Note that in ASP.Net Core Web API, data is always returned as JSON even if text/html is specified as the content type in the header. This is because the built-in XML formatter is not registered by default. Now, suppose the client has specified a format in which it wants to receive data, but the format is not available. In this case, the framework would use the default JSON formatter as the output formatter.

The following code snippet shows how you can register the XML formatter to enable your ASP.Net Core Web API to emit data in text/xml format.

services.AddMvc(options =>
{
    options.OutputFormatters.Add(new XmlSerializerOutputFormatter());
});

If you would like to use XML as both input and output formatter, you can specify the following in the ConfigureServices method of the Startup class.

options.InputFormatters.Add(new XmlSerializerInputFormatter());
options.OutputFormatters.Add(new XmlSerializerOutputFormatter());

Create a custom output formatter in ASP.Net Core

To create a custom output formatter, you should create a class that extends any of the available output formatters—TextOutputFormatter, JsonOutputFormatter, etc.—or the OutputFormatter class. Incidentally, OutputFormatter is the base class for all output formatters. Similarly, InputFormatter is the base class for all input formatters. The formatters TextInputFormatters, JsonInputFormatter, etc. all extend the InputFormatter class.

To create a simple output formatter, create a class that extends the TextOutputFormatter class and overrides the WriteResponseBodyAsync method as shown below.

public class MyCustomOutputFormatter : TextOutputFormatter
    {
        public override Task WriteResponseBodyAsync
         (OutputFormatterWriteContext context,
         Encoding selectedEncoding)
        {
            throw new NotImplementedException();
        }
    }

The next thing you will need to do is to write the necessary code to specify the supported media types and supported encodings. You can write this code in the constructor of the MyCustomOutputFormatter class as shown in the code snippet given below.

public MyCustomOutputFormatter()
        {
            SupportedMediaTypes.Add
            (MediaTypeHeaderValue.Parse(""));
            SupportedEncodings.Add(Encoding.UTF8);
            SupportedEncodings.Add(Encoding.Unicode);
            //Write code here to add the supported media types
        }

The next step is to override the CanWriteType methods to specify how the data will be serialized. Here is how the MyCustomOutputFormatter class looks now.

using Microsoft.AspNetCore.Mvc.Formatters;
using System;
using Microsoft.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace IDGExamples
{
    public class MyCustomOutputFormatter : TextOutputFormatter
    {
        public MyCustomOutputFormatter()
        {
            SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse
            ("text/MyCustomFormat"));
            SupportedEncodings.Add(Encoding.UTF8);
            SupportedEncodings.Add(Encoding.Unicode);
        }
        public bool CanWriteType
        (OutputFormatterCanWriteContext context)
        {
            throw new NotImplementedException();
        }
        public override Task WriteResponseBodyAsync
        (OutputFormatterWriteContext context,
          Encoding selectedEncoding)
        {
            throw new NotImplementedException();
        }
    }
}

I will leave it to you to implement the CanWriteType and WriteResponseBodyAsync methods.

Register the custom output formatter in ASP.Net Core

When you register a formatter, you add the formatter to the FormatterCollection. At runtime, when there is an Accept header in the request, the ASP.Net Core framework iterates this collection to retrieve the formatter as specified in the accept header.

You can register the custom output formatter in the ConfigureServices method as shown in the code snippet given below.

public void ConfigureServices(IServiceCollection services)
{
     services.AddMvc(options =>
     {
       options.OutputFormatters.Add(new
         MyCustomOutputFormatter());
       //Usual code
     });
}

ASP.Net Core provides built-in support for the JSON, XML, and plain text formats for sending data over the wire. You will need to create a custom output formatter whenever you want to transmit data in any format other than these.

Copyright © 2019 IDG Communications, Inc.