Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OData function works with one parameter but not two or more #64

Closed
dcadlereii opened this issue Jan 7, 2021 · 5 comments
Closed

OData function works with one parameter but not two or more #64

dcadlereii opened this issue Jan 7, 2021 · 5 comments
Assignees

Comments

@dcadlereii
Copy link

dcadlereii commented Jan 7, 2021

I am working on a greenfield ASP.NET 5 (net5) API and we are using Microsoft OData v8.00-preview3. I have created a function with one parameter that is working correctly. However, when I add a second parameter to that same function, I get a 404 not found when I run the API and try to hit the endpoint function in Postman.

Here is my Edm model builder. Note: With the 2nd parameter commented out, This function works properly;

   public static IEdmModel GetEdmModelV1()
   {
        var builder = new ODataConventionModelBuilder();

        var organizationModel = builder.EntitySet<Organization>("Organizations").EntityType.HasKey(o => o.OrganizationId);

        var productPrice = organizationModel.Collection
            .Function("GetPrice")
            .Returns<ProductPrice>();
        productPrice.Parameter<string>("organizationId").Required();
        //productPrice.Parameter<string>("partId").Required();

        return builder.GetEdmModel();
    }

Here is my controller. Note: The Get and Get() method work just fine. And the GetPrice method with just one parameter gets hit as expected and stops at the marked debug breakpoint. However, if I uncomment the 2nd parameter in the edm model builder class and replace the ODataRoute and method signature of the GetPrice method with the lines that are currently commented out below, I get a 404 Not Found error and the GetPrice method marked breakpoint is never hit.

    [Authorize]
    [ODataModel("odata-v1")]
    public class OrganizationsController : ControllerBase
    {
        private readonly CdContext context;

        public OrganizationsController(CdContext context)
        {
            this.context = context ?? throw new ArgumentNullException(nameof(context));
        }

        [HttpGet]
        [EnableQuery]
        public IEnumerable<Organization> Get()
        {
            return context.Organizations;
        }

        [EnableQuery]
        public IActionResult Get(string key)
        {
            context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
            var entity = context.Organizations.SingleOrDefault(o => o.OrganizationId == key);
            if (entity == null)
            {
                return NotFound($"No organization was found with OrganizationId = {key}");
            }

            return Ok(entity);
        }

        [HttpGet]
        //[ODataRoute("ProductPrices(organizationId={organizationId}, partId={partId})")]
        [ODataRoute("GetPrice(organizationId={organizationId}")]
        //public ProductPrice ProductPrice([FromODataUri] string organizationId, [FromODataUri] string partId)
        public IActionResult GetPrice([FromODataUri] string organizationId)
        {
            ...   // <-- Breakpoint placed on this line
            ...
            ...
        }
    }

Here is the URL in Postman for the single parameter function that works and the two parameter function that get the 404 Not Found.

https://{{url}}/odata-v1/organizations/GetPrice(OrganizationId='10001')  <-- Working single parameter request URL

https://{{url}}/odata-v1/organizations/GetProductPrice(organizationId='10001', partId='100000-01')  <-- This does not work and gets a 404 Not Found response

I should mention that the second parameter, PartId, is not a field in the Organization Model. I just need that value for the processing within the controller method

Is this a bug or am I missing something.

@xuzhg
Copy link
Member

xuzhg commented Jan 8, 2021

@dcadlereii

I can't find a method named "GetProductPrice" defined in the "GetEdmModelV1". Do you mean "GetPrice" method?

So, I can't understand 'https://{{url}}/odata-v1/organizations/GetProductPrice(organizationId='10001', partId='100000-01')', do you mean 'https://{{url}}/odata-v1/organizations/GetPrice(organizationId='10001', partId='100000-01')'

Let's assume that you

  1. use "GetPrice" function name
  2. has two parameters (organizationId, partId)
  3. the action name in the controller is also "GetPrice".

Then, it should work.

"Be noted", your request call has a "whitespace" before "partId='100000-01'. If you remove it, it should work as below Postman snapshot:

Detail test codes, you can find it in daea53c

image

@xuzhg xuzhg self-assigned this Jan 8, 2021
@dcadlereii
Copy link
Author

Sam,

Thanks so much for the quick reply. Your blog is actually what started me on the v8.00 path on this project. The issue was, in fact, the whitespace between the first and second parameter. The function name difference in my posted code example was because I had tried changing the name when troubleshooting while I was creating the original post and didn't realize I had already copy and pasted the old edm model with the modified controller code. I really appreciate your help :)

@RobTF
Copy link

RobTF commented Feb 7, 2021

I made this mistake as well and it took me a while to understand what was going on; as you say

http://some/path/myFunc(param1='something', param2='another') will 404, whereas
http://some/path/myFunc(param1='something',param2='another') will work.

Another thing to watch out for is that if you get the parameter data types subtlety wrong this can also result in a 404, for example if my parameters to the OData function are Guid and then string, the example below applies;

http://some/path/myFunc(param1='B334999A-CD71-4178-BF55-E66B601C2A45',param2='another') will 404, whereas
http://some/path/myFunc(param1=B334999A-CD71-4178-BF55-E66B601C2A45,param2='another') will work.
(note the single quotes around the Guid param in the first example)

It's technically correct, although I suppose a 400 with details of the typing problem might be more intuitive.

@xuzhg
Copy link
Member

xuzhg commented Apr 28, 2021

@RobTF It sounds we need to support the parameter constraint. So far, i haven't had a design for that.

@xuzhg
Copy link
Member

xuzhg commented Jan 18, 2022

Close it. Please file a new issue if you have questions/concerns. Thanks.

@xuzhg xuzhg closed this as completed Jan 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants