Custom GET Action in ASP.NET WebAPI 2 OData Controller

I am using WebApi2 and OData. I want to add a custom action and use it with the GET method

GET /odata/Providers(2)/DoSth

      

but I don't understand how it works. Here is the code for one of my controllers:

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 metadata / odata / $

but cannot run this method from url (showing 404: "HTTP resource not found that matches request URI").

Any ideas to improve this issue?

+3


source to share


2 answers


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

If that doesn't work, add the method attribute to the controller:



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

      

If you are just starting to play with OData, I recommend that you start with OData V4, which is the OASIS standard. Below is an example of actions: https://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/OData/v4/ODataActionsSample/ .

+5


source


I solved the problem differently ... I am not a deep dive programmer just an intermediate ... I still solve problems in any way when they arise ...

I needed a search function that could not be handled by the standard $ filter functions and I needed to return an IQueryable like any OData 4 controller (no get function).

First in my suitable controller ... I took the same signature of my "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 WebAPi Config, this is a signature;

1) the first line contains 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 name the parameter and what type it is ... 5) the fifth line is VERY important if you want to avoid having to call ": //.../namespace.function (param = 'value')". This removes the namespace limitation. see this

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

config.EnableUnqualifiedNameCall(unqualifiedNameCall: true);

      

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

0


source







All Articles