1

I need to create an OData controller with this assign.

http://xxxxxx/odata/mock/Itens(NumContrato='1234',IdItem='10')/Pedidos

ItensController

public class ItensController : ODataController
{
    [HttpPost]
    [ODataRoute("(NumContrato={NumContrato},IdItem={IdItem})/Pedidos")]
    public IQueryable<Pedido> Pedidos([FromODataUri] string NumContrato, [FromODataUri] string IdItem)
    {
        ... do something
    }
}

WebApiConfig.cs

...
config.Routes.MapODataServiceRoute(
        "ODataRoute",
        "odata/mock",
        model: GetModel(),
        new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));
...

public static IEdmModel GetModel()
{
    ODataModelBuilder builder = new ODataConventionModelBuilder();
    ...
    builder.EntitySet<Dominio.ODataSapFake.Item>("Itens");
    builder.EntitySet<Dominio.ODataSapFake.LinhaDeServico>("LinhasDeServicos");
    builder.EntitySet<Dominio.ODataSapFake.Pedido>("Pedidos");
    var a = builder.Entity<Dominio.ODataSapFake.Item>().Collection.Action("Pedidos");
    a.Parameter<string>("NumContrato");
    a.Parameter<string>("IdItem");
    a.ReturnsCollectionFromEntitySet<Dominio.ODataSapFake.Pedido>("Pedidos");
    ...
    return builder.GetEdmModel();
}

An error occurs when call service.

<m:error xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
    <m:code/>
    <m:message xml:lang="en-US">
        No HTTP resource was found that matches the request URI 'http://localhost:4492/odata/mock/Itens(NumContrato='100',IdItem='00040')/Pedidos'.
    </m:message>
    <m:innererror>
        <m:message>No routing convention was found to select an action for the OData path with template '~/entityset/key/navigation'.
        </m:message>
        <m:type/>
        <m:stacktrace/>
    </m:innererror>
</m:error>
5
  • You should also post the structure of the Item, that would have solved the issue a lot quicker :) Commented Sep 7, 2020 at 5:28
  • I agree, but it is a giant class and did not know custom routing. By the way, that's how I solved the problem. :) Commented Sep 8, 2020 at 14:16
  • Cool, I see you've added that tag now, you should post your solution as an answer, did you use attribute notation or a CustomRouteConvention. the docs are pretty good on custom routing learn.microsoft.com/en-us/odata/webapi/routing-abstract Commented Sep 9, 2020 at 0:26
  • When your class is large, you only need to include the main elements, such as the class name, the key properties and any other properties that you reference in your question, such as filters or in this case Pedidos. Just put an elipsis ... to indicate lines of code that are omitted. It sounds like I'm being pedantic but often going through the process to write a good question helps you to resolve the issue, you can still post it, and you can post your solution and you will still draw commentary. Commented Sep 9, 2020 at 0:30
  • Of course not! I need to participate more, write more... for practicing! Commented Sep 9, 2020 at 1:53

1 Answer 1

1

Either your URL is incorrect, or your configuration is incorrect, lets explore both possibilities:

Assuming that the config is correct, you have declared Action called Pedidos has 2 parameters, and it is bound to the collection, no to an item... the URL that matches your definition is actually:

~/Itens/Pedidos(NumContrato='1234',IdItem='10')

Assuming that URL is correct, then you need to configure the endpoint as an Item bound Action and we also assume that the Itens record already has the keys NumContrato and IdItem defined:

builder.EntitySet<Dominio.ODataSapFake.LinhaDeServico>("LinhasDeServicos");
builder.EntitySet<Dominio.ODataSapFake.Pedido>("Pedidos");
var itens = builder.EntitySet<Dominio.ODataSapFake.Item>("Itens");
// Key should be defined by attribute notation, but we can redefine it here for clarity
itens.EntityType.HasKey(x => x.NumContrato);
itens.EntityType.HasKey(x => x.IdItem);
// declare the Action bound to an Item
itens.Item.Action("Pedidos")
    .ReturnsCollectionFromEntitySet<Dominio.ODataSapFake.Pedido>("Pedidos");

Update 1 - GET support:

Action supports HTTP Post, which OP has decorated the method with, but if you intend to support HTTP GET, then you must configure the endpoint as a Function instead. The syntax is still the same.

  • don't forget to remove the [HttpPost] attribute, consider replacing it with [EnableQuery] or [HttpGet]

Update 2 - Item Navigation with Composite Key

If the Item data record has a Navigation Property called Pedidos and your intention is to support the standard Item navigation down this property path then you do not need to include this information in the config all.

  • remove the [HttpPost], this is a GET request.
  • remove the [ODataRoute] attribute, the default routes should work
  • Make sure that you use the names of the key properties, using the same casing and order as they are declared with in the configuration.
    • If you are using auto configuration, then the order will match the Key attribute column specification in your data model.
  • For OData v3 you may need to follow this advice: Odata v3 Web Api navigation with composite key
Sign up to request clarification or add additional context in comments.

10 Comments

Thanks bro! URL is correct, so... items.Item.Action(...) was not found. Changed for items.EntityType.Action(...), but the same error occurs.
...and Item has the keys.
I don't know if it's important, but Pedidos is also an Item attribute.
Yeah that can cause some trouble, however Actions are POST endpoints, so make sure you POST to it, if you need to support GET I need to change my answer, let me know :)
Well ... Once again, you're right! My service needs to return results, so ... GET is the most suitable. Is the use of POST necessary for ACTIONS or not? Please, show me answer with GET. I tried something with functions, but in OData V3 it is not available. Right?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.