$count with Singleton returning List
Hi, I don't know if it is a bug, or missunderstanding. I think there is little documentation on singletons and their uses.
I want to have an endpoint to get a List of conflicts (strings), so I think the best approach is to model it as Singleton.
So I've modeled it as follows:
edmBuilder.Singleton<List<string>>("Conflicts");
And I have a Controller:
public class ConflictsController: ODataController
{
[EnableQuery]
public IActionResult Get()
{
return Ok(new List<string>() { "id1", "id2", "id3" }.AsQueryable()); // This is only for testing.
}
When I access to my URL:
http://url/Conflicts
This returns a list of conflicts (strings) and this is working fine.
But now, in the Microsoft.AspNetCore.OData 7.5.5 (or above versions) if I want to do a ?$count=true to paginate those conflicts, I get the following error:
"Object of type 'System.Linq.EnumerableQuery`1[System.String]' cannot be converted to type 'System.Linq.IQueryable`1[System.Linq.IEnumerable`1[System.String]]'.",
Is this normal or is it a bug? How should it be fixed?
In the Microsoft.AspNetCore.OData 7.5.0 or 7.5.2 this worked fine... but i didn't find any related to this change on release notes.
Thanks
@alvorteg That's interesting. In the Microsoft.AspNetCore.OData 7.5.0 or 7.5.2 this worked fine. do you have your repo?
If you use 8.0, you can do like:
- Create a POCO class, for example:
public class Conflict
{
public IList<string> Values {get;set;}
}
- use this class to define a singleton:
edmBuilder.Singleton<Conflict>("Conflict");
- create the singleton controller.
public class ConflictController: ODataController
{
[EnableQuery]
public IActionResult GetValues()
{
return Ok(new List<string>() { "id1", "id2", "id3" }.AsQueryable()); // This is only for testing.
}
}
- a request that you can use looks like: "~/Conflict/values"
@xuzhg thanks for your quick response!
I had already tried what you said on the 7.5.6 version. The call works correctly and the list of strings is retrieved, but the $count=true still does not work.
I'm sorry I can't share my repo, but I can show you the obtained results with 7.5.2 and 7.5.6 versions.
With 7.5.6

If I add $count=true to the URL:

Exactly same code with 7.5.2

If I add $count=true to the URL:

Do you need some more information that can help you find the solution?
Thanks in advance!
@alvorteg can you share your CSDL metadata? model builder? your controller?
Startup:
public class Startup {
public IConfiguration Configuration {
get;
}
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
//Persistence Injection
services.AddPersistenceDependencyServices(this.Configuration.GetConnectionString("QueryDB"));
services.AddDependencyInjections();
services.AddOData();
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints => {
endpoints.MapODataRoute("TestAPIv1", "TestAPI/v1", GenerateEdmModel());
endpoints.Select().Expand().OrderBy().Filter().Count().MaxTop(null);
endpoints.EnableDependencyInjection();
endpoints.SetTimeZoneInfo(TimeZoneInfo.Utc);
});
}
private IEdmModel GenerateEdmModel() {
var edmBuilder = new ODataConventionModelBuilder();
edmBuilder.Singleton<IList<string>> ("Conflicts");
return edmBuilder.GetEdmModel();
}
}
ConflictsController
public class ConflictsController : ODataController
{
private readonly IConflictsService conflictsService;
public ConflictsController (IConflictsService conflictsService)
{
this.conflictsService= conflictsService;
}
[ODataRoute]
[EnableQuery]
public IQueryable<string> Get() => this.conflictsService.GetConflicts();
}
As I mentioned in the previous message, with this code, version 7.5.2 works, and 7.5.6 doesn't work.
Thanks again @xuzhg and tell me if you need something else.
@habbes Would you please help take a look? Is there any recently commit related?
@alvorteg Basically, you should not define a singleton using 'dmBuilder.Singleton<IList
@xuzhg Not really, I could create a "Conflicts" class with a property that is a list of strings (as you suggested in previous answers), but I wouldn't really need that intermediate class.
Anyway, I've tried that too and the $count=true still fails in 7.5.6.
Thanks!
@habbes @xuzhg Is there any news?
@alvorteg Just curious if you were able to resolve this issue? I'm having the same issue when using $orderby. My controller is named ComparablesController and it's returning IQueryable<ComparableViewModel> or IQueryable<Comparable> depending on Get method called, where these are custom object types. The IQueryable<Comparable> works fine, but the IQueryable<ComparableViewModel> throws the same conversion error you were seeing. Using Microsoft.AspNetCore.OData 8.0.10 nuget. Thanks.