OData / WebApi

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

Inconsistent casing behavior between raw enum strings and fully qualified enum strings in OData requests #1668

Open julealgon opened 5 years ago

julealgon commented 5 years ago

When making an OData request, one can either specify just the string representation for an enum parameter, or its fully qualified name. When using the fully qualified name, the OData parser accepts the values using case insensitive logic, but when passing only the string values, casing needs to match exactly with the enum member for the request to work.

Assemblies affected

Microsoft.AspNetCore.OData 7.0.1

Reproduce steps

  1. Create an API that takes an enum as a paramter. For example:
    namespace Company.Domain
    {
    public enum ProductType
    {
        Undefined,
        TypeA,
        TypeB
    }
    }
[ODataRoute("Default.GetProductsByType(ProductType={productType})")]
public ActionResult<IEnumerable<ProductDetail>> Get(ProductType productType)
{
    ...
}
var function = builder.EntityType<ProductDetail>().Collection.Function("GetProductsByType");
function.Parameter<ProductType>("ProductType");
function.ReturnsCollectionFromEntitySet<ProductDetail>("ProductDetails");
  1. Make a request using fully qualified namespace a. GET http://localhost/api/odata/productdetails/GetProductsByType(ProductType=Company.Domain.ProductType'typea') b. GET http://localhost/api/odata/productdetails/GetProductsByType(ProductType=Company.Domain.ProductType'TypeA')

  2. Make a request using enum name only a. GET http://localhost/api/odata/productdetails/GetProductsByType(ProductType='typea') b. GET http://localhost/api/odata/productdetails/GetProductsByType(ProductType='TypeA')

Expected result

All 4 requests should pass parsing and hit the controller with the same ProductType.TypeA enum value.

Actual result

Requests 2.a, 2.b, and 3.b pass as expected. Request 3.a fails with a HTTP 404.

KanishManuja-MS commented 5 years ago

@julealgon This may have been fixed with 7.0.2 but let me confirm that. I will get back to you when I get the time to investigate this.

freeranger commented 5 years ago

@KanishManuja-MS Did you manage to confirm if this is the case? thanks

KanishManuja-MS commented 5 years ago

@freeranger Not yet, I was occupied with other tasks. The new version (7.1) is released now but I suspect that this may not have been fixed as I was doing some testing tangential to this issue. I will have more detailed investigation notes posted next week if this gets some time allocated next week.

freeranger commented 5 years ago

Yeah I upgraded to 7.1 and unfortunately you are correct in that it is not fixed there.

TheDevelolper commented 3 years ago

I think I might be seeing something similar but not quite the same for posts:

We have a user management system. Users can login using either windows or forms based Authentication. We use a very simple enum on our backend to represent the user logon type:

public enum UserLogonType
{
    Forms,
    Windows,
}

When we use the generated client to send the request it contains the following:

AccountType: "Models.Enums.UserLogonType'Windows'"

This causes the server to return a bad request as it can't parse the Enum.

If I modify the request and send this it works:

AccountType: "Windows"

I can also send the number and that will work too:

AccountType: 1
julealgon commented 3 years ago

@FacePalmDev I'd recommend opening a separate issue for your problem. While it is related to how enums are serialized, this one was very specifically talking about the casing problem on the enum member.

Yours appears to be different here (not being able to desserialize a full enum specification altogether), so you may get more traction with a dedicated issue.

I agree they might be related though, so would suggest referencing this one from the new one.

TheDevelolper commented 3 years ago

@julealgon actually it turned out that the problem was on the front end... had to add a single line to my config. Fix here:

https://github.com/diegomvh/angular-odata/issues/23