Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom GET action in ASP.NET WebAPI 2 OData Controller

I'm using WebApi2 and OData. I want add custom action, and use it by GET method

GET /odata/Providers(2)/DoSth

but I dont understand how it works exactly. Here is code for one of my controller:

public class ProvidersController : ODataController
{
    private Entities db = new Entities();

    // GET: odata/Providers
    [Queryable]
    public IQueryable<PROVIDER> GetProviders()
    {
        return db.PROVIDER;
    }
    //... OTHER GENERATED METHODS

    //MY TEST METHOD SHOULD BE inoked: GET /odata/Providers(2)/DoSth
    public int DoSth()
    {
        return 22;
    }
 }

and WebApiConfigFile:

  ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
  builder.EntitySet<PROVIDER>("Providers").EntityType.HasKey(o => o.P_ID);
  //others entities ...

  //my custom action without any parameters, returns int:
  ActionConfiguration getTest = builder.Entity<PROVIDER>().Action("DoSth");
  getTest.Returns<int>();

Method existing in /odata/$metadata

but cant run this method from the url (still showing 404: "No HTTP resource was found that matches the request URI").

Any ideas how to improve this issue?

like image 825
user2987281 Avatar asked Oct 26 '25 11:10

user2987281


2 Answers

In OData an action can only be invoked by the POST method. So just change the request from GET to POST.

If it doesn't work, add an attribute to the method in the controller:

[HttpPost]
public int DoSth()
{
    return 22;
}

If you just start to play with OData, I recommend you start from OData V4, which is an OASIS standard. Here is a sample about actions: https://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/OData/v4/ODataActionsSample/ .

like image 181
Tan Jinfu Avatar answered Oct 29 '25 01:10

Tan Jinfu


I solved the problem in a different way... I am not a deep dive programmer only an intermediate... I do however solve problems in any way possible as they arise...

I required a search capability that could not be handled by standard $filter functionality and I needed to return an IQueryable just like any OData 4 controller would (less a get function).

First in my appropriate controller... I took the exact same signature of my Get"Entity" call and added a parameter.

    [EnableQuery]
    public IQueryable<detail> Getdetails([FromODataUri] int key)
    {
        return db.masters.Where(m => m.masterid == key).SelectMany(m => m.details);
    }

    // custom function goes here...
    [EnableQuery]
    public IQueryable<detail> GetSearchDetails([FromODataUri] int key, [FromODataUri] IEnumerable<int> search)
    {
       1) do your own function logic here... mine happens to be a very complex search...
       2) make sure to return iQueryable as result... I use standard linq queries and then the final return is toList() as IQueryable
       3) I also did a simple return search.Count = 0 ? return all results : return queried results.
    }

In the WebAPi Config this is the signature;

1) the first line says place the code in the MasterController. 2) the second line tells me what to call the function. 3) the third line tells me what to return. 4) the fourth line tells me what to call the parameter and what type it is... 5) the fifth line is VERY important if you want to avoid having to have to call "://.../namespace.function(param='value')". This removes the dotted namespace constraint. see:this

builder.EntityType<master>()
            .Function("GetSearchDetails")
            .ReturnsCollectionFromEntitySet<detail>("details")
            .CollectionParameter<int>("search");

config.EnableUnqualifiedNameCall(unqualifiedNameCall: true);

This approach solved many of my problems on the client side... Now, i can call h!!p://domain/odata/master(n)/GetSearchDetails(search=[2,10,31]) or if it were an array of string h!!p://domain/odata/master(n)/GetSearchDetails(search=['two','ten','thirtyone']) and it returns an IQueryable just like calling the underlying entity... However, the added benifit is that ALL the standard OData v4 functionality is still there $filter, $select... etc...

like image 45
stewbash Avatar answered Oct 29 '25 02:10

stewbash



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!