13

I am getting the following error:

The path template 'GetClients()' on the action 'GetClients' in controller 'Clients' is not a valid OData path template. Resource not found for the segment 'GetClients'.

My controller method looks like this

public class ClientsController : ODataController
{
    [HttpGet]
    [ODataRoute("GetClients(Id={Id})")]
    public IHttpActionResult GetClients([FromODataUri] int Id)
    {
        return Ok(_clientsRepository.GetClients(Id));
    }
}

My WebAPIConfig file has

builder.EntityType<ClientModel>().Collection
       .Function("GetClients")
       .Returns<IQueryable<ClientModel>>()
       .Parameter<int>("Id");

config.MapODataServiceRoute(
    routeName: "ODataRoute",
    routePrefix: "odata",
    model: builder.GetEdmModel());

I am hoping to be able to call the odata rest api like this:

http://localhost/odata/GetClients(Id=5)

Any idea what I am doing wrong?

abatishchev
  • 92,232
  • 78
  • 284
  • 421
Nate
  • 1,974
  • 4
  • 22
  • 44
  • Similar error here - https://stackoverflow.com/questions/27824774/odata-v4-error-on-start-up-resource-not-found-for-the-segment-whatever – sashoalm Feb 16 '17 at 10:06

2 Answers2

12

You don't even need to add such a function to get an entity.

builder.EntitySet<ClientModel>("Clients")

is all you need.

And then write your action as:

public IHttpActionResult GetClientModel([FromODataUri] int key)
{    
      return Ok(_clientsRepository.GetClients(key).Single());
}

Or

This is what worked. The above did not work:

public IHttpActionResult Get([FromODataUri] int key)
{    
    return Ok(_clientsRepository.GetClients(key).Single());
}

Then the Get request

http://localhost/odata/Clients(Id=5)

or

http://localhost/odata/Clients(5)

will work.

Update: Use unbound function to return many ClientModels.

The follow code is for v4. For v3, you can use action.

builder.EntitySet<ClientModel>("Clients");
var function = builder.Function("FunctionName");
function.Parameter<int>("Id");
function.ReturnsCollectionFromEntitySet<ClientModel>("Clients");

Add a method in the controller like:

[HttpGet]
[ODataRoute("FunctionName(Id={id})")]
public IHttpActionResult WhateverName(int id)
{
    return Ok(_clientsRepository.GetClients(id));
}

Send a request like:

GET ~/FunctionName(Id=5)
abatishchev
  • 92,232
  • 78
  • 284
  • 421
Feng Zhao
  • 2,887
  • 1
  • 12
  • 19
  • 1
    I get No HTTP resource was found that matches the request URI 'http://localhost/odata/Clients(Id=5)'. – Nate Jul 09 '14 at 23:26
  • I am using Odata v3 because I am using jaydata which uses Odata and they do not seem to work with v4. How does routing work with v3? – Nate Jul 09 '14 at 23:27
  • I changed it to use v4 and I followed your instruction but now I get no data return. localhost/odata/$metatdata works but http://localhost/odata/Clients(5 returns nothing – Nate Jul 10 '14 at 00:14
  • 1
    Did the change. still get No HTTP resource was found that matches the request URI 'http://localhost/odata/Clients(5) – Nate Jul 10 '14 at 04:48
  • The difference of two methods is only with the name. The "GetClientModel(int key)" will be matched firstly, and then the "Get(int key)" will be matched. As you said, the latter one works but the previous one doesn't, is the reason that the name of the entity type is not equal to "ClientModel"? Two methods both work on my machine. – Feng Zhao Jul 10 '14 at 06:07
  • Great stuff. Thanks bro – Hugo Nava Kopp Mar 15 '17 at 17:20
-1

This route is incorrect: [ODataRoute("GetClients(Id={Id})")]

It should be: [ODataRoute("Clients({Id})")]

URL should be: http://localhost/odata/Clients(Id=5)

abatishchev
  • 92,232
  • 78
  • 284
  • 421
Nate
  • 1,974
  • 4
  • 22
  • 44
  • With [ODataRoute("Clients({Id})")], the function you defined in the model is never used. If you really want function "GetClients" to return many ClientModels, I can provider with code to do that. – Feng Zhao Jul 09 '14 at 08:26
  • Yes, can you show me how to get this to return many client models? Thanks – Nate Jul 10 '14 at 00:33