Raskolnikov
Raskolnikov

Reputation: 4009

Sent complex object with api

There are many topic but nothing is helpful to me.

I will show you what have I done, and you can tell me what is wrong.

In api I want to desirialize complex object that is send from client:

    [HttpPost]
    public async Task Post([FromBody]string item)
    {
        WorkItem data = JsonConvert.DeserializeObject<WorkItem>(item);
        //...
    }

How I post complex object:

public async Task AddWorkItem()
{
    using (var client = HttpClientFactory.GetClient())
    {
        var item = new WorkItem()
        {
           Description = DateTime.Now.ToString("h:mm:ss tt"),
           Id = 11
        };

        var inner1 = new ItemUsage()
        {
            Id = 45,
            UsedFor = "something"
        };

        Collection<ItemUsage> Usage = new Collection<ItemUsage>();
        Usage.Add(inner1);

        item.Usage = Usage;

        string output = JsonConvert.SerializeObject(item);

        var response = await client.PostAsync("api/WorkItem", new StringContent(output));
        if (!response.IsSuccessStatusCode)
        {
            throw new Exception((int)response.StatusCode + "-" + response.StatusCode.ToString());
        }
    }

I get error : 415-UnsupportedMediaType . Maybe my aproach is not best? I need some clean way to post any complex object and my idea is to do this with Json string. What do you think?

Upvotes: 0

Views: 103

Answers (3)

Raskolnikov
Raskolnikov

Reputation: 4009

Ok it is now clear to me. I will add whole code so that someone else can use it.

   [HttpPost]
        public async Task Post([FromBody]WorkItem item)
        {
            //No need to deserialize, you can use item here
        }

Call api:

 public async Task AddWorkItem()
        {
            using (var client = HttpClientFactory.GetClient())
            {
                //Complex object example::
                ///////////////////
                var item = new WorkItem()
                {
                    Description = DateTime.Now.ToString("h:mm:ss tt"),
                    Id = 11
                };

                var inner1 = new ItemUsage()
                {
                    Id = 45,
                    UsedFor = "something"
                };

                Collection<ItemUsage> Usage = new Collection<ItemUsage>();
                Usage.Add(inner1);

                item.Usage = Usage;
                ////////////////////////////
                var json = JsonConvert.SerializeObject(item);
                var content = new StringContent(json, UnicodeEncoding.UTF8, "application/json");
                var response = await client.PostAsync("api/WorkItem", content);
                if (!response.IsSuccessStatusCode)
                {
                    throw new Exception((int)response.StatusCode + "-" + response.StatusCode.ToString());
                }
            }
       }

Create client

public static class HttpClientFactory
    {
        public static HttpClient GetClient()
        {
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri("http://localhost:1431");

            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));

            return client;
        }
    }

Upvotes: 0

Avinash Jain
Avinash Jain

Reputation: 7616

Look like issue is with the datetime serialization. Please see the below answer for help

JsonConvert.SerializeObject vs JsonSerializer.Serialize

Upvotes: 0

Phil
Phil

Reputation: 84

you are missing one of the key features of WebAPI called model binding or parameter binding. Before the Controller's Action is invoked the incoming data is bound to the Actions parameters. In other words the WebAPI pipeline will handle most deserialization for you. In your example your parameter type is a string, but what you are sending to the server cannot be converted into a string. Supposing the rest of your plumbing is fine, changing the parameter type to WorkItem should do the trick. public async Task Post([FromBody]WorkItem item) If you must accept a string parameter then you must ensure that the body of the request can be converted to a string or write a custom model binder. See here for more info on raw request body handling

Upvotes: 1

Related Questions