Ich möchte in der Lage sein, den Filter im Controller zu ändern und dann die Daten basierend auf dem geänderten Filter zurückgeben.
Also ich habe einen ODataQueryOptions-Parameter auf der Serverseite, die ich verwenden kann, um die FilterQueryOption zu betrachten.
Nehmen wir an, der Filter ist ungefähr so "$ filter = ID eq -1", aber auf der Serverseite, wenn ich "-1" für eine ID sehe, sagt dieser, dass der Benutzer alle Datensätze auswählen möchte.
Ich habe versucht, die "$ filter = ID eq-1" in "$ filter = ID ne-1" zu ändern, die mir alle durch die Einstellung der Filter.RawValue geben würde, aber das ist nur lesbar.
Ich habe versucht, eine neue FilterQueryOption zu erstellen, aber dies erfordert einen ODataQueryContext und einen ODataQueryOptionParser, von denen ich nicht weiß, wie ich sie erstellen soll.
Ich habe dann versucht, den Filter = Null und dann uns die ApplyTo, die scheint zu arbeiten, wenn ich einen Unterbrechungspunkt in der Steuerung und überprüfen Sie dies auf der unmittelbaren Fenster, aber sobald es die GET-Methode auf dem Controller dann es verlässt "kehrt" zurück zu dem, was in der URL übergeben wurde.
Dieser Artikel spricht davon, etwas sehr ähnliches "The best way to modify a WebAPI OData QueryOptions.Filter" zu tun, aber sobald es die GET-Methode des Controllers verlässt, wird es wieder auf den URL-Abfragefilter zurückgesetzt.
UPDATE MIT SAMPLE CODE
[EnableQuery]
[HttpGet]
public IQueryable<Product> GetProducts(ODataQueryOptions<Product> queryOptions)
{
if (queryOptions.Filter != null)
{
var url = queryOptions.Request.RequestUri.AbsoluteUri;
string filter = queryOptions.Filter.RawValue;
url = url.Replace("$filter=ID%20eq%201", "$filter=ID%20eq%202");
var req = new HttpRequestMessage(HttpMethod.Get, url);
queryOptions = new ODataQueryOptions<Product>(queryOptions.Context, req);
}
IQueryable query = queryOptions.ApplyTo(db.Products.AsQueryable());
return query as IQueryable<Product>;
}
diesen Code ausführen, werden keine Produkte zurückgeben dies, weil die ursprüngliche Abfrage in der URL-Produkt 1 und tauschte ich die ID-Filter des Produkts 1 mit Produkt 2 wollte.
Jetzt, wenn ich SQL Profiler ausführen, kann ich sehen, dass es etwas wie "Select * aus Produkt WHERE ID = 1 UND ID = 2" hinzugefügt.
ABER Wenn ich das gleiche tue, indem ich die $ Spitze ersetze, dann funktioniert es gut.
[EnableQuery]
[HttpGet]
public IQueryable<Product> GetProducts(ODataQueryOptions<Product> queryOptions)
{
if (queryOptions.Top != null)
{
var url = queryOptions.Request.RequestUri.AbsoluteUri;
string filter = queryOptions.Top.RawValue;
url = url.Replace("$top=2", "$top=1");
var req = new HttpRequestMessage(HttpMethod.Get, url);
queryOptions = new ODataQueryOptions<Product>(queryOptions.Context, req);
}
IQueryable query = queryOptions.ApplyTo(db.Products.AsQueryable());
return query as IQueryable<Product>;
}
END RESULT
Mit Hilfe von Microsoft. Hier ist die endgültige Ausgabe, die Filter, Count und Paging unterstützt.
using System.Net.Http;
using System.Web.OData;
using System.Web.OData.Extensions;
using System.Web.OData.Query;
/// <summary>
/// Used to create custom filters, selects, groupings, ordering, etc...
/// </summary>
public class CustomEnableQueryAttribute : EnableQueryAttribute
{
public override IQueryable ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions)
{
IQueryable result = default(IQueryable);
// get the original request before the alterations
HttpRequestMessage originalRequest = queryOptions.Request;
// get the original URL before the alterations
string url = originalRequest.RequestUri.AbsoluteUri;
// rebuild the URL if it contains a specific filter for "ID = 0" to select all records
if (queryOptions.Filter != null && url.Contains("$filter=ID%20eq%200"))
{
// apply the new filter
url = url.Replace("$filter=ID%20eq%200", "$filter=ID%20ne%200");
// build a new request for the filter
HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Get, url);
// reset the query options with the new request
queryOptions = new ODataQueryOptions(queryOptions.Context, req);
}
// set a top filter if one was not supplied
if (queryOptions.Top == null)
{
// apply the query options with the new top filter
result = queryOptions.ApplyTo(queryable, new ODataQuerySettings { PageSize = 100 });
}
else
{
// apply any pending information that was not previously applied
result = queryOptions.ApplyTo(queryable);
}
// add the NextLink if one exists
if (queryOptions.Request.ODataProperties().NextLink != null)
{
originalRequest.ODataProperties().NextLink = queryOptions.Request.ODataProperties().NextLink;
}
// add the TotalCount if one exists
if (queryOptions.Request.ODataProperties().TotalCount != null)
{
originalRequest.ODataProperties().TotalCount = queryOptions.Request.ODataProperties().TotalCount;
}
// return all results
return result;
}
}
Das funktionierte fast. Es hat tatsächlich den $ filter -Befehl auf dem Server geändert, aber dann hat es auch den $ select -Befehl abgebrochen. Ich kann $ select nicht mehr verwenden, wenn ein Filter angewendet wird. Ich erhalte den Fehler "Die EDM-Instanz vom Typ 'Product Nullable = True' fehlt die Eigenschaft 'X'" Wobei 'X' der Eigenschaftsname ist, den ich auswählen wollte. Wenn ich alle Eigenschaften in $ select einfüge, scheint es gut zu funktionieren. – goroth
Das funktioniert jetzt sogar mit $ select, nachdem Sie "ApplyTo" hinzugefügt haben, bevor die Abfrageoptionen neu initialisiert werden. Vielen Dank. – goroth
Lösung funktioniert bei OData 5.5.1 nicht. Die Änderung der URL hat keine Auswirkungen. –