Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
ODataQueryOptionExtensions - Modifying ODataQueryOptions on the fly - https://d-fens.ch/2017/02/26/modifying-odataqueryoptions-on-the-fly/ Support oData V4
/**
* Copyright 2017 d-fens GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using PBSWebServerAPI.Util;
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Web.OData.Query;
namespace PBSWebServerAPI.Extensions
{
public static partial class ODataQueryOptionsExtensions
{
public static readonly ODataQuerySettings _OdataQuerySettings = new ODataQuerySettings();
public static ODataQueryOptions<TEntity> Transform<TEntity>(this ODataQueryOptions<TEntity> queryOptions, ODataQueryOptionsUtilitiesTransformSettings transform)
{
return ODataQueryOptionsUtilities.Transform
(
queryOptions,
transform
);
}
public static ODataQueryOptions Transform<TEntity>
(
this ODataQueryOptions<TEntity> queryOptions,
Func<IReadOnlyDictionary<string, string>, FilterQueryOption, string> transformFilter,
Func<IReadOnlyDictionary<string, string>, OrderByQueryOption, IList<string>> transformOrderBy,
Func<IReadOnlyDictionary<string, string>, SelectExpandQueryOption, IList<string>> transformExpand,
Func<IReadOnlyDictionary<string, string>, SelectExpandQueryOption, IList<string>> transformSelect,
Func<IReadOnlyDictionary<string, string>, SkipQueryOption, int?> transformSkip,
Func<IReadOnlyDictionary<string, string>, TopQueryOption, int?> transformTop
)
{
Contract.Requires(null != queryOptions);
return ODataQueryOptionsUtilities.Transform
(
queryOptions: queryOptions,
transformFilter: transformFilter,
transformOrderBy: transformOrderBy,
transformExpand: transformExpand,
transformSelect: transformSelect,
transformSkip: transformSkip,
transformTop: transformTop
);
}
public static ODataQueryOptions RemoveSkipCount<TEntity>(this ODataQueryOptions<TEntity> queryOptions)
{
Contract.Requires(null != queryOptions);
Contract.Ensures(null != Contract.Result<ODataQueryOptions>());
return ODataQueryOptionsUtilities.Transform
(
queryOptions,
new ODataQueryOptionsUtilitiesTransformSettings
{
Skip = (map, option) => default(int?)
}
);
}
public static ODataQueryOptions SetSkipCount<TEntity>(this ODataQueryOptions<TEntity> queryOptions, int value)
{
Contract.Requires(null != queryOptions);
Contract.Requires(0 <= value);
Contract.Ensures(null != Contract.Result<ODataQueryOptions>());
return ODataQueryOptionsUtilities.Transform
(
queryOptions,
new ODataQueryOptionsUtilitiesTransformSettings
{
Skip = (map, option) => value
}
);
}
}
}
/**
* Copyright 2017 d-fens GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using Microsoft.Ajax.Utilities;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.OData.Query;
//using biz.dfch.CS.Commons.Linq;
//using Net.Appclusive.Public.Domain;
namespace PBSWebServerAPI.Util
{
public class ODataQueryOptionsUtilities
{
public const char QUERY_OPTIONS_PREFIX = '?';
public const char QUERY_OPTIONS_SEPARATOR = '&';
public const char QUERY_OPTIONS_DELIMITER = '=';
public const string QUERY_OPTION_EXPAND = "$expand";
public const string QUERY_OPTION_SELECT = "$select";
public const string QUERY_OPTION_SKIP = "$skip";
public const string QUERY_OPTION_TOP = "$top";
public const string QUERY_OPTION_FILTER = "$filter";
public const char QUERY_OPTION_SELECT_EXPAND_DELIMITER = ',';
public static ODataQueryOptions<TEntity> Transform<TEntity>
(
ODataQueryOptions<TEntity> queryOptions,
ODataQueryOptionsUtilitiesTransformSettings settings
)
{
Contract.Requires(null != queryOptions);
Contract.Requires(null != settings);
Contract.Ensures(null != Contract.Result<ODataQueryOptions>());
return Transform<TEntity>
(
queryOptions: queryOptions,
transformFilter: settings.Filter,
transformOrderBy: settings.OrderBy,
transformExpand: settings.Expand,
transformSelect: settings.Select,
transformSkip: settings.Skip,
transformTop: settings.Top
);
}
public static ODataQueryOptions<TEntity> Transform<TEntity>
(
ODataQueryOptions<TEntity> queryOptions,
Func<IReadOnlyDictionary<string, string>, FilterQueryOption, string> transformFilter,
Func<IReadOnlyDictionary<string, string>, OrderByQueryOption, IList<string>> transformOrderBy,
Func<IReadOnlyDictionary<string, string>, SelectExpandQueryOption, IList<string>> transformExpand,
Func<IReadOnlyDictionary<string, string>, SelectExpandQueryOption, IList<string>> transformSelect,
Func<IReadOnlyDictionary<string, string>, SkipQueryOption, int?> transformSkip,
Func<IReadOnlyDictionary<string, string>, TopQueryOption, int?> transformTop
)
{
Contract.Requires(null != queryOptions);
Contract.Ensures(null != Contract.Result<ODataQueryOptions>());
var uri = queryOptions.Request.RequestUri;
var queryParameters = uri.Query
.TrimStart(QUERY_OPTIONS_PREFIX)
.Split(new[] { QUERY_OPTIONS_SEPARATOR }, StringSplitOptions.RemoveEmptyEntries)
.ToDictionary
(
e => e.Split(QUERY_OPTIONS_DELIMITER).FirstOrDefault(),
e => e.Split(QUERY_OPTIONS_DELIMITER).LastOrDefault()
);
if (null != transformFilter)
{
var result = transformFilter(new ReadOnlyDictionary<string, string>(queryParameters), queryOptions.Filter);
if (null != result)
{
queryParameters[QUERY_OPTION_FILTER] = result;
}
}
if (null != transformOrderBy)
{
var result = transformOrderBy(new ReadOnlyDictionary<string, string>(queryParameters), queryOptions.OrderBy);
if (null != result)
{
queryParameters[QUERY_OPTION_EXPAND] = string.Join(QUERY_OPTION_SELECT_EXPAND_DELIMITER.ToString(), result);
}
}
if (null != transformExpand)
{
var result = transformExpand(new ReadOnlyDictionary<string, string>(queryParameters), queryOptions.SelectExpand);
if (null != result)
{
queryParameters[QUERY_OPTION_EXPAND] = string.Join(QUERY_OPTION_SELECT_EXPAND_DELIMITER.ToString(), result);
}
}
if (null != transformSelect)
{
var result = transformSelect(new ReadOnlyDictionary<string, string>(queryParameters), queryOptions.SelectExpand);
if (null != result)
{
queryParameters[QUERY_OPTION_SELECT] = string.Join(QUERY_OPTION_SELECT_EXPAND_DELIMITER.ToString(), result);
}
}
if (null != transformSkip)
{
var result = transformSkip(new ReadOnlyDictionary<string, string>(queryParameters), queryOptions.Skip);
if (result.HasValue)
{
queryParameters[QUERY_OPTION_SKIP] = result.Value.ToString();
}
else
{
if (queryParameters.ContainsKey(QUERY_OPTION_SKIP))
{
queryParameters.Remove(QUERY_OPTION_SKIP);
}
}
}
if (null != transformTop)
{
var result = transformTop(new ReadOnlyDictionary<string, string>(queryParameters), queryOptions.Top);
if (result.HasValue)
{
queryParameters[QUERY_OPTION_TOP] = result.Value.ToString();
}
else
{
if (queryParameters.ContainsKey(QUERY_OPTION_TOP))
{
queryParameters.Remove(QUERY_OPTION_TOP);
}
}
}
var newQueryOptions = new StringBuilder();
queryParameters.ForEach(e =>
{
newQueryOptions.Append(QUERY_OPTIONS_SEPARATOR);
newQueryOptions.Append(e.Key);
newQueryOptions.Append(QUERY_OPTIONS_DELIMITER);
newQueryOptions.Append(e.Value);
});
queryOptions.Request.RequestUri =
new Uri($"{uri.Scheme}://{uri.Authority}{uri.AbsolutePath}{QUERY_OPTIONS_PREFIX}{newQueryOptions}");
var newOdataQueryOptions = (ODataQueryOptions<TEntity>)Activator.CreateInstance(queryOptions.GetType(), queryOptions.Context, queryOptions.Request);
return newOdataQueryOptions;
}
}
}
/**
* Copyright 2017 d-fens GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Web.OData.Query;
namespace PBSWebServerAPI.Util
{
public class ODataQueryOptionsUtilitiesTransformSettings
{
public Func<IReadOnlyDictionary<string, string>, FilterQueryOption, string> Filter;
public Func<IReadOnlyDictionary<string, string>, OrderByQueryOption, IList<string>> OrderBy;
public Func<IReadOnlyDictionary<string, string>, SelectExpandQueryOption, IList<string>> Expand;
public Func<IReadOnlyDictionary<string, string>, SelectExpandQueryOption, IList<string>> Select;
public Func<IReadOnlyDictionary<string, string>, SkipQueryOption, int?> Skip;
public Func<IReadOnlyDictionary<string, string>, TopQueryOption, int?> Top;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment