OData / WebApi

OData Web API: A server library built upon ODataLib and WebApi
https://docs.microsoft.com/odata
Other
854 stars 476 forks source link

Post Requestbody is not parsed with correct Attribute description #2404

Open DrBlackBird opened 3 years ago

DrBlackBird commented 3 years ago

Assemblies affected

OData WebApi 7.5.5

Hi everybody,

I´m trying to write an API with ASP .Netcore and OData together with API Versioning. I´m facing an issue which I´m totally out of ideas.

I have two models:

public class UserEvent
    {
        [JsonProperty(PropertyName = "id")]
        public string id { get; set; }
        [Required]
        public string UserId { get; set; }
        public string UserName { get; set; }
        public string Source { get; set; }
        public string Operation { get; set; }
        [DataType(DataType.Date)]
        [ModelBinder(typeof(DateTimeModelBinder))]
        public DateTime? DateOfEvent { get; set; }
        public string Resource { get; set; }
        public string ResourceId { get; set; }
        public string ResourceType { get; set; }

        [NotMapped]
        public Host Initiator { get; set; }

        public string UniqueSharingId { get; set; }
        public string ListItemUniqueId { get; set; }

        public string NewHost { get; set; }
    }

and

public class Host
    {
        public string HostUpn { get; set; }
        public string HostObjectId { get; set; }
}

My Edm Model is build like this:

public class UserEventsModelConfiguration : IModelConfiguration
    {

        public void Apply(ODataModelBuilder builder, ApiVersion apiVersion, string routePrefix)
        {
            //builder = ((ODataConventionModelBuilder)builder);
            //builder = new ODataConventionModelBuilder();
            builder.Namespace = "UserEvents";

            builder.EntitySet<UserEvent>("UserEvents");
            var host = builder.ComplexType<Host>();
            builder.ComplexType<Host>().Property(x => x.HostObjectId);
            builder.ComplexType<Host>().Property(x => x.HostUpn);
            var props = builder.ComplexType<Host>().Properties;
            builder.EntityType<UserEvent>().ComplexProperty<Host>(x => x.Initiator);
        }
    }

When I try to create a new UserEvent with Post and this payload:

{
    "Id": "01120510-abbd-4317-9efc-0d10427c3444",
    "Operation": "Test",
    "UserId": "12345",
    "Resource": "API",
    "ResourceId": "1234",
    "initiator":
    {
        "HostUpn": "System",
        "HostObjectId": "11111111-1111-1111-1111-111111111111"
    }
}

works fine!

But with this:

{
    "Id": "01120510-abbd-4317-9efc-0d10427c3444",
    "Operation": "Test",
    "UserId": "12345",
    "Resource": "API",
    "ResourceId": "1234",
    "Initiator":
    {
        "HostUpn": "System",
        "HostObjectId": "11111111-1111-1111-1111-111111111111"
    }
}

it doesnt work.

Note: the only difference is, that "Initiator" is written with a lower i in the working payload and with a capital I in the not working payload.

I tried to debug with the source code of the version 7.5.5 and I found out that in ODataReaderExtensions.cs in ReadCollectionItem() the reader is not able to figure out the nested object inside the payload. With the lower i everything works and the nested object is detected but the the capital I it is not.

Does somebody has an idea what is happening here? Everything else works fine, getting objects also but I totally struggle with post requests...

Thanks a lot!

Best regards Thomas

Sreejithpin commented 3 years ago

Hi, Can you please give little more details: 1) For the case with lower case "i", does the post request gets successful ? 2) For the Upper case "I" can you please let us know what is the error thrown 3) I see you tried conventionalmodelbuilder as well and commented, how is it coming when using conventionalmodelbuilder?

thanks

DrBlackBird commented 3 years ago

Hi @Sreejithpin,

Well it depends. If we use the Conventionalmodelbuilder like this:

builder = new ODataConventionModelBuilder().EnableLowerCamelCase()

it works with lower case

if we use it like this:

builder = new ODataConventionModelBuilder();

it works with upper case characters.

So 1. is true if we use the latter.

  1. The thrown error is the following:
{
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
    "title": "One or more validation errors occurred.",
    "status": 400,
    "traceId": "00-5661c087ee29f645b02786faa2b6e531-439bba459d21db43-00",
    "errors": {
        "": [
            "The input was not valid."
        ]
    }
}
  1. I´m not sure if I understand your question. Can you please be more precise?

And one thing more I wanted to point out is that we found out that requests are parsed case insenstive for "normal" attributes on the Edm Model but not for complex types like in our case the "initiator" is. Maybe that is some worthy information for you.

Thanks!