Reputation: 111
I've got Asp.Net Core application and there is an abstract controller.
I want to create a method, which will allow me to render list of entities as PartialView.
I've made it like this:
Should return PartialView with list of entities
[HttpGet]
[EnableQuery()]
public async Task<IActionResult> _List()
{
var result = _context.GetQueryByType<T>(); //returns DbSet<T> of whole table
return PartialView(await result.ToListAsync());
}
Example PartialView
@model IEnumerable<SomeClass>
<table class="table table-sm table-striped table-hover">
...
</table>
I want to call my method like this:
http://localhost:32769/SomeController/_List?$filter=id%20eq%2009515a38-2a1a-4a53-a4f8-e91e4dbd870b
And get filtered List view.
But anyway I get only whole table data.
The only solution for me is split this logic into 2 methods:
http://localhost:32769/odata/SomeClass?$filter=ReleaseId%20eq%2011f28258-48cb-4c82-85e0-822850fd1f5c
[HttpPost]
public IActionResult _List([FromBody] IEnumerable<T> entities)
{
return PartialView(entities);
}
I don't like this solution. Is there any possibility to filter my view data using OData queries?
Upvotes: 1
Views: 464
Reputation: 111
Thx to ChristophLütjen.
.ApplyTo() is the solution.
Finally, working method looks like:
[HttpGet]
[EnableQuery]
public async Task<IActionResult> _List(ODataQueryOptions<T> queryOptions)
{
var result= (IQueryable<T>)queryOptions.ApplyTo(_context.GetQueryByType<T>());
return PartialView(await result.ToListAsync());
}
Also, it's very important to use ODataQueryOptions<T>
, not ODataQueryOptions
.
If you will use not common class, you will get an error, that method should return IEnumerable<T>
, but not IActionResult
.
Here is some documentation. Just want to pin it to the answer.
Hope, that this info will be usefull for someone else.
upd:
Also I've found out, that it's not perfect soulution, if you want to use $expand
method in your OData queries.
If you'll try to get type T
of expanded query, you'll face the problem of SelectAllAndExpand type.
In this case this is the solution, I think it's not very beatiful and perfect, but it works:
[HttpGet]
[EnableQuery]
public IActionResult _List(ODataQueryOptions<T> queryOptions)
{
var validationSettings = new ODataValidationSettings
{
AllowedQueryOptions = AllowedQueryOptions.All,
AllowedFunctions = AllowedFunctions.All,
};
queryOptions.Validate(validationSettings);
IQueryable resultSet = queryOptions.ApplyTo(_context.GetQueryByType<T>(), new ODataQuerySettings());
List<T> resultList = new List<T>();
foreach (var item in resultSet)
{
if (item is T)
{
resultList.Add((T)item);
}
else if (item.GetType().Name == "SelectAllAndExpand`1")
{
var entityProperty = item.GetType().GetProperty("Instance");
resultList.Add((T)entityProperty.GetValue(item));
}
}
return PartialView(resultList as IEnumerable<T>);
}
Found it here: https://github.com/OData/WebApi/issues/1441
Upvotes: 1