How to create an instance of ODataQueryOptions

I have a working (simplified) ODataController with the following method.

 public class MyTypeController : ODataController { [HttpGet] [EnableQuery] [ODataRoute("myTypes")] public IQueryable<MyType> GetMyTypes(ODataQueryOptions<MyType> options) { return _repo.myResultsAsQueryable(); } } 

I would like to be able to call this method from the server, and for this I need to create an instance of ODataQueryOptions , which requires an ODataQueryContext .

There are examples of how to do this (for example, here and here ), but they all seem to refer to a previous version of OData. The ODataQueryContext constructor currently requires a third argument ( ODataPath path), which is not addressed in any of the examples I can find.

Edit: @snow_FFFFFF, Here is some other context ... I understand that I can just use the OData endpoint via HttpClient, but I would like to interact directly with IQueryable, as you say.

The problem is that the application I'm working on allows users to create filters (for example, complex search engines) that can be saved and later called by other users. From the JS client, they simply search for the filter by id and issue a request to the OData endpoint with the filter applied to the query string. This works very well on the client side, but I would like to be able to do something similar on the server side.

This is what I would like to do, but how can I instantiate an ODataPath argument?

 public IQueryable<MyType> FilterMyTypes(int filterID) { // lookup filter by filterID from db... filter = "$filter=Status eq 1"; // for example... ODataPath path = // but how can I get the path!!! new ODataQueryContext(edmModel, typeof(MyType), path); var uri = new HttpRequestMessage(HttpMethod.Get, "http://localhost:56339/mytypes?" + filter); var opts = new ODataQueryOptions<MyType>(ctx, uri); var results = new MyTypeController().GetMyTypes(opts); } 

Another application of this would be support for dynamic grouping, as shown below:

 [HttpGet] [Route("myTypes/{filterID:int}/groupby/{groupByFieldName}")] public IHttpActionResult GroupMyTypes(int filterID, string groupByFieldName) { // For example: get all Active MyTypes and group by AssignedToUserID... // Get the results of the filter as IQueryable... var results = FilterMyTypes(filterID); // group on groupByFieldName var grouped = results.GroupBy(x => GetPropertyValue(x,groupByFieldName)); // select the groupByFieldName and the count var transformedResults = grouped.Select(g => new { g.Key, Count = g.Count() }); return Ok(transformedResults); } 
+5
source share
2 answers

Sure. ODataPath is a list of ODataPathSegment (s) that OData Uri spec should track.

In the OData Web API, it is easy to instantiate an ODataPath, for example:

 IEdmModel model = GetEdmModel(); IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet(setName); ODataPath path = new ODataPath(new EntitySetPathSegment(entitySet)); 

The above path follows the OData specification that it has an odata pattern like:

 ~/entityset 

More test examples (codes) can be found here.

+3
source

Your odata controller provides an HTTP interface to your data, should you not access it via HTTP (even if from a server)? There is a VS add-in for creating odata client code:

https://visualstudiogallery.msdn.microsoft.com/9b786c0e-79d1-4a50-89a5-125e57475937

Or, if you are doing this from the same project, why not a regular method that returns an IQueryable that can be called from your code or from a controller?

UPDATE . Based on additional information in the original question:

If you have ODataQueryOptions defined in the controller method, this will allow you to parse the well-formed odata query that calls this method. I used this when I needed to translate parts of an odata query because I needed to query multiple data sources in order to return the final result.

It sounds like you want something that accepts parameters and parameters other than odata. To do this, you probably need to look at user actions and / or functions (if you just return data, perhaps a function):

http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/odata-actions-and-functions

UPDATE # 2 : And after a more detailed reading, I think I skipped your question - I have no answer, but I will play with it. Can't you just reform the URL itself (as opposed to instantiating request parameters?

UPDATE # 3 . I think it will be difficult for you to cope with this, thinking that he is receiving a request from ... this is not really a request from. Let's go back to the second option mentioned in my original answer - why is it not a normal method that you can use, and the odata controller can use - something like this:

 // some sort of helper class public class HelperObject { public static IQueryable<MyType> GetGroupedValues(int filterID, string groupByFieldName) { // all your code/logic here } } // your odata controller uses the helper [HttpGet] [Route("myTypes/{filterID:int}/groupby/{groupByFieldName}")] public IHttpActionResult GroupMyTypes(int filterID, string groupByFieldName) { return Ok(HelperObject.GetGroupedValues(filterID, groupByFieldName)); } // ... and so does your other code that wants to do the same thing var x = HelperObject.GetGroupedValues(filterID, groupByFieldName); 
0
source

Source: https://habr.com/ru/post/1235385/


All Articles