title: Serializing Enum as string using attribute in Azure Functions 3.0
body: <p>I have tried getting an HTTP-trigger in an Azure Functions 3.0/3.1 app to return the string-representation of enums without any luck. I have tried both Core 3.0 and Core 3.1.</p>
  
  <p>Given this class:</p>
  
  <pre class="lang-cs prettyprint-override"><code>public enum TestEnum
  {
     TestValue
  }
  
  public class TestClass
  { 
     public TestEnum Test { get; set; }
  }
  </code></pre>
  
  <p>I expect this HTTP-trigger:</p>
  
  <pre class="lang-cs prettyprint-override"><code>[FunctionName("MyHttpTrigger")]
  public static IActionResult Run(
     [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log)
  {
      return new OkObjectResult(new TestClass { Test = TestEnum.TestValue });
  }
  </code></pre>
  
  <p>to return <code>{ "test": "TestValue" }</code>. Instead it returns <code>{ "test": 0 }</code>.</p>
  
  <p>In .Net Core 2, I could decorate the enum using <code>[JsonConverter(typeof(StringEnumConverter))]</code> from the namespace <code>Newtonsoft.Json</code> to make this happen. This does not work now.</p>
  
  <p>I know .Net Core 3 switched to the converter in the <code>System.Text.Json</code>-namespace, so I tried decorating the same enum with <code>[JsonConverter(typeof(JsonStringEnumConverter))]</code> from the namespace <code>System.Text.Json.Serialization</code>. This did not work either.</p>
  
  <p>All of the other similar issues either says that the above should work, or, like <a href="https://stackoverflow.com/questions/58440400/enum-type-no-longer-working-in-net-core-3-0-frombody-request-object">this</a>, says to solve it by configuring JsonOptions in the <code>.AddControllers()</code> or <code>.AddMvc()</code>-chain, but for a function app that won't work. The function runtime is responsible for setting up the controllers, so we don't have direct access to further configuration AFAIK.</p>
  
  <p>The issue should be reproducible with a barebones Azure Functions project using the core tools:</p>
  
  <pre><code>func init MyFunctionProj
  cd MyFunctionProj
  func new --name MyHttpTrigger --template "HttpTrigger"
  </code></pre>
  
  <p>Then change the http trigger to return an object with an enum inside.</p>
  
  <p>My versions:</p>
  
  <pre><code>&gt; func --version
  3.0.1975
  &gt; dotnet --version
  3.1.100
  </code></pre>
  
  <h2>Additional information</h2>
  
  <p>I have tried multiple workarounds, so here is some of my observations.
  <code>OkObjectResult</code> is handled by <a href="https://github.com/aspnet/Mvc/blob/master/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/ObjectResultExecutor.cs" rel="noreferrer">ObjectResultExecutor</a>. I tried to copy the implementation into my solution and adding it to the DI container so I could debug:</p>
  
  <pre class="lang-cs prettyprint-override"><code>builder.Services.AddSingleton&lt;IActionResultExecutor&lt;ObjectResult&gt;, TestExecutor&gt;();
  
  </code></pre>
  
  <p>At line 101 in the linked source, the formatter is chosen. Interestingly, when I break at this point, the formatter chosen is <a href="https://github.com/aspnet/AspNetCore/blob/master/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonOutputFormatter.cs" rel="noreferrer">NewtonsoftJsonOutputFormatter</a>! I would think the first <code>JsonConverter</code>-attribute should work with this, but it doesn't.</p>
  
  <p>I figured it would be worth a shot to modify the list of available output formatters. The ActionResultExecutor uses <a href="https://github.com/aspnet/AspNetCore/blob/master/src/Mvc/Mvc.Core/src/Infrastructure/DefaultOutputFormatterSelector.cs" rel="noreferrer">DefaultOutputFormatterSelector</a> to make its selection, which in turn injects <code>IOptions&lt;MvcOptions&gt;</code> to get output formatters.</p>
  
  <p>To force the <code>DefaultOutputFormatterSelector</code> to choose differently I tried this:</p>
  
  <pre class="lang-cs prettyprint-override"><code>class MvcOptionsConfiguration : IPostConfigureOptions&lt;MvcOptions&gt; 
  {
  ...
  }
  
  public class Startup : FunctionsStartup
  {
      public override void Configure(IFunctionsHostBuilder builder)
      {
          builder.Services.ConfigureOptions&lt;MvcOptionsConfiguration&gt;();
      }
  }
  </code></pre>
  
  <p>Note that the regular <code>IConfigureOptions&lt;T&gt;</code> couldn't be used as the <code>options.Outputformatters</code>-collection was missing all other formatters than <code>Microsoft.AspNetCore.Mvc.WebApiCompatShim.HttpResponseMessageOutputFormatter</code>, which is strange in itself (why is a brand new 3.0 app using a compatibility shim?).</p>
  
  <p>I tried to remove the type <code>NewtonsoftJsonOutputFormatter</code> from the collection using:</p>
  
  <pre class="lang-cs prettyprint-override"><code>options.OutputFormatters.RemoveType&lt;NewtonsoftJsonOutputFormatter&gt;();
  </code></pre>
  
  <p>To do that I had to reference the nuget package <code>Microsoft.AspNetCore.Mvc.NewtonsoftJson</code> to access the type, but the type when I referenced it was different from the one used by the runtime. <code>type.Assembly.CodeBase</code> for the type used by the runtime was located in <code>%USERPROFILE%/AppData/Local/AzureFunctionsTools/</code> but the one from nuget was located in <code>Project root/bin/Debug</code>. I have never encountered this before. Usually, the package will be a transient dependency so I can reference it without explicitly depending on the package myself, so I'm not really sure what's going on here. Is this normal, or is there something wrong in my environment?</p>
  
  <p>When I removed it in another manner it didn't matter and it got selected anyway, so it seems like the <code>MvcOptions</code> injected in <code>DefaultOutputFormatterSelector</code> is not the same <code>MvcOptions</code> we can configure in the startup.</p>
  
  <p>At this point, I ran out of leads and turned to you guys. I hope there is someone who can point me in the right direction.</p>