<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Bipin Radhakrishnan</title>
    <description>The latest articles on Forem by Bipin Radhakrishnan (@bipinr).</description>
    <link>https://forem.com/bipinr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F130272%2F203a37a4-0343-4303-8c6c-7c396d04b75a.png</url>
      <title>Forem: Bipin Radhakrishnan</title>
      <link>https://forem.com/bipinr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bipinr"/>
    <language>en</language>
    <item>
      <title>Alternate ways to intercept and manipulate Response in Asp.Net Core- Part 3</title>
      <dc:creator>Bipin Radhakrishnan</dc:creator>
      <pubDate>Sun, 07 Jun 2020 14:59:53 +0000</pubDate>
      <link>https://forem.com/bipinr/alternate-ways-to-intercept-and-manipulate-response-in-asp-net-core-part-3-4f34</link>
      <guid>https://forem.com/bipinr/alternate-ways-to-intercept-and-manipulate-response-in-asp-net-core-part-3-4f34</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution 3
&lt;/h2&gt;

&lt;p&gt;This approach is a mix of &lt;a href="https://dev.to/rbipin/alternate-ways-to-intercept-and-manipulate-response-in-asp-net-core-part-1-4omf"&gt;solution 1&lt;/a&gt; and &lt;a href="https://dev.to/rbipin/alternate-ways-to-intercept-and-manipulate-response-in-asp-net-core-part-2-2mbc"&gt;Solution 2&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
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.&lt;/p&gt;


&lt;h3&gt;
  
  
  Pros and Cons of the solution
&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The MVC pipeline remains unaltered, unlike Solution 1.&lt;/li&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I haven't found any yet. Let me know in case any finds any.&lt;/p&gt;


&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I created two Action Filters one for the Washington weather station endpoint and Quebec endpoint.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2F2020%2F06%2FSol2-action-filters.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2F2020%2F06%2FSol2-action-filters.JPG" alt="Sol2-action-filters" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The snippet of the new Action Filter&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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);
        }
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next created two output formatters for the endpoints, one for Washington and other for Quebec Canada endpoint&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2F2020%2F06%2Fcode_output_formatters.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2F2020%2F06%2Fcode_output_formatters.JPG" alt="code_output_formatters" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The snippet of one of the output formatters&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; 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);
        }
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I created a middleware called &lt;em&gt;SimpleMiddleware&lt;/em&gt; in the solution. The middleware simply sets the response status to 200.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2F2020%2F06%2FSol2-middleware.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2F2020%2F06%2FSol2-middleware.JPG" alt="Sol2-middleware" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Endpoint 1: Washington Weather Staion&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;WeatherForecast xmlns:WS="http://www.wausweatherStation.com/xml/namespaces/type" xmlns:Metric="http://www.wausweatherstation.com/xml/namespaces/siunit/temperature"&amp;gt;
&amp;lt;Date&amp;gt;2020-06-02T13:50:52.5094204-04:00&amp;lt;/Date&amp;gt;
&amp;lt;Temperature&amp;gt;
&amp;lt;Celsius&amp;gt;8&amp;lt;/Celsius&amp;gt;
&amp;lt;Farenheit&amp;gt;46&amp;lt;/Farenheit&amp;gt;
&amp;lt;/Temperature&amp;gt;
&amp;lt;Summary&amp;gt;Mild&amp;lt;/Summary&amp;gt;
&amp;lt;/WeatherForecast&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Endpoint 2: Quebec Canada&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;WeatherForecast xmlns:WS="http://www.qubeccanadaweatherstation.com/xml/namespaces/type" xmlns:Metric="http://www.qubeccanadaweatherstation.com/xml/namespaces/siunit/temperature"&amp;gt;
&amp;lt;Date&amp;gt;2020-06-02T13:56:09.5506734-04:00&amp;lt;/Date&amp;gt;
&amp;lt;Temperature&amp;gt;
&amp;lt;Celsius&amp;gt;34&amp;lt;/Celsius&amp;gt;
&amp;lt;Farenheit&amp;gt;93&amp;lt;/Farenheit&amp;gt;
&amp;lt;/Temperature&amp;gt;
&amp;lt;Summary&amp;gt;Cool&amp;lt;/Summary&amp;gt;
&amp;lt;/WeatherForecast&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The sample code for solution 3 is &lt;a href="https://github.com/BipinBlog/asp.net_response_manipulation" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;br&gt;&lt;br&gt;
or &lt;a href="https://github.com/BipinBlog/asp.net_response_manipulation" rel="noopener noreferrer"&gt;https://github.com/BipinBlog/asp.net_response_manipulation&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Solution : OutputFormatters_in_result.sln&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>webapi</category>
      <category>dotnetcore</category>
    </item>
    <item>
      <title>Alternate ways to intercept and manipulate response in Asp.Net core - Part 2</title>
      <dc:creator>Bipin Radhakrishnan</dc:creator>
      <pubDate>Sun, 07 Jun 2020 14:36:01 +0000</pubDate>
      <link>https://forem.com/bipinr/alternate-ways-to-intercept-and-manipulate-response-in-asp-net-core-part-2-2mbc</link>
      <guid>https://forem.com/bipinr/alternate-ways-to-intercept-and-manipulate-response-in-asp-net-core-part-2-2mbc</guid>
      <description>&lt;h2&gt;
  
  
  The Problem:
&lt;/h2&gt;

&lt;p&gt;I have a web API with two endpoints, the endpoints serve 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.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://dev.to/rbipin/alternate-ways-to-intercept-and-manipulate-response-in-asp-net-core-part-1-4omf"&gt;Solution 1&lt;/a&gt;
&lt;/h3&gt;

&lt;h2&gt;
  
  
  Solution 2
&lt;/h2&gt;

&lt;p&gt;Create &lt;em&gt;Action Filters&lt;/em&gt; for the endpoints and manually serialize the output in the &lt;em&gt;OnResultExecuting()&lt;/em&gt; method and write the serialized output to the response body.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros and Cons of the solution
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The MVC pipeline remains unaltered, unlike Solution 1.&lt;/li&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Since we start writing the response body, further manipulation of response is not possible. This is demonstrated in the mode using a middleware.
&amp;lt;!--kg-card-end: markdown--&amp;gt;
### Implementation
&amp;lt;!--kg-card-begin: markdown--&amp;gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I created two action filters one for the Washington weather station endpoint and Quebec endpoint.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2F2020%2F06%2FSol2-action-filters.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2F2020%2F06%2FSol2-action-filters.JPG" alt="Sol2-action-filters" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then I created a custom XML serializer to serialize the object into XML.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2F2020%2F06%2FSol2-xml-serializers.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2F2020%2F06%2FSol2-xml-serializers.JPG" alt="Sol2-xml-serializers" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Use the XML serializers in the corresponding action filters and serialize the object, here is a snippet from Washington action filter&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Action Filter
public class WashingtonOuputFilterAttribute : 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;
            var serializedResult = WashingtonOutputSerializer.Instance.Serialize(result.Value);
            var resultBytes = Encoding.UTF8.GetBytes(serializedResult);
            response.Headers.Add("Content-Type","application/xml");
            await response.Body.WriteAsync(resultBytes, 0, resultBytes.Length);
            base.OnResultExecuting(context);
        }
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the code of lazy-loaded singleton Washington XML Serializer&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//Washington XML Serializer
 public class WashingtonOutputSerializer
    {
        public static readonly Lazy&amp;lt;WashingtonOutputSerializer&amp;gt; lazyWashingtonSerializer =
            new Lazy&amp;lt;WashingtonOutputSerializer&amp;gt;(() =&amp;gt; new WashingtonOutputSerializer());
        public static WashingtonOutputSerializer Instance
        {
            get { return lazyWashingtonSerializer.Value; }
        }
        private WashingtonOutputSerializer() { }
        public string Serialize(object outputObject)
        {
            var namespaces = new XmlSerializerNamespaces();
            namespaces.Add("WS", "http://www.wausweatherStation.com/xml/namespaces/type");
            namespaces.Add("Metric", "http://www.wausweatherstation.com/xml/namespaces/siunit/temperature");
            return XMLSerializer.Instance.Serialize(outputObject, namespaces);
        }
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I created a middleware called &lt;em&gt;SimpleMiddleware&lt;/em&gt; in the solution to demonstrate one of the drawbacks of this solution and why I started searching for solution 3. The middleware simply sets the response status to 200.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2F2020%2F06%2FSol2-middleware.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2F2020%2F06%2FSol2-middleware.JPG" alt="Sol2-middleware" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The middleware is commented in the &lt;em&gt;Configure()&lt;/em&gt; method in the &lt;em&gt;Startup.cs&lt;/em&gt; file.&lt;br&gt;&lt;br&gt;
you may uncomment and check out the error&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; //app.UseSimpleMiddleware();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2F2020%2F06%2Ferror_middleware-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2F2020%2F06%2Ferror_middleware-1.png" alt="error_middleware-1" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;!--kg-card-end: markdown--&amp;gt;&amp;lt;!--kg-card-begin: markdown--&amp;gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Endpoint 1: Washington Weather Staion&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;WeatherForecast xmlns:WS="http://www.wausweatherStation.com/xml/namespaces/type" xmlns:Metric="http://www.wausweatherstation.com/xml/namespaces/siunit/temperature"&amp;gt;
&amp;lt;Date&amp;gt;2020-06-02T13:50:52.5094204-04:00&amp;lt;/Date&amp;gt;
&amp;lt;Temperature&amp;gt;
&amp;lt;Celsius&amp;gt;8&amp;lt;/Celsius&amp;gt;
&amp;lt;Farenheit&amp;gt;46&amp;lt;/Farenheit&amp;gt;
&amp;lt;/Temperature&amp;gt;
&amp;lt;Summary&amp;gt;Mild&amp;lt;/Summary&amp;gt;
&amp;lt;/WeatherForecast&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Endpoint 2: Quebec Canada Weather Station&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;WeatherForecast xmlns:WS="http://www.qubeccanadaweatherstation.com/xml/namespaces/type" xmlns:Metric="http://www.qubeccanadaweatherstation.com/xml/namespaces/siunit/temperature"&amp;gt;
&amp;lt;Date&amp;gt;2020-06-02T13:56:09.5506734-04:00&amp;lt;/Date&amp;gt;
&amp;lt;Temperature&amp;gt;
&amp;lt;Celsius&amp;gt;34&amp;lt;/Celsius&amp;gt;
&amp;lt;Farenheit&amp;gt;93&amp;lt;/Farenheit&amp;gt;
&amp;lt;/Temperature&amp;gt;
&amp;lt;Summary&amp;gt;Cool&amp;lt;/Summary&amp;gt;
&amp;lt;/WeatherForecast&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://dev.to/rbipin/alternate-ways-to-intercept-and-manipulate-response-in-asp-net-core-part-3-4f34"&gt;Solution 3&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The sample code for solution is &lt;a href="https://github.com/BipinBlog/asp.net_response_manipulation" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;br&gt;&lt;br&gt;
or &lt;a href="https://github.com/BipinBlog/asp.net_response_manipulation" rel="noopener noreferrer"&gt;https://github.com/BipinBlog/asp.net_response_manipulation&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Solution : Serialize_in_action_filter.sln&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>webapi</category>
      <category>dotnetcore</category>
    </item>
    <item>
      <title>Alternate ways to intercept and manipulate response in Asp.Net core- Part 1</title>
      <dc:creator>Bipin Radhakrishnan</dc:creator>
      <pubDate>Sun, 07 Jun 2020 11:42:06 +0000</pubDate>
      <link>https://forem.com/bipinr/alternate-ways-to-intercept-and-manipulate-response-in-asp-net-core-part-1-4omf</link>
      <guid>https://forem.com/bipinr/alternate-ways-to-intercept-and-manipulate-response-in-asp-net-core-part-1-4omf</guid>
      <description>&lt;p&gt;I'm going to make this post kind of a problem and solution post. In my pursuit to solve my problem, I stumbled upon three different solutions. I'm going to make each of these solutions a different post/ part. I will also discuss the pros and cons that I found with each of the solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem:
&lt;/h2&gt;

&lt;p&gt;I have a web API with two endpoints, the endpoints serve 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. I wanted to explore other ways to tackle this. Why? because this will be fun ;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution 1
&lt;/h2&gt;

&lt;p&gt;Using Action Filter to clear the output formatter of the MVC pipeline and adding the vendor-specific formatter&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros and Cons of the solution
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code is nice separated, i.e business logic is taken care of by the API, and formatting the output is achieved by the formatters.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We are directly manipulating the output formatters in the MVC pipeline.&lt;/li&gt;
&lt;li&gt;Unable to test in my machine, but I believe this may interfere with other endpoints, I also noticed a null reference exception from this area after hosting in the cloud.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I created two output formatters inheriting from XmlSerializerOutputFormatter. I serialize the object to the correct format using the vendor-specific XML namespaces.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2F2020%2F06%2Fcode_output_formatters.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2F2020%2F06%2Fcode_output_formatters.JPG" alt="code_output_formatters" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The snippet of output formatter&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace OutputFormatter.API
{
    public class WashingtonOutputFormatter : XmlSerializerOutputFormatter
    {
        public WashingtonOutputFormatter()
        {

        }
        public WashingtonOutputFormatter(XmlWriterSettings xmlWriterSettings) : base(xmlWriterSettings)
        {

        }
        protected override void Serialize(XmlSerializer xmlSerializer, XmlWriter xmlWriter, object value)
        {
            var namespaces = new XmlSerializerNamespaces();
            namespaces.Add("WS", "http://www.wausweatherStation.com/xml/namespaces/type");
            namespaces.Add("Metric", "http://www.wausweatherstation.com/xml/namespaces/siunit/temperature");
            xmlSerializer.Serialize(xmlWriter, value, namespaces);
        }

    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create two ActionFilterAttribute, in this case for Quebec Canada and another for Washington. These two action filters will clear the existing output filters in the MVC pipeline and add the corresponding output filter. Quebec Canada Action filter will add the Quebec Canada output formatter to the pipeline and the Washington Action filter will add only Washington output formatter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2F2020%2F05%2Fcode_action_filter.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2F2020%2F05%2Fcode_action_filter.JPG" width="800" height="400"&gt;&lt;/a&gt;screen shot of action filter attribute&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class WashingtonOuputFilterAttribute : ActionFilterAttribute
    {

        public override void OnActionExecuting(ActionExecutingContext context)
        {
            var washingtonOutputFormat = new WashingtonOutputFormatter(new XmlWriterSettings()
            {
                OmitXmlDeclaration = true
            });

            var outputFormattersToRemove = new List&amp;lt;IOutputFormatter&amp;gt;()
            {
                new XmlSerializerOutputFormatter(),
                new SystemTextJsonOutputFormatter(new System.Text.Json.JsonSerializerOptions()),
                new QuebecCanadaOutputFormatter()
            };
            var commonFormatter = new FilterActionCommon();
            commonFormatter.ClearOutputFormatters(context, outputFormattersToRemove);
            commonFormatter.AddOutputFormatter(context, washingtonOutputFormat);
            base.OnActionExecuting(context);
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Endpoint 1: Washington Weather Staion&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;WeatherForecast xmlns:WS="http://www.wausweatherStation.com/xml/namespaces/type" xmlns:Metric="http://www.wausweatherstation.com/xml/namespaces/siunit/temperature"&amp;gt;
&amp;lt;Date&amp;gt;2020-06-02T13:50:52.5094204-04:00&amp;lt;/Date&amp;gt;
&amp;lt;Temperature&amp;gt;
&amp;lt;Celsius&amp;gt;8&amp;lt;/Celsius&amp;gt;
&amp;lt;Farenheit&amp;gt;46&amp;lt;/Farenheit&amp;gt;
&amp;lt;/Temperature&amp;gt;
&amp;lt;Summary&amp;gt;Mild&amp;lt;/Summary&amp;gt;
&amp;lt;/WeatherForecast&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Endpoint 2: Quebec Canada Weather Station&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;WeatherForecast xmlns:WS="http://www.qubeccanadaweatherstation.com/xml/namespaces/type" xmlns:Metric="http://www.qubeccanadaweatherstation.com/xml/namespaces/siunit/temperature"&amp;gt;
&amp;lt;Date&amp;gt;2020-06-02T13:56:09.5506734-04:00&amp;lt;/Date&amp;gt;
&amp;lt;Temperature&amp;gt;
&amp;lt;Celsius&amp;gt;34&amp;lt;/Celsius&amp;gt;
&amp;lt;Farenheit&amp;gt;93&amp;lt;/Farenheit&amp;gt;
&amp;lt;/Temperature&amp;gt;
&amp;lt;Summary&amp;gt;Cool&amp;lt;/Summary&amp;gt;
&amp;lt;/WeatherForecast&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can see that the only difference between the two output are the namespaces.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://dev.to/rbipin/alternate-ways-to-intercept-and-manipulate-response-in-asp-net-core-part-2-2mbc"&gt;Solution 2&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The sample code for this is &lt;a href="https://github.com/BipinBlog/asp.net_response_manipulation" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;br&gt;&lt;br&gt;
or &lt;a href="https://github.com/BipinBlog/asp.net_response_manipulation" rel="noopener noreferrer"&gt;https://github.com/BipinBlog/asp.net_response_manipulation&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Solution : OutputFormatters-Pipeline.sln&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>webapi</category>
      <category>dotnetcore</category>
    </item>
    <item>
      <title>My learning plan 2020</title>
      <dc:creator>Bipin Radhakrishnan</dc:creator>
      <pubDate>Fri, 29 May 2020 10:55:59 +0000</pubDate>
      <link>https://forem.com/bipinr/my-learning-plan-2020-19io</link>
      <guid>https://forem.com/bipinr/my-learning-plan-2020-19io</guid>
      <description>&lt;p&gt;This is a list of things I want to learn in 2020 and why these subjects interest me. These are not in any order, so I may try to learn things based on my interest and as I time permits. I know this is a pretty extensive list, so I'm trying to achieve as much possible. I believe some I can learn as part of my work.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I want to learn &lt;a href="https://angular.io/" rel="noopener noreferrer"&gt;Angular&lt;/a&gt;, this is a very popular framework and I could use this at my work too. An added advantage, the latest version of angular uses &lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;typescript&lt;/a&gt; and I can pick up some typescript when learning angular.&lt;/li&gt;
&lt;li&gt;Learning &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt;, another popular framework. I tried to learn some basics and found this very interesting. React is also used in building cross-platform apps using &lt;a href="https://reactnative.dev/" rel="noopener noreferrer"&gt;react native&lt;/a&gt; for mobile and &lt;a href="https://www.electronjs.org/" rel="noopener noreferrer"&gt;electronjs&lt;/a&gt; for desktop.&lt;/li&gt;
&lt;li&gt;I want to learn &lt;a href="https://www.adobe.com/in/products/photoshop.html" rel="noopener noreferrer"&gt;Adobe Photoshop&lt;/a&gt; and &lt;a href="https://www.adobe.com/in/products/photoshop-lightroom.html" rel="noopener noreferrer"&gt;Adobe Lightroom&lt;/a&gt; because I'm also a photography enthusiast and want to be better in photo editing.&lt;/li&gt;
&lt;li&gt;I want to learn &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;vue.js&lt;/a&gt;, this is another front end framework for web design that is gaining a lot of traction.&lt;/li&gt;
&lt;li&gt;Master &lt;a href="https://en.wikipedia.org/wiki/SOLID" rel="noopener noreferrer"&gt;SOLID&lt;/a&gt; principles, is fundamental for any good application architecture. I have a good understand of SOLID principles and try to follow these in my application architecture, but no always.&lt;/li&gt;
&lt;li&gt;Learn &lt;a href="https://kubernetes.io/" rel="noopener noreferrer"&gt;Kubernetes&lt;/a&gt;, because of this industry-acclaimed container orchestration system.&lt;/li&gt;
&lt;li&gt;Complete Harvard &lt;a href="https://online-learning.harvard.edu/course/cs50-introduction-computer-science" rel="noopener noreferrer"&gt;CS50&lt;/a&gt; course, this is a great course to refresh your computer science basics and is considered to be the best.&lt;/li&gt;
&lt;li&gt;Learn a bit of &lt;a href="https://www.python.org/" rel="noopener noreferrer"&gt;Python&lt;/a&gt;, python is a favorite for folks in data analysis, AI, and Machine learning. These are areas I would like to learn at some point in the future. So learning a little bit of Python will benefit me. I'm hoping I can lean this as part of the CS50 course.&lt;/li&gt;
&lt;li&gt;I want to learn &lt;a href="https://golang.org/" rel="noopener noreferrer"&gt;golang&lt;/a&gt;, I have a heard lot about golang and how this is being used increasingly more these days.&lt;/li&gt;
&lt;li&gt;Learning &lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;Nodejs&lt;/a&gt;, I know a little bit of nodejs already. I worked on a personal project using nodejs, but did not get time to learn it properly and finish my project.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>learning</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>I created an AutoMapper in C# to copy property values automatically</title>
      <dc:creator>Bipin Radhakrishnan</dc:creator>
      <pubDate>Wed, 27 May 2020 09:24:41 +0000</pubDate>
      <link>https://forem.com/bipinr/i-created-an-automapper-in-c-to-copy-property-values-automatically-1483</link>
      <guid>https://forem.com/bipinr/i-created-an-automapper-in-c-to-copy-property-values-automatically-1483</guid>
      <description>&lt;p&gt;I was working on a project that required mapping values to complex objects when I say complex the target object was a large collection of multiple objects several levels deep. Some of the objects to which the values had to be mapped were several levels down. The task of finding the correct objects or directly assigning values to the properties of objects was tedious, especially if it had to be done over and over again. This problem led me to create the object auto mapper. During the course of this post, the target is the object you are operating on or mapping the values to and the source is the object from which the values are copied.&lt;/p&gt;

&lt;p&gt;Auto mapper uses reflection to index all the objects on which it is operating. After the index is created, the algorithm can then identify the target object on which to operate based on the type of the source object. Once the target object is found then the algorithm sweeps through the properties of the target to identify all the properties that have a public set on them. The algorithm will now set the values of the properties.&lt;/p&gt;

&lt;p&gt;Some of the features of my Auto mapper is&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatically finds the first occurrence of an object type and maps them.&lt;/li&gt;
&lt;li&gt;If there are multiple objects of the same type in the target object, you can specify the property name to map it to.&lt;/li&gt;
&lt;li&gt;If the object already has some data in it, this will preserve the existing once and map only the new once.&lt;/li&gt;
&lt;li&gt;If the target property is null, the auto mapper can initialize the property and map the values.&lt;/li&gt;
&lt;li&gt;If the target property is a List or an Array[], it can initialize it.&lt;/li&gt;
&lt;li&gt;If the property is null or if it already has values the new values get added to it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/rbipin/AutoMapper" rel="noopener noreferrer"&gt;https://github.com/rbipin/AutoMapper&lt;/a&gt;&lt;/p&gt;

</description>
      <category>c</category>
      <category>automapper</category>
      <category>reflections</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>5 Useful IBM DB2 Queries</title>
      <dc:creator>Bipin Radhakrishnan</dc:creator>
      <pubDate>Thu, 04 Jan 2018 05:22:20 +0000</pubDate>
      <link>https://forem.com/bipinr/5-useful-ibm-db2-queries-ek3</link>
      <guid>https://forem.com/bipinr/5-useful-ibm-db2-queries-ek3</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2Fwordpress%2F2018%2F01%2Fibm_db2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2Fwordpress%2F2018%2F01%2Fibm_db2.png" alt="5 Useful DB2 Queries" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are some IBM DB2 queries that can be very useful.&lt;/p&gt;

&lt;h4&gt;
  
  
  Query to identify Stores Procedures that is using a particular table
&lt;/h4&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Identify Schema used by a Stored Procedures
&lt;/h4&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Identify Primary Key of a table
&lt;/h4&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Identify Foreign key of a table
&lt;/h4&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  View used by table
&lt;/h4&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


</description>
      <category>database</category>
      <category>db2</category>
      <category>ibm</category>
      <category>ibmdb2</category>
    </item>
    <item>
      <title>Log4net rolling file log based on date and file size</title>
      <dc:creator>Bipin Radhakrishnan</dc:creator>
      <pubDate>Tue, 15 Aug 2017 03:04:08 +0000</pubDate>
      <link>https://forem.com/bipinr/log4net-rolling-file-log-based-on-date-and-file-size-32k7</link>
      <guid>https://forem.com/bipinr/log4net-rolling-file-log-based-on-date-and-file-size-32k7</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2Fwordpress%2F2017%2F08%2FApacheSoftwareFoundation.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.bipinr.com%2Fcontent%2Fimages%2Fwordpress%2F2017%2F08%2FApacheSoftwareFoundation.png" alt="Log4net rolling file log based on date and file size" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Logging is an important part of any application and a developer spends a good amount of time writing code to log. Logging is important as this helps us create a trace of all the events in the application and in turn helps in debugging, identifying and analyzing issues and bugs. Log4net is an open source framework for logging the output in an application. The application framework is released under Apache License, Version 2.0. Log4net provides multiple types of logging techniques.&lt;/p&gt;

&lt;p&gt;What we are going to discuss today is how to configure log4net for a requirement I wanted to implement in one of my project? Requirement was to implement a rolling log system based on date and file size. i.e I wanted to implement a file logging, that would create a new log file everyday and if the file size extends a certain size it should create a new file.&lt;/p&gt;

&lt;p&gt;To accomplish this, I used the “&lt;em&gt;RollingFileAppender&lt;/em&gt;” for the type of appender. Let’s discuss the important parameters in the configuration.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;PreserveLogFileNameExtension&lt;/em&gt; – This parameter indicates if the file extension of the log files should be preserved during rolling.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;rollingStyle&lt;/em&gt; – Rolling criteria to use for log, I used &lt;em&gt;Composite&lt;/em&gt; to roll based on date and size of the log.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;datePattern&lt;/em&gt; – Date pattern to append to the log file name, I configured this as &lt;em&gt;_MMddyyyy&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;maxSizeRollBackups&lt;/em&gt; – Maximum number of log files to keep before deleting during rolling.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;maximumFileSize&lt;/em&gt; – Maximum size of the log file before it is rolled to new file.
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;staticLogFileName&lt;/em&gt; – Indicates whether to always log in the same file, I set this to &lt;em&gt;true&lt;/em&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the component to read the parameter from the config file. We to add the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XmlConfigurator.Configure();
or
[assembly: log4net.Config.XmlConfigurator(Watch=false)]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The parameters used in the configuration are given below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;log4net&amp;gt;
  &amp;lt;appender name="RollingLogFile" type="log4net.Appender.RollingFileAppender"&amp;gt;
    &amp;lt;file value="log.log" /&amp;gt;
    &amp;lt;PreserveLogFileNameExtension value="true"/&amp;gt;
    &amp;lt;appendToFile value="false" /&amp;gt;
    &amp;lt;rollingStyle value="Composite"/&amp;gt;
    &amp;lt;datePattern value="_MMddyyyy"/&amp;gt;
    &amp;lt;maxSizeRollBackups value="2"/&amp;gt;
    &amp;lt;maximumFileSize value="10KB"/&amp;gt;
    &amp;lt;staticLogFileName value="true" /&amp;gt;
    &amp;lt;layout type="log4net.Layout.PatternLayout"&amp;gt;
      &amp;lt;conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" /&amp;gt;
    &amp;lt;/layout&amp;gt;
  &amp;lt;/appender&amp;gt;
  &amp;lt;root&amp;gt;
    &amp;lt;appender-ref ref="RollingLogFile" /&amp;gt;
  &amp;lt;/root&amp;gt;
&amp;lt;/log4net&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The sample code with the configuration and code used to test the rolling log is available in the below repository&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Sample Code:&lt;/strong&gt; &lt;a href="https://github.com/rbipin/RollingLog_Log4net" rel="noopener noreferrer"&gt;https://github.com/rbipin/RollingLog_Log4net&lt;/a&gt;&lt;/p&gt;

</description>
      <category>filelogging</category>
      <category>log4net</category>
      <category>logging</category>
    </item>
  </channel>
</rss>
