Die ideale Lösung wäre, dies auf der Client-Seite mit den integrierten Filterfunktionen tolower
und toupper
zu handhaben. Dies würde dem Client erlauben, die Wahl zu treffen, ob mit oder ohne Berücksichtigung der Groß-/Kleinschreibung gefiltert werden soll.
Auf der Serverseite ist es derzeit die beste Vorgehensweise, den Anforderungs-URI zu ändern und ein neues Anforderungsobjekt für den geänderten URI zu generieren. Siehe OData V4 modify $filter on server side. Es gibt ein offenes Problem im Web-API-OData für eine elegantere query option interception/modification mechanism.
String-Operation direkt auf Anfrage durchführen URI wird immer fehleranfällig sein. Wir können die linked answer verbessern, indem wir das Rich Object Model für Filterausdrücke in der OData Library (ODL) nutzen. Beachten Sie, dass der Filterausdruck ODataQueryOptions.Filter.FilterClause.Expression
ein abstrakter Syntaxbaum ist, der den Wert $filter
darstellt.
Der Code, der benötigt Namensräumen von ODL folgt:
using Microsoft.OData.Core;
using Microsoft.OData.Core.UriBuilder;
using Microsoft.OData.Core.UriParser;
using Microsoft.OData.Core.UriParser.Semantic;
using Microsoft.OData.Core.UriParser.TreeNodeKinds;
using Microsoft.OData.Edm;
zunächst eine Hilfsklasse definieren die verschiedenen Knoten zum Neuschreiben, die einen Filter AST bilden. Die folgende Klasse handhabt derzeit nur BinaryOperatorNode
(z. B. eq
Ausdrücke).
public static class FilterExpressionHelper
{
public static SingleValueNode RewriteAsCaseInsensitive(BinaryOperatorNode node)
{
// Handle {Edm.String eq Edm.String}
if (node.OperatorKind == BinaryOperatorKind.Equal && node.Left.TypeReference.IsString() && node.Right.TypeReference.IsString())
{
// Wrap both operands with toupper().
node = new BinaryOperatorNode(BinaryOperatorKind.Equal,
new SingleValueFunctionCallNode("toupper", new List<QueryNode> { node.Left }, node.Left.TypeReference),
new SingleValueFunctionCallNode("toupper", new List<QueryNode> { node.Right }, node.Right.TypeReference));
}
return node;
}
// Add methods to handle other node types; e.g., SingleValueFunctionCallNode.
}
Als nächstes definieren einen Helfer den rewriter aufzurufen und die Abfragezeichenfolge des Anforderungs-URI zu regenerieren (wie durch ODataQueryOptions
modelliert).
public class ODataUriHelper
{
public static string RewriteQuery(ODataQueryOptions queryOptions)
{
var odataUri = BuildODataUri(queryOptions);
var uriBuilder = new ODataUriBuilder(ODataUrlConventions.Default, odataUri);
var uri = uriBuilder.BuildUri();
// Do not return the leading '?'.
return uri.Query.Substring(1);
}
private static readonly Uri DummyServiceRoot = new Uri("http://localhost");
private static readonly ODataPath DummyPath = new ODataPath(Enumerable.Empty<ODataPathSegment>());
private static ODataUri BuildODataUri(ODataQueryOptions queryOptions)
{
var uri = new ODataUri();
uri.ServiceRoot = DummyServiceRoot;
uri.Path = DummyPath;
uri.Filter = RewriteFilter(queryOptions.Filter?.FilterClause);
uri.OrderBy = queryOptions.OrderBy?.OrderByClause;
uri.SelectAndExpand = queryOptions.SelectExpand?.SelectExpandClause;
uri.Skip = queryOptions.Skip?.Value;
uri.Top = queryOptions.Top?.Value;
return uri;
}
private static FilterClause RewriteFilter(FilterClause filterClause)
{
if (filterClause != null)
{
var filterExpr = filterClause.Expression;
var binaryExpr = filterExpr as BinaryOperatorNode;
if (binaryExpr != null)
{
filterExpr = FilterExpressionHelper.RewriteAsCaseInsensitive(binaryExpr);
filterClause = new FilterClause(filterExpr, filterClause.RangeVariable);
}
// Add support for other node types here.
}
return filterClause;
}
}
Schließlich binden sie alle zusammen mit einer benutzerdefinierten Version des EnableQuery
Attribut, das Umschreiben bedingt ausführt.
public class CustomEnableQueryAttribute : EnableQueryAttribute
{
public override IQueryable ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions)
{
if (queryOptions.Filter != null)
{
var query = ODataUriHelper.RewriteQuery(queryOptions);
var uri = new UriBuilder(queryOptions.Request.RequestUri) { Query = query };
var request = new HttpRequestMessage(HttpMethod.Get, uri.Uri);
queryOptions = new ODataQueryOptions(queryOptions.Context, request);
}
return base.ApplyQuery(queryable, queryOptions);
}
}
Haben Sie das eingebaute in versucht [ 'tolower'] (http://docs.oasis-open.org/odata/odata/v4.0/errata02/ os/complete/part2-url-konventionen/odata-v4.0-errata02-os-part2-url-conventions-complete.html # _Toc406398123) Funktion? Z. B. '/ Lieferanten? $ Filter = tolower (Adresse/Stadt) eq 'Stadt'. – lencharest
Ich habe keine Kontrolle darüber, welche Abfragen gesendet werden, sie werden von Benutzern erstellt. Ich bin in der Lage, Ausdruck intern zu ändern, obwohl – user21479
user21479 Ich habe an dem gleichen Problem gearbeitet, und ich habe eine Idee, wie es zu lösen, aber was ich nicht weiß ist, wie man den neuen Ausdruck (Ergebnis des ExpressionVisitor) in die Abfrage-Pipeline. –