Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET WebAPI OData - Inheriting from EntitySetController<> but using Get(ODataQueryOptions options) rather than [Queryable]Get()

I'm using the ASP.Net WebAPI nightly build (2013-01-16) to get the latest OData support possible.

As the Meta-Me blog on MSDN OData 0.2.0-alpha release post says, there's now an EntitySetController<T> from which OData controllers can be derived to take away a lot of the pain and plumbing code.

The EntitySetController<T> class implements Get() as

[Queryable]
public virtual IQueryable<TEntity> Get()
{
    throw EntitySetControllerHelpers.GetNotImplementedResponse(Request);
}

I'd like to make use of the more specific Get(ODataQueryOptions options) method offered by the ASP.Net Web API OData support.

I've coded it as

public IEnumerable<Patient> Get(ODataQueryOptions options)
{
    IQueryable patients = entities.Patients;

    if (options.Filter != null)
    {
        patients = options.Filter.ApplyTo(patients, new ODataQuerySettings());
    }

    return (patients as IQueryable<Patient>).AsEnumerable();
}

(I've also had this return IQueryable<> and saw someone else talk about an ODataResult - that's a type I can't discover at the moment).

However, if I try to use the ODataQueryOptions-based Get method in my own controller I get an error message about multiple actions matching the request. Specifically that error is

Multiple actions were found that match the request: 

System.Collections.Generic.IEnumerable`1[Dox.Server.Model.Patient] Get(System.Web.Http.OData.Query.ODataQueryOptions) on type Dox.Server.Web.Controllers.PatientController

System.Linq.IQueryable`1[Dox.Server.Model.Patient] Get() on type System.Web.Http.OData.EntitySetController`2[[Dox.Server.Model.Patient, Dox.Server.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

I assume this is due to the route resolver (sorry if that's poor ASP.NET routing terminology) seeing Get() or Get(...) on the controller's base class as well as the controller class itself.

Questions: a) Is there some way of adjusting routes to fix this? b) If not, should I make my own version of EntitySetController<T> and swap out it's Get() method?

The configuration being called by Application_Start() is limited to

public static void EnableOData( HttpConfiguration config )
{
    var model = BuildModelImplicitly(config);

    //As per LinqPad forum: http://forum.linqpad.net/discussion/178/odata-v3-not-working
    IEdmEntityContainer container = model.EntityContainers().First();
    model.SetIsDefaultEntityContainer(container, true);

    //config.EnableOData(model, "api");
    config.Routes.MapODataRoute("OData", "api", model);

    //config.EnableSystemDiagnosticsTracing();

}

There's no other configuration being called to do with routes or handlers, etc. Note that the EnableOData() method on HttpConfiguration no longer exists in the latest nightly builds as per this CodePlex discussion.

Thanks very much!

like image 549
Ian Yates Avatar asked Jan 18 '13 05:01

Ian Yates


1 Answers

It's very cool to see that you're using our nightly builds :)

The reason you're getting a multiple matching actions error is because EntitySetController already defines a Get method. The good news is that EntitySetController also defines a QueryOptions property that you can use to retrieve the query options. So you should be able to override the EntitySetController's Get method and use the query options property instead of the parameter. It should behave exactly the same way as if you had bound the query options to an action parameter.

like image 193
Youssef Moussaoui Avatar answered Sep 20 '22 22:09

Youssef Moussaoui