Luis Valencia
Luis Valencia

Reputation: 33998

Deserialize from HttpRequest not working correctly in web api

I have a custom model binder to get some values from FormData that come from a react application. Everything works fine except for one specific property: TenantDomainUrl. When deseerialization occurs, this value is set to null, even if its sent in the request:

Image1: (just before sending the request, check the console:

enter image description here

The custom model binder code is this:

public class TenantModelBinder : IModelBinder
    {
        public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
        {
            if (bindingContext.ModelType != typeof(Tenant))
            {
                return false;
            }

            var task = Task.Run(async () =>
            {
                var model = new Tenant();

                if (!actionContext.Request.Content.IsMimeMultipartContent())
                {
                    bindingContext.ModelState.AddModelError(bindingContext.ModelName, "WebRequeest content 'multipart/form-data' is valid");
                }
                else
                {
                    var provider = await actionContext.Request.Content.ReadAsMultipartAsync();

                    //var fileContent = provider.Contents.FirstOrDefault(n => n.Headers.ContentDisposition.Name.Equals("file"));
                    var fileContent = provider.Contents.FirstOrDefault(n => n.Headers.ContentDisposition.Name.Equals(@"""file"""));
                    if (fileContent == null)
                    {
                        bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Section 'file' is missed");
                    }

                    //var modelContent = provider.Contents.FirstOrDefault(n => n.Headers.ContentDisposition.Name.Equals("model"));
                    var modelContent = provider.Contents.FirstOrDefault(n => n.Headers.ContentDisposition.Name.Equals(@"""model"""));
                    if (modelContent == null)
                    {
                        bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Section 'model' is missed");
                    }

                    if (fileContent != null && modelContent != null)
                    {
                        model = JsonConvert.DeserializeObject<Tenant>(
                            await modelContent.ReadAsStringAsync());

                        model.CertificateFile = fileContent.ReadAsByteArrayAsync().Result;
                    }
                }

                return model;
            });

            task.Wait();

            bindingContext.Model = task.Result;
            return true;
        }
    }

And the 2nd image after deserialization

enter image description here

I dont think I actually need to post the REACT JS Code

Update:

readasstring returns the json correctly with the value, but after deserialization the property is null:

enter image description here

Update 2, tenant class

public class Tenant
    {
        [JsonProperty("id")]
        public string TenantDomainUrl { get; set; }

        public string ApplicationId { get; set; }

        public string SiteCollectionTestUrl { get; set; }

        public string CertificatePassword { get; set; }

        public byte[] CertificateFile { get; set; }


        public Uri CertificatePath { get; set; }

        public override string ToString()
        {
            return JsonConvert.SerializeObject(this);
        }
    }

Upvotes: 0

Views: 333

Answers (2)

pfx
pfx

Reputation: 23244

Because of the JsonProperty it will not be read from the TenantDomainUrl JSON value, but from id.

[JsonProperty("id")]

Remove the attribute, or alter the posted JSON.

UPDATE

In your first picture above I notice

 "id":null

Refering to a previous post on this topic, make sure to pass this id via your FormData with the key id and the value set, something like here below.

data.append("model", JSON.stringify({ "id": "your-id-goes-here" }} 

Upvotes: 2

reZach
reZach

Reputation: 9459

Edit:

If the [JsonProperty("id")] must stay on TenantDomainUrl, you need to change the JSON you post to this endpoint to have a key of id instead of TenantDomainUrl. Something like this

{"id":"cm.microsoft.com","ApplicationId":"a21-fan-...", /* other properties in your JSON */}

instead of

{"TenantDomainUrl":"cm.microsoft.com","ApplicationId":"a21-fan-...", /* other properties in your JSON */}

Upvotes: 1

Related Questions