Reputation: 41
My requirement is to allow only a few properties to be used in OData $filter option. Here I have a student model, which contains a bunch of properties. I want only the 'name' property have the $filter capability enabled. But somehow it is not working. Can anybody please help me.
The following is my code
My model:
public class Student {
public string Id { get; set; }
public string Name { get; set; }
public string AccessType { get; set; }
public string SortOrder { get; set; }
public string Status { get; set; }
}
public class RestrictiveFilterByQueryValidator : FilterQueryValidator
{
static readonly string[] allowedProperties = { "name" };
public RestrictiveFilterByQueryValidator(DefaultQuerySettings defaultQuerySettings)
: base(defaultQuerySettings)
{
}
public override void ValidateSingleValuePropertyAccessNode(
SingleValuePropertyAccessNode propertyAccessNode,
ODataValidationSettings settings)
{
string propertyName = null;
if (propertyAccessNode != null)
{
propertyName = propertyAccessNode.Property.Name;
}
if (propertyName != null && !allowedProperties.Contains(propertyName))
{
throw new ODataException(
String.Format("Filter on {0} not allowed", propertyName));
}
base.ValidateSingleValuePropertyAccessNode(propertyAccessNode, settings);
}
public static implicit operator System.Web.Http.OData.Query.Validators.FilterQueryValidator(RestrictiveFilterByQueryValidator v)
{
throw new NotImplementedException();
}
}
public class MyQueryableAttribute : QueryableAttribute
{
public override void ValidateQuery(HttpRequestMessage request, System.Web.Http.OData.Query.ODataQueryOptions queryOptions)
{
if (queryOptions.Filter != null)
{
queryOptions.Filter.Validator = new RestrictiveFilterByQueryValidator(new DefaultQuerySettings());
}
// HttpRequestMessage request, ODataQueryOptions queryOptions
base.ValidateQuery(request, queryOptions);
}
}
[MyQueryable]
public ActionResult<IEnumerable<Student>> GetAllStudent()
{
}
When I followed the above code, my normal $filter with valid properties also don't work as expected. I think I am missing something. Any help will be grateful.
Upvotes: 2
Views: 1358
Reputation: 16554
Do not call the base implementation of the Validator if the property IS Valid.
It's not that obvious but the base implementation exists to format the error message in a standard way so you return nothing when it is valid and call the base only when it is NOT valid!
public override void ValidateSingleValuePropertyAccessNode(
SingleValuePropertyAccessNode propertyAccessNode,
ODataValidationSettings settings)
{
string propertyName = null;
if (propertyAccessNode != null)
{
propertyName = propertyAccessNode.Property.Name;
}
if (propertyName != null && !allowedProperties.Contains(propertyName))
{
base.ValidateSingleValuePropertyAccessNode(propertyAccessNode, settings);
}
}
Upvotes: 1