1
votes

Im creating OData controller and want it to support function with 2 params. Here is my current code.

OData cofig:

ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.Namespace = "hop";

builder.EntitySet<ScheduleDTO>("Schedules");
var function = builder.Function("GetByEntityAndJurisdiction");

function.Parameter<Guid>("EntityId");
function.Parameter<Guid>("JurisdictionId");
function.ReturnsCollectionFromEntitySet<ScheduleDTO>("Schedules");

Controller:

            [ODataRoutePrefix("Schedules")]
            public class ScheduleODataController : BaseODataManager, IScheduleODataManager
            {
                [ODataRoute]
                public async Task<IHttpActionResult> GetAsync(ODataQueryOptions<ScheduleDTO> options)
                {
                    .....
                    return Ok(schedules.Select(x => Mapper.Map<ScheduleDTO>(x)));
                }

                [HttpGet]
                [ODataRoute("GetByEntityAndJurisdiction(EntityId={entityId}, JurisdictionId={jurisdictionId})")]
                public async Task<IHttpActionResult> GetByEntityAndJurisdiction(ODataQueryOptions<ScheduleDTO> options, [FromODataUri] Guid entityId, [FromODataUri] Guid jurisdictionId)
                {
                   .....    
                   return Ok(schedules.Select(x => Mapper.Map<ScheduleDTO>(x)));
                }
            }

Starting my app, I have following error:

A first chance exception of type 'System.InvalidOperationException' occurred in System.Web.OData.dll

Additional information: The path template 'Schedules/GetByEntityAndJurisdiction(EntityId={entityId}, JurisdictionId={jurisdictionId})' on the action 'GetByEntityAndJurisdiction' in controller 'ScheduleOData' is not a valid OData path template. The request URI is not valid. Since the segment 'Schedules' refers to a collection, this must be the last segment in the request URI or it must be followed by an function or action that can be bound to it otherwise all intermediate segments must refer to a single resource.

How to resolve this problem? Thanks in advance.

1

1 Answers

1
votes

@Vladimir

In your controller, you add a prefix attribute [ODataRoutePrefix("Schedules")] on the controller. Doing so will add the prefix string at head of all the [ODataRoute] in the same controller. So, for below action

public async Task<IHttpActionResult> GetByEntityAndJurisdiction(ODataQueryOptions<ScheduleDTO> options, [FromODataUri] Guid entityId, [FromODataUri] Guid jurisdictionId)
{...}

the full Uri template should be:

Schedules/GetByEntityAndJurisdiction(EntityId={entityId}, JurisdictionId={jurisdictionId})

Obviously, This Uri is invalid because:

  1. The collection of Schedules doesn't have a bound function named GetByEntityAndJurisdiction
  2. Even though GetByEntityAndJurisdiction is a bound function, you should call the bound function through it's namespace-qualified function name.

Maybe, It's confused that you have build the function as the following codes:

var function = builder.Function("GetByEntityAndJurisdiction");

However, it means to build an unbound function. An unbound function is called through function import by issuing a GET request to a URL identifying the function import and passing parameter values using inline parameter syntax. The canonical URL for a function import is the service root, followed by the name of the function import.

So, you can change your codes as follows to make it work:

  1. If you want to keep the model schema unchanged, that is to build GetByEntityAndJurisdiction as unbound function, please remove the ODataRoutePrefix("Schedules")] from your controller. Or create a new controller (any controller), move the action into the new controller but don't add the Prefix attribute.

  2. If you want to change the schema and keep the controller unchanged, that is to GetByEntityAndJurisdiction as bound function.

Please do as follows :

var entity = builder.EntitySet<ScheduleDTO>("Schedules").EntityType;
var function = entity.Collection.Function("GetByEntityAndJurisdiction");

...

For more information about function, you can refer to OData.Org or Function Sample page, or Function blog.