Support list/enumrable of complex types for ABP dynamic/static c# proxies on GET requests
Currently, it can not properly convert these kind of objects to query string parameters. Example method parameter:
// APP SERVICE METHOD:
public async Task<PagedResultDto<Dictionary<string, object?>>> GetListAsync(DynamicEntityListRequestDto input)
// METHOD PARAM
public class DynamicEntityListRequestDto : PagedResultRequestDto
{
public string EntityName { get; set; }
public List<DynamicQuerySortArgs>? Sortings { get; set; }
}
public class DynamicQuerySortArgs
{
public string PropertyName { get; set; }
public bool IsDescending { get; set; }
}
Now the request is made like that:
https://localhost:44337/api/app/dynamic-entity?
EntityName=LowCodeDemo.Customers.Customer&
Sortings[0]=LowCodeDemo.LowCode.DynamicQuerySortArgs&
SkipCount=0&MaxResultCount=10&api-version=1.0
So, it makes ToString() for the LowCodeDemo.LowCode.DynamicQuerySortArgs object, but it should send its values properly.
We can't convert all types to query strings,formdata, or path correctly. So we have provided IObjectToQueryString/IObjectToFormData/IObjectToPath for developers to implement themselves.
Add a class that implements the IObjectToQueryString<DynamicEntityListRequestDto>, build the query string yourself, and add it to AbpHttpClientProxyingOptions's QueryStringConverts.
https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/IObjectToQueryString.cs https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ExtraPropertyDictionaryConverts/ExtraPropertyDictionaryToQueryString.cs https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientModule.cs#L34-L38
@maliming it didn't work smoothly, because HttpActionParameterHelper.FindParameterValue also couldn't properly retrieve the value.
Anyway, I think we can handle enumrable of any type with reflection, at least one level depth.
because HttpActionParameterHelper.FindParameterValue also couldn't properly retrieve the value.
I will try to reproduce it to resolve the problem.
Adding IObjectToQueryString<List<DynamicQuerySortArgs>> can solve this case.
var input = new DynamicEntityListRequestDto()
{
EntityName = "Person",
Sortings = new List<DynamicQuerySortArgs>()
{
new DynamicQuerySortArgs() {PropertyName = "Name", IsDescending = false},
new DynamicQuerySortArgs() {PropertyName = "Age", IsDescending = true}
}
};
public class DynamicQuerySortArgsToQueryString : IObjectToQueryString<List<DynamicQuerySortArgs>>, ITransientDependency
{
public Task<string> ConvertAsync(ActionApiDescriptionModel actionApiDescription, ParameterApiDescriptionModel parameterApiDescription, List<DynamicQuerySortArgs> values)
{
if (values.IsNullOrEmpty())
{
return Task.FromResult<string>(null);
}
var sb = new StringBuilder();
for (var i = 0; i < values.Count; i++)
{
sb.Append($"Sortings[{i}].PropertyName={values[i].PropertyName}&Sortings[{i}].IsDescending={values[i].IsDescending}&");
}
sb.Remove(sb.Length - 1, 1);
return Task.FromResult(sb.ToString());
}
}
Configure<AbpHttpClientProxyingOptions>(options =>
{
options.QueryStringConverts.Add(typeof(List<DynamicQuerySortArgs>), typeof(DynamicQuerySortArgsToQueryString));
});
/api/app/dynamic-entity?EntityName=Person&Sortings[0].PropertyName=Name&Sortings[0].IsDescending=False&Sortings[1].PropertyName=Age&Sortings[1].IsDescending=True&SkipCount=0&MaxResultCount=10&api-version=1.0
Thanks for your suggestion