Deserializing a generic object from POST body

Viewed 2844

I have a WebAPI endpoint that to takes in a generic object.

[HttpPost]
[ApiRoute("endpoint/{type}")]
public IHttpActionResult MyPostEndpoint(TypeEnum type, [FromBody] object myObject){}

We work on the object generically but then eventually convert it to our object type, but when we do we have to turn it into a JObject first, so grabbing the object looks like this:

var myfoo = ((JObject) object).ToObject<Foo>();

If I supply Foo directly as my POST parameter (e.g. [FromBody] Foo myObject) then it deserializes the incoming JSON to a Foo, but it won't deserialize to a generic C# object. Is there a way I can get it to deserialize to a generic C# object instead of leaving it a JObject so I can get myfoo like this instead?

var myfoo = (Foo) object;
3 Answers

I think you can do like following to have a loosely typed method

public static class HttpRequestHelper
    {
        public static async Task<T> GetDataModelFromRequestBodyAsync<T>(HttpRequestMessage req)
        {
            dynamic requestBody = await req.Content.ReadAsStringAsync();
            object blobModelObject = JsonConvert.DeserializeObject<object>(requestBody);
            var blobModel = ((JObject)blobModelObject).ToObject<T>();

            return blobModel;
        }
    }

and usage is like following:

var blobModel = await HttpRequestHelper.GetDataModelFromRequestBodyAsync<RequestBlobModel>(req);

Hope This Helps

.NET CLI

dotnet new web --name "GenericEndpointExample"
cd GenericEndpointExample
dotnet add package SingleApi

Program.cs:

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

// map generic endpoint
app.MapSingleApi("sapi", 
    // add your generic request handler
    // for example, return the received data (already typed object)
    x => Task.FromResult(x.Data), 
    // add assemblies for resolving received data types
    typeof(MyClassName).Assembly, typeof(List<>).Assembly, typeof(int).Assembly);

app.Run();

Example request for type: MyClassName

POST /sapi/MyClassName
{"Name":"Example"}

Example request for generic: Dictionary<string,int?[]>

POST /sapi/Dictionary(String,Array(Nullable(Int32)))
{"key1":[555,null,777]}

GitHub repository with examples

Related