AspNetCoreOData icon indicating copy to clipboard operation
AspNetCoreOData copied to clipboard

Odata 8.0.4 with .net6: not matching DeleteRef route

Open GabrieleVolpato opened this issue 3 years ago • 3 comments

Hello everyone!

I'm using OData 8.0.4 with asp net core 6.0, and I can't find the correct way to implement ODataController's DeleteRef method. I can't understand if I'm failing something or it's a library problem.

This is the signature of my method: public async Task<ActionResult> DeleteRef([FromODataUri] int key, string navigationProperty, [FromODataUri] string relatedKey)

If I remove the relatedKey parameter, it then matches, but I cannot access the id of the related entity. For now, I'm extracting data by getting the id manually from Request's Query, but then another problem occurs. I use the following method to extract the id from the odata string https://localhost:44336/api/Components(3994).

public static TKey GetKeyFromUri<TKey>(HttpRequest request, Uri uri)
{
    if (uri == null)
    {
        throw new ArgumentNullException("uri");
    }

    var odataFeature = request.ODataFeature();
    var uriParser = new ODataUriParser(odataFeature.Model, new Uri(odataFeature.BaseAddress), uri);
    var keySegment = uriParser.ParsePath().OfType<KeySegment>().FirstOrDefault();
    if (keySegment?.Keys == null || !keySegment.Keys.Any())
    {
        throw new InvalidOperationException("The link does not contain a key.");
    }

    return (TKey)keySegment.Keys.FirstOrDefault().Value;
}

But only in this case, oDataFeature.BaseAddress returns null. Other data, like Model, are correctly evaluated.

This is the complete route I'm trying to match: https://localhost:44336/api/Tools(8)/Components/$ref?$id=https://localhost:44336/api/Components(3994)

Thanks to anyone who will help me!

GabrieleVolpato avatar Dec 17 '21 08:12 GabrieleVolpato

I'm facing the same problem (using AspNetCore.OData 8.0.10). Is there a solution in the meantime?

kfrentzel avatar Aug 04 '22 13:08 kfrentzel

The convention documentation has the arguments in a different order than what you are using.

image

(I don't know why the action is called DeleteLink there and not DeleteRef though...)

Does it make any difference for you if you swap the last two arguments and use:

public async Task<ActionResult> DeleteRef(
    [FromODataUri] int key, 
    [FromODataUri] string relatedKey, 
    string navigationProperty)

?

julealgon avatar Aug 04 '22 14:08 julealgon

I've tried that too. The result is the same: 404 Not found. The route cannot be resolved. It looks like there are problems with the RefRoutingConvention.

kfrentzel avatar Aug 05 '22 05:08 kfrentzel

@kfrentzel @GabrieleVolpato

For a single-valued navigation property, you should implement controller actions matching either of the following:

// Let's say the single-valued navigation property is named "Customer"

// DELETE http://localhost:19644/odata/Orders(1)/Customer/$ref
public ActionResult DeleteRefToCustomer([FromRoute] int key)
{
    // ...
}

// Or

// DELETE http://localhost:19644/odata/Orders(1)/Customer/$ref
public ActionResult DeleteRef([FromRoute] int key, [FromRoute] string navigationProperty)
{
    // ...
}

For a collection-valued navigation property, you should implement controller actions matching either of the following:

// Let's say the collection-valued navigation property is named "Orders"

// DELETE http://localhost:5000/odata/Customers(1)/Orders(2)/$ref
public ActionResult DeleteRefToOrders([FromRoute] int key, [FromRoute] int relatedKey)
{
    // ...
}

// Or
// DELETE http://localhost:5000/odata/Customers(1)/Orders(2)/$ref
public ActionResult DeleteRef([FromRoute] int key, [FromRoute] int relatedKey, [FromRoute] string navigationProperty)
{
    // ...
}

Kindly let me know if this helps...

gathogojr avatar Jan 05 '23 19:01 gathogojr

@GabrieleVolpato I'll go ahead and close this. If the solution I proposed doesn't work, feel free to reopen it

gathogojr avatar Jan 09 '23 08:01 gathogojr