Belizzle
Belizzle

Reputation: 1414

Deserializing a generic object from POST body

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;

Upvotes: 2

Views: 4853

Answers (3)

raichiks
raichiks

Reputation: 286

I use this code for generic post method with data returned. Then you can pass any class, so the request is more generic.

 public class Requests
 {
 //...
 public async Task<ResultType> Create<ResultType>(string uri)
 {
 //TODO implementation of httpclient POST logic go here
            
var data = await results.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<ResultType>(data);
return result;
}

Call method

List<foo> foos = new List<foo>();
Request requestToServer = new request();
Task.WaitAll(Task.Run(async =>(){
foos = await requestToServer.Create<Foo>("/foo");
}));

Now You can pass any predefined class

Upvotes: 1

Leonid Salavatov
Leonid Salavatov

Reputation: 221

.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

Upvotes: 0

Haithem KAROUI
Haithem KAROUI

Reputation: 1611

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

Upvotes: 0

Related Questions