Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for issue 121 - Added support for multiple filters with same name name #122

Merged
merged 1 commit into from
Apr 5, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
230 changes: 125 additions & 105 deletions OrderCloud.Catalyst/Models/ListOptions/ListArgsBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,117 +8,137 @@

namespace OrderCloud.Catalyst
{
public class ListArgsModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
Require.That(bindingContext != null, new ArgumentNullException(nameof(bindingContext)));
public class ListArgsModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
Require.That(bindingContext != null, new ArgumentNullException(nameof(bindingContext)));

if (bindingContext.ModelType.WithoutGenericArgs() != typeof(ListArgs<>) && bindingContext.ModelType.WithoutGenericArgs() != typeof(SearchArgs<>))
return Task.CompletedTask;
if (bindingContext.ModelType.WithoutGenericArgs() != typeof(ListArgs<>) && bindingContext.ModelType.WithoutGenericArgs() != typeof(SearchArgs<>))
return Task.CompletedTask;

var listArgs = (IListArgs)Activator.CreateInstance(bindingContext.ModelType);
LoadFromQueryString(bindingContext.HttpContext.Request.Query, listArgs);
listArgs.ValidateAndNormalize();
bindingContext.Model = listArgs;
bindingContext.Result = ModelBindingResult.Success(listArgs);
return Task.CompletedTask;
}
var listArgs = (IListArgs)Activator.CreateInstance(bindingContext.ModelType);
LoadFromQueryString(bindingContext.HttpContext.Request.Query, listArgs);
listArgs.ValidateAndNormalize();
bindingContext.Model = listArgs;
bindingContext.Result = ModelBindingResult.Success(listArgs);
return Task.CompletedTask;
}

public virtual void LoadFromQueryString(IQueryCollection query, IListArgs listArgs)
{
listArgs.Filters = new List<ListFilter>();
foreach (var param in query)
{
int i;
var (key, value) = (param.Key, param.Value);
switch (key.ToLower())
{
case "sortby":
listArgs.SortBy = value.ToString().Split(',').Distinct().ToArray();
break;
case "page":
if (int.TryParse(value, out i) && i >= 1)
listArgs.Page = i;
else
throw new UserErrorException("page must be an integer greater than or equal to 1.");
break;
case "pagesize":
if (int.TryParse(value, out i) && i >= 1 && i <= 100)
listArgs.PageSize = i;
else
throw new UserErrorException($"pageSize must be an integer between 1 and 100.");
break;
case "search":
listArgs.Search = value.ToString();
break;
case "searchon":
listArgs.SearchOn = value.ToString();
break;
case "searchtype":
var prop = listArgs.GetType().GetProperty(nameof(SearchType));
if (prop != null)
{
if (!Enum.TryParse(value, true, out SearchType searchType))
{
var options = string.Join(", ", Enum.GetNames(typeof(SearchType)));
throw new UserErrorException($"searchType must be one of: {options}");
}
prop.SetValue(listArgs, searchType);
}
else
{
// model has no SearchType. it's a ListArgs<T> and not a SearchArgs<T>
listArgs.Filters.Add(new ListFilter(key, value));
}
break;
default:
listArgs.Filters.Add(new ListFilter(key, value));
break;
}
}
}
}
public virtual void LoadFromQueryString(IQueryCollection query, IListArgs listArgs)
{
listArgs.Filters = new List<ListFilter>();
foreach (var param in query)
{
int i;
var (key, value) = (param.Key, param.Value);
switch (key.ToLower())
{
case "sortby":
listArgs.SortBy = value.ToString().Split(',').Distinct().ToArray();
break;
case "page":
if (int.TryParse(value, out i) && i >= 1)
listArgs.Page = i;
else
throw new UserErrorException("page must be an integer greater than or equal to 1.");
break;
case "pagesize":
if (int.TryParse(value, out i) && i >= 1 && i <= 100)
listArgs.PageSize = i;
else
throw new UserErrorException($"pageSize must be an integer between 1 and 100.");
break;
case "search":
listArgs.Search = value.ToString();
break;
case "searchon":
listArgs.SearchOn = value.ToString();
break;
case "searchtype":
var prop = listArgs.GetType().GetProperty(nameof(SearchType));
if (prop != null)
{
if (!Enum.TryParse(value, true, out SearchType searchType))
{
var options = string.Join(", ", Enum.GetNames(typeof(SearchType)));
throw new UserErrorException($"searchType must be one of: {options}");
}
prop.SetValue(listArgs, searchType);
}
else
{
// model has no SearchType. it's a ListArgs<T> and not a SearchArgs<T>
if (value.Count > 1)
{
foreach (var val in value)
{
listArgs.Filters.Add(new ListFilter(key, val));
}
}
else
{
listArgs.Filters.Add(new ListFilter(key, value));
}
}
break;
default:
if (value.Count > 1)
{
foreach (var val in value)
{
listArgs.Filters.Add(new ListFilter(key, val));
}
}
else
{
listArgs.Filters.Add(new ListFilter(key, value));
}
break;
}
}
}
}

public class ListArgsPageOnlyModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
Require.That(bindingContext != null, new ArgumentNullException(nameof(bindingContext)));
public class ListArgsPageOnlyModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
Require.That(bindingContext != null, new ArgumentNullException(nameof(bindingContext)));

if (bindingContext.ModelType.WithoutGenericArgs() != typeof(ListArgsPageOnly))
return Task.CompletedTask;
if (bindingContext.ModelType.WithoutGenericArgs() != typeof(ListArgsPageOnly))
return Task.CompletedTask;

var listArgs = (ListArgsPageOnly)Activator.CreateInstance(bindingContext.ModelType);
LoadFromQueryString(bindingContext.HttpContext.Request.Query, listArgs);
bindingContext.Model = listArgs;
bindingContext.Result = ModelBindingResult.Success(listArgs);
return Task.CompletedTask;
}
var listArgs = (ListArgsPageOnly)Activator.CreateInstance(bindingContext.ModelType);
LoadFromQueryString(bindingContext.HttpContext.Request.Query, listArgs);
bindingContext.Model = listArgs;
bindingContext.Result = ModelBindingResult.Success(listArgs);
return Task.CompletedTask;
}

public virtual void LoadFromQueryString(IQueryCollection query, ListArgsPageOnly listArgs)
{
foreach (var param in query)
{
int i;
var (key, value) = (param.Key, param.Value);
switch (key.ToLower())
{
public virtual void LoadFromQueryString(IQueryCollection query, ListArgsPageOnly listArgs)
{
foreach (var param in query)
{
int i;
var (key, value) = (param.Key, param.Value);
switch (key.ToLower())
{

case "page":
if (int.TryParse(value, out i) && i >= 1)
listArgs.Page = i;
else
throw new UserErrorException("page must be an integer greater than or equal to 1.");
break;
case "pagesize":
if (int.TryParse(value, out i) && i >= 1 && i <= 100)
listArgs.PageSize = i;
else
throw new UserErrorException($"pageSize must be an integer between 1 and 100.");
break;
}
}
}
}
case "page":
if (int.TryParse(value, out i) && i >= 1)
listArgs.Page = i;
else
throw new UserErrorException("page must be an integer greater than or equal to 1.");
break;
case "pagesize":
if (int.TryParse(value, out i) && i >= 1 && i <= 100)
listArgs.PageSize = i;
else
throw new UserErrorException($"pageSize must be an integer between 1 and 100.");
break;
}
}
}
}
}
Loading