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

OData: Getting an item by ID returns a 404. #1188

Closed TonyValenti closed 2 years ago

TonyValenti commented 6 years ago

Getting an item by ID returns a 404.

Assemblies affected

Microsoft.ASPNETCore.OData 7.0.0.11221

Reproduce steps

Create a method such as:

        public virtual async Task<ContactJson> Get([FromODataUri] long key) {
            var query = await API.Get(key)
                .DefaultAwait()
                ;

            return query.Response;
        }

Then go to a URI such as: http://localhost:5000/odata/ContactApi(945741858)/Email_Addresses

Expected result

My Get method is invoked.

Actual result

I receive a 404 error.

Additional detail

xuzhg commented 6 years ago

Hi, @TonyValenti

Your URI http://localhost:5000/odata/ContactApi(945741858)/Email_Addresses looks like a property access. Basically,

  1. Get() handles the request like http://localhost:5000/odata/ContactApi
  2. Get(long key) handles the request like http://localhost:5000/odata/ContactApi(945741858)
  3. Get{PropertyName)(long key) handles the request like http://localhost:5000/odata/ContactApi(945741858)/{PropertyName}

So, only a Get method can't handle your property access request. if you haven't a method name GetEmail_Addresses(long key) in your controller, you will get a 404 response.

TonyValenti commented 6 years ago

@xuzhg Thanks for that info. How do I make it so that all property accesses are automatically implemented? My objects have lots of properties and I kind of expect that when I return an object, the system can automatically figure out how to get just that specific property.

xuzhg commented 6 years ago

@TonyValenti

Here's a sample https://github.com/xuzhg/WebApiSample/commit/f8ef59296d4bdf9f3a51bd7d245244baf62316e4 That you can refer to.

TonyValenti commented 6 years ago

@xuzhg

Thanks for putting that sample together but it does not seem to work for ASPNetCore/OData Core. Do you have any other suggestions?

xuzhg commented 6 years ago

@robward-ms

robward-ms commented 6 years ago

@TonyValenti:

As Sam mentioned, property access requires a method to handle the property retrieval. While Sam's sample uses a custom routing convention, the built-in PropertyRoutingConvention handles this for you. We have a bit of info in the docs about this convention here: http://odata.github.io/WebApi/#03-04-custom-routing-convention.

Using the current build, I validated that adding a property access method works as you expect it to. Basically, you need to add a controller method like:

public GetEmail_Addresses([FromODataUri] string key) { ...return the email addresses from the object matching key or NotFound(). }

The code for the PropertyRoutingConvention, specifically the part that looks for the mathcing action name, is here: https://github.com/OData/WebApi/blob/ba37702e8371a3f361e6075f8c20dbb343620e03/src/Microsoft.AspNet.OData.Shared/Routing/Conventions/PropertyRoutingConvention.cs#L31-L33

Can you try this and report back?

TonyValenti commented 6 years ago

Hi Rob, Is there a way for me to do this without implementing a whole bunch of boilerplate methods. Basically what I'm hearing is that I'll need to implement a lot of methods that look like this:

public <typeOfEmail_Addresses> GetEmail_Addresses([FromODataUri] string key)
{
  return Get(key).EmailAddresses;
}

public <typeOfPhone_Numbers> GetPhone_Numbers([FromODataUri] string key)
{
  return Get(key).PhoneNumbers;
}

//etc.

In my situation, I want to use OData to basically expose a set of in-memory objects to reporting through Excel.

Always glad to help,

[image: AlphaDrive for Clio] https://www.alphadriveforclio.com/

Tony Valenti Software Engineer T: 402-401-7568 E: Tony.Valenti@AlphaDriveForClio.com W: www.AlphaDriveForClio.com https://www.alphadriveforclio.com/

Schedule a Meeting with Me https://www.alphadriveforclio.com/schedule-meeting This message contains confidential information and is intended only for the intended recipients. If you are not an intended recipient you should not disseminate, distribute or copy this e-mail. Please notify us immediately by e-mail if you have received this e-mail by mistake and delete this e-mail from your system. E-mail transmission cannot be guaranteed to be secure or error-free as information could be intercepted, corrupted, lost, destroyed, arrive late or incomplete, or contain viruses. Therefore we do not accept liability for any errors or omissions in the contents of this message, which arise as a result of e-mail transmission. If verification is required please request a hard-copy version.

On Tue, Feb 6, 2018 at 12:31 PM, Rob Ward notifications@github.com wrote:

@TonyValenti https://github.com/tonyvalenti:

As Sam mentioned, property access requires a method to handle the property retrieval. While Sam's sample uses a custom routing convention, the built-in PropertyRoutingConvention handles this for you. We have a bit of info in the docs about this convention here: http://odata.github.io/WebApi/#03-04-custom-routing-convention.

Using the current build, I validated that adding a property access method works as you expect it to. Basically, you need to add a controller method like:

public GetEmail_Addresses([FromODataUri] string key) { ...return the email addresses from the object matching key or NotFound(). }

The code for the PropertyRoutingConvention, specifically the part that looks for the mathcing action name, is here: https://github.com/OData/WebApi/blob/ ba37702e8371a3f361e6075f8c20dbb343620e03/src/Microsoft. AspNet.OData.Shared/Routing/Conventions/PropertyRoutingConvention.cs# L31-L33

Can you try this and report back?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/OData/WebApi/issues/1188#issuecomment-363519515, or mute the thread https://github.com/notifications/unsubscribe-auth/AM-qVuGsqQ894IumVxAmIEa0hYF9fGUHks5tSJqIgaJpZM4RR6P7 .

robward-ms commented 6 years ago

That functionality is not currently implemented out-of-the box. You could create a custom routing convention that route all such calls to a method of your choosing and handle it in that method. That is what the sample Sam provided does: the routing convention handles property routing by resolving all calls to the "ReturnPropertyValue" method, which then takes the property name as a parameter. You could then use reflection to lookup the value without hard-coding a property name to property lookup.

DennisInSky commented 4 years ago

I am getting the same 404 error when just trying to query an item by its id like http://localhost:111/odata/Products(1)

I have a controller methods like this `[HttpGet] [EnableQuery] public IEnumerable GetModels() { return Products.AsQueryable(); }

public ProductModel GetModelById([FromODataUri] int key) { throw new NotImplementedException(); }`

Would you please clarify if it is supposed to work out-of-the box or I have to implement custom routing?

gathogojr commented 2 years ago

Fixed by https://github.com/OData/WebApi/pull/2456 - support for deeply nested paths