3

I'm using Microsoft.AspNet.OData v6.0.0 and expect that setting the MaxTop value to 10 will enable the $top query option.

However, requesting the URL http://localhost:23344/odata/v4/Resources?$top=10 still gives me the error:

{"error":{"code":"","message":"The query specified in the URI is not valid. The limit of '0' for Top query has been exceeded. The value from the incoming request is '10'.","innererror":{"message":"The limit of '0' for Top query has been exceeded. The value from the incoming request is '10'.","type":"Microsoft.OData.ODataException","stacktrace":"   at System.Web.OData.Query.Validators.TopQueryValidator.Validate(TopQueryOption topQueryOption, ODataValidationSettings validationSettings)\r\n   at System.Web.OData.Query.TopQueryOption.Validate(ODataValidationSettings validationSettings)\r\n   at System.Web.OData.Query.Validators.ODataQueryValidator.Validate(ODataQueryOptions options, ODataValidationSettings validationSettings)\r\n   at System.Web.OData.Query.ODataQueryOptions.Validate(ODataValidationSettings validationSettings)\r\n   at System.Web.OData.EnableQueryAttribute.ValidateQuery(HttpRequestMessage request, ODataQueryOptions queryOptions)\r\n   at System.Web.OData.EnableQueryAttribute.ExecuteQuery(Object response, HttpRequestMessage request, HttpActionDescriptor actionDescriptor, ODataQueryContext queryContext)\r\n   at System.Web.OData.EnableQueryAttribute.OnActionExecuted(HttpActionExecutedContext actionExecutedContext)"}}}

As though the top query still has a limit of 0.

Controller

public class ResourcesController : ODataController
{
    private IResourceService resourceService;
    public ResourcesController(IResourceService resourceService)
    {
        this.resourceService = resourceService;
    }

    [EnableQuery(MaxTop=10)]
    public IQueryable<Resource> Get()
    {
        return resourceService.GetResources().AsQueryable();
    }
    [EnableQuery]
    public SingleResult<Resource> Get([FromODataUri] int key)
    {
        var result = resourceService.GetResources().Where(r => r.Id == key).AsQueryable();

        return SingleResult.Create(result);
    }
}

WebApiConfig.cs

public static void Register(HttpConfiguration config)
{
    ODataConventionModelBuilder builder = new ODataConventionModelBuilder
    {
        Namespace = "MyNamespace",
        ContainerName = "DefaultContainer"
    };
    builder.EntitySet<Resource>("Resources");
    builder.EntityType<Resource>().Select().Count().Expand().OrderBy();
    config.MapODataServiceRoute(
        routeName: "ODataRoute",
        routePrefix: "odata/v4",
        model: builder.GetEdmModel());
}

What I've found

Github issue describing possible bug with behaviour of MaxTop

What does work

Every other query option I've enabled, including $skip.

What I've Tried

As in this question Setting config.Select().Expand().Filter().OrderBy().MaxTop(null).Count(); in the WebApiConfig.cs before config.mapODataServiceRoute(.... Didn't work.

Adding [Page(MaxTop = 100)] to my Resource model as in the same question. Didn't work.

Setting [Page] attribute on model. From WebApi OData documentation "if you set the Page Attribute, by default it will enable the $top with no-limit maximum value". Didn't work.

Setting [EnableQuery(PageSize=10)] attribute on controller. From WebApi OData documentation "if you set the Page Attribute, by default it will enable the $top with no-limit maximum value". Enabled paging but Didn't work.

The error says the limit was 0 for top in every case

Community
  • 1
  • 1
glcheetham
  • 973
  • 8
  • 23

3 Answers3

8

I had the same issue and discovered that if you specify any rules in builder like you did.

builder.EntitySet<Resource>("Resources");
builder.EntityType<Resource>().Select().Count().Expand().OrderBy();

Value set by attribute will be overriden and set to 0.

If you remove those entries and put global configuration like

config.Select().Expand().Filter().OrderBy().MaxTop(600).Count();

It will work.

Also you can define MaxTop using fluent interface on builder like this.

builder.EntityType<T>().Page(100, 100);

And it'll work even if you define other rules in builder for entity type.

Summarizing

It's probably caused that new configuration is created when you define some config in fluent builder interface and you cannot use attributes (EnableQueryAttribute on controller and Page on model).

It's probably a bug because they still recommend attribute approach. I will report it as issue on OData repository.

Igor
  • 60,821
  • 10
  • 100
  • 175
Pawel
  • 887
  • 1
  • 9
  • 28
  • You're absolutely right: using **global configuration only** enables use of `$top` attribute. For reference, I think I found your issue: https://github.com/OData/WebApi/issues/928 – glcheetham Mar 08 '17 at 11:05
  • I think you're close. I've dug through the source code for the EnableQuery attribute and all I have to say is that it is all a big mess. In some places MaxTop is a nullable int, other places it isn't, so generally if you don't provide a value for MaxTop it automatically gets set to 0. This includes the attribute itself, the global configuration, and the EDM model. If I want to use [EnableAttribute] I have to address all of those places. – JZimmerman Mar 10 '17 at 22:58
  • OK, I take some of that back (but I cannot edit my comment). After a little more testing it appears that the minimum requirement if you want to use [EnableQuery] is to set the page size for the entity type. If you do just that (i.e. no global configuration nor MaxTop property for the attribute itself) things will work. To make matters worse there is no variation in the error message, etc., to give you any indication where the source for the MaxTop value is coming from. Simply maddening. – JZimmerman Mar 10 '17 at 23:06
  • Thanks, and for `config.Select()` to work add `using System.Web.OData.Extensions;` hope helps someone. – Shaiju T Aug 10 '17 at 08:24
  • setting the config globally solved my issue with maxtop. – silverfox1948 Sep 10 '17 at 23:08
  • I've seen some magic 'config' variable appear in three stackoverflow-articles now. Where does this come from? In my Configure(IApplicationBuilder app) I call UseMvc I have no "config" variable that has a method or extension "MaxCount" – realbart Nov 08 '19 at 11:42
0

I had the same error. In my case I tried to hide a specific field from an entity with the Select(..) extension on EntityType<..>().

builder
    .EntityType<User>()
    .Select(System.Web.OData.Query.SelectExpandType.Disabled, "Password");

This happens inside my GetModel()-method. So I just changed the order in which I set the global settings:

config.Count().Filter().OrderBy().Expand().Select().MaxTop(100);

IEdmModel model;
model = GetModel();
w.malgadey
  • 31
  • 5
0

This is for the People coming with the same issue for .NetCore 6.0 . These filters can be added in the Program.cs with the AddController (controller extension) as shown below.

builder.Services.AddControllers(options =>
{
    options.Filters.Add(new EnableQueryAttribute()
    {
        AllowedQueryOptions = AllowedQueryOptions.All,
        AllowedOrderByProperties = null,
        AllowedLogicalOperators = AllowedLogicalOperators.All,
    });
}).AddOData(o => o.Select().Filter().OrderBy().SetMaxTop(100));

Required namespaces are

using Microsoft.AspNetCore.OData;
using Microsoft.AspNetCore.OData.Query;
lokanath das
  • 736
  • 1
  • 10
  • 35