Reputation: 7949
I have a Web API project which has been used for several years without OData support, just with standard URL params.
I now wish to add OData support to this API, but as the API is not built on a queryable model the intention is to receive the ODataQueryOptions<T>
object and pass this down to a repository.
Everything I can find to read about supporting OData either assumes that I have a queryable model or is overly simplistic and simply tells me how to make sense of the ODataQueryOptions
object. Consequently I'm unable to get a simple method up and running.
Here's what I currently have.
[Route("test")]
[HttpGet]
[EnableQuery]
public IHttpActionResult Test(ODataQueryOptions<TestOptions> options)
{
var settings = new ODataValidationSettings {
AllowedFunctions = AllowedFunctions.None,
AllowedLogicalOperators = AllowedLogicalOperators.Equal,
AllowedArithmeticOperators = AllowedArithmeticOperators.None,
AllowedQueryOptions = AllowedQueryOptions.Filter
};
try
{
options.Validate(settings);
}
catch (ODataException exception)
{
return BadRequest(exception.Message);
}
var binaryOperator = options.Filter?.FilterClause?.Expression as BinaryOperatorNode;
if (binaryOperator != null)
{
var property = binaryOperator.Left as SingleValuePropertyAccessNode ?? binaryOperator.Right as SingleValuePropertyAccessNode;
var constant = binaryOperator.Left as ConstantNode ?? binaryOperator.Right as ConstantNode;
if (property?.Property != null && constant?.Value != null)
{
;
}
}
return Ok();
}
The TestOptions
class (in the ODataQueryOptions<TestOptions>
param) is currently an empty class:
public class TestOptions
{
}
I've also added
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// existing code
config.AddODataQueryFilter();
}
}
However, upon calling this from a REST API client...
{
"Message": "An error has occurred.",
"ExceptionMessage": "No non-OData HTTP route registered.",
"ExceptionType": "System.InvalidOperationException",
"StackTrace": " ... "
}
What have I missed? I would have thought that I might have to register OData-enabled methods in the global.asax or similar, but the exception implies that the problem is with non-OData methods, but all the other methods still return as expected (i.e., without any OData involvement).
Upvotes: 11
Views: 11466
Reputation: 12693
Actually, this works perfectly without EntityDate or any other model setup. You just need a List<Poco.Language>
that you can convert with .AsQueryable()
and off you go.
[Route(""), HttpGet]
public IHttpActionResult Get(ODataQueryOptions<Poco.Language> queryOptions)
{
return Ok(queryOptions.ApplyTo(_repository.GetAll().AsQueryable()));
}
Above controller can be called with all types of OData query options, normal routes and no setup in the WebApiConfig.
Poco.Language
is just a plain C# POCO class.
Upvotes: 9
Reputation: 866
Did you add this to your Startup?
public void Configuration(IAppBuilder appBuilder)
{
// Set up server configuration
var config = new HttpConfiguration();
config.Routes.MapODataRoute(routeName: "OData", routePrefix: "odata", model: GetEdmModel());
appBuilder.UseWebApi(config);
}
private IEdmModel GetEdmModel()
{
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Customer>("customer");
modelBuilder.EntitySet<Order>("order");
modelBuilder.EntitySet<Customer>("response");
return modelBuilder.GetEdmModel();
}
I am trying to do the same thing you are, but with a .Net Core Web Api. I downloaded the samples from https://github.com/OData/ODataSamples and he has a working project that does exactly what we're trying to do. Look at ODataQueryableSample.csproj. It doesn't use EntityFramework either, just creates a list in memory.
Also, I don't think you need both the [EnableQuery] attribute and ODataQueryOptions parameter - the sample gives an example for both and doesn't use them together.
I haven't gotten this working with my project either, but I have seen it working on my PC so I believe its just a configuration thing (for instance, my Startup uses IApplicationBuilder instead of IAppBuilder). You might also try to hit it from a browser to get a better exception message.
Upvotes: 0