The Problem
I have a web API with two endpoints, the endpoints serve mapped data in XML format for two different vendors. The result of both the endpoints is the same object but there are some differences like namespaces. The problem is how to return the same object with only namespaces serialized differently? I didn't want to go with the obvious solution of serializing the object with the different namespaces and returning them.
Solution 3
This approach is a mix of solution 1 and Solution 2.
Create Action Filters for the two endpoints, also created two output formatters like in solution 1 for both the endpoints. In the action filter, get the result object and add the output formatters to the formatters of the result.
Pros and Cons of the solution
Pros
- The MVC pipeline remains unaltered, unlike Solution 1.
- Because there is a separate action filter, there is a clear separation of concerns. Code is well separated, i.e business logic is taken care of by the API, and formatting the output is achieved by the formatters.
- We are not writing into the response body here like solution 2, so the middleware in the pipeline will not be affected in case any middleware alters the response.
Cons
I haven't found any yet. Let me know in case any finds any.
Implementation
Step 1
I created two Action Filters one for the Washington weather station endpoint and Quebec endpoint.
The snippet of the new Action Filter
public class QubecCanadaOuputFilterAttribute : ActionFilterAttribute
{
public override async void OnResultExecuting(ResultExecutingContext context)
{
var response = context.HttpContext.Response;
if (response.StatusCode != 200)
{
base.OnResultExecuting(context);
}
var result = context.Result as ObjectResult;
result.Formatters.Add(new QuebecCanadaOutputFormatter());
base.OnResultExecuting(context);
}
}
Step 2
Next created two output formatters for the endpoints, one for Washington and other for Quebec Canada endpoint
The snippet of one of the output formatters
public class QuebecCanadaOutputFormatter : XmlSerializerOutputFormatter
{
public QuebecCanadaOutputFormatter()
{
}
public QuebecCanadaOutputFormatter(XmlWriterSettings xmlWriterSettings) : base(xmlWriterSettings)
{
}
protected override void Serialize(XmlSerializer xmlSerializer, XmlWriter xmlWriter, object value)
{
var namespaces = new XmlSerializerNamespaces();
namespaces.Add("WS", "http://www.qubeccanadaweatherstation.com/xml/namespaces/type");
namespaces.Add("Metric", "http://www.qubeccanadaweatherstation.com/xml/namespaces/siunit/temperature");
xmlSerializer.Serialize(xmlWriter, value, namespaces);
}
}
I created a middleware called SimpleMiddleware in the solution. The middleware simply sets the response status to 200.
Output
Endpoint 1: Washington Weather Staion
<WeatherForecast xmlns:WS="http://www.wausweatherStation.com/xml/namespaces/type" xmlns:Metric="http://www.wausweatherstation.com/xml/namespaces/siunit/temperature">
<Date>2020-06-02T13:50:52.5094204-04:00</Date>
<Temperature>
<Celsius>8</Celsius>
<Farenheit>46</Farenheit>
</Temperature>
<Summary>Mild</Summary>
</WeatherForecast>
Endpoint 2: Quebec Canada
<WeatherForecast xmlns:WS="http://www.qubeccanadaweatherstation.com/xml/namespaces/type" xmlns:Metric="http://www.qubeccanadaweatherstation.com/xml/namespaces/siunit/temperature">
<Date>2020-06-02T13:56:09.5506734-04:00</Date>
<Temperature>
<Celsius>34</Celsius>
<Farenheit>93</Farenheit>
</Temperature>
<Summary>Cool</Summary>
</WeatherForecast>
Code
The sample code for solution 3 is here
or https://github.com/BipinBlog/asp.net_response_manipulation
Solution : OutputFormatters_in_result.sln
Top comments (0)