1

I've created an ASP.NET 2.0 webapi and am trying to return an abstract type from a method which returns IActionResult, i.e.

    // GET api/trades/5
    [HttpGet("{id}", Name = "GetTrade")]
    [ProducesResponseType(typeof(Trade), 200)] 
    [ProducesResponseType(404)]
    public IActionResult Get(int id)
    {
        var item = _context.Trades.FirstOrDefault(trade => trade.Id == id);
        if (item == null)
        {
            return NotFound();
        }
        return Ok(item);
    }

The Trade type is an abstract base class, I want the serialised JSON to include the $type attribute so the client can deserialise to the correct concrete type. The code below controls the output serialiser if I change the method to return Trade (the json returned contains a $type attribute with the concrete type name) but not IActionResult (no $type attribute).

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services
            .AddDbContext<RiskSystemDbContext>(opt => opt.UseInMemoryDatabase("RiskSystemDb"));

        services
            .AddMvc(options => {})
            .AddJsonOptions(options =>
            {
                options.SerializerSettings.Converters.Add(new StringEnumConverter());
                options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
                options.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;
            });
    }

How do I set TypeNameHandling for an IActionResult?

Edit:

For a class FutureTrade : Trade {} I expect

{
  "$type": "RiskSystem.Model.FutureTrade, RiskSystem.Model",
  "id": 1,
  "createdDateTime": "2018-04-12T15:59:11.3680885+12:00"
  ...
}

Getting

{
  "id": 1,
  "createdDateTime": "2018-04-12T15:59:11.3680885+12:00"
  ...
}

The following works as expected

    // GET api/trades
    [HttpGet]
    public IEnumerable<Trade> Get()
    {
        return _context.Trades.ToList();
    }

Regards Dave

7
  • 1
    Please include some expected and actual json object structure that is returned to your JS client. This will help everyone to visualize your issue. Commented Apr 12, 2018 at 5:44
  • I've edited as requested (the client is .Net not JS though) Commented Apr 12, 2018 at 7:10
  • Can you try with this option options.SerializerSettings.TypeNameHandling = TypeNameHandling.Objects Commented Apr 12, 2018 at 7:46
  • Thanks, that seems to work consistently. Add as a proper solution and I'll mark it as the answer. Commented Apr 12, 2018 at 16:07
  • 1
    @user2981639 by default web api uses JSON.NET serializer settings as TypeNameHandling.None so the $type is not included, you can change it as per your requirement. Commented Apr 13, 2018 at 12:38

1 Answer 1

1

Changing the TypeNameHandling from Auto to Objects will force the JSON serializer to emit the type name always.

Please change your TypeNameHandling from

options.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;

to

options.SerializerSettings.TypeNameHandling = TypeNameHandling.Objects
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.