Open gdodd1977 opened 3 years ago
@clairernovotny can anyone follow this issue? we have the same issue.
I'm not sure what you would expect to see here for this? Query strings are ultimately key/value pairs, not rich complex data. Those are better done in a body with a format like json, xml, or yaml.
You can't pass a body to a GET.
The question remains, what does the query expect?
@clairernovotny complex type can serialize to query string with dot as property separator and serialization format for collections (and collection of complex types)can be done with square bracket and index.
public class ListOption
{
public List<FilterModel> Filter { get; set; } = new List<FilterModel>();
public List<SortModel> Sort { get; set; } = new List<SortModel>();
public int Page { get; set; }
public int Limit { get; set; }
}
public class FilterModel
{
public FilterModel(string property, string value)
{
Property = property;
Value = value;
}
public string Property { get;}
public string Value { get;}
}
public class SortModel
{
public SortModel(string property,string direction)
{
Property = property;
Direction = direction;
}
public string Property { get; }
public string Direction { get;}
}
query string for "ListOption" model can be as like below. Page=25&Limit=0&Sort[0].Direction=asc&Sort[0].Property=entryDate&Sort[1].Direction=desc&Sort[1].Property=Age
we need to bind our model from query in .netCore API https://docs.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-6.0#dictionaries
Learn how model binding in ASP.NET Core works and how to customize its behavior.
Something like Sort[1]
is a very specific representation of a property; it's not something that can be generalized between REST backends/clients so if you need that, I'd recommend using a custom formatter.
Can you provide me with an example or any documentation of a custom formatter?
@clairernovotny I'm not sure I follow your last answer re: Sort[1]. @HosseinSalmanian is asking for Refit to model bind for a .NET Core API. .NET binding has used square bracket notation for arrays and dictionaries since its inception. If I understand you correctly, you're saying Sort[1]
is a non-standard format? What I don't understand is how can a .NET library not support the default .NET format and say it's nonstandard and won't be implemented?
Regardless, I'm in the same boat and I'd like to implement it. I have a third-party API that takes in a filter dictionary in the querystring in the following format: ?filter[email]=hello@world.com&filter[company]=github
My data type is a Params
class with a Dictionary<string, object> filters { get; set; }
That's fine and all, except I have no clue how to format the dictionary with bracket notation instead of dot notation.
Looking at overriding DefaultUrlParameterFormatter
doesn't seem to help, I don't think. From what I can tell it doesn't distinguish between the key and the value, and by the time this gets called, it's already on the string key of my dictionary and not on the dictionary itself.
Soooooo yea... documentation or an example of a custom formatter would be helpful :) FWIW I looked at the test cases that override/implement DefaultUrlParameterFormatter
and it wasn't helpful for the above case.
Refit supports REST API's all up and does not make .NET-specific assumptions about formatting. It is bad idea to put a platform/language-specific feature in a URL/query as leaks implementation details into a public surface area.
That said, it should be possible for a custom formatter implementation to generate what's needed and if that extension point is missing, then we can take a PR to add it.
I'm not suggesting to put platform-specific assumptions in. But I am suggesting that, if a .NET platform supposes to support all APIs it should at least support the APIs of said platform.
I'd hate to see something hardcoded, but I'd also expect to see some formatting options built in to support an API built on the same platform.
Apologies if my explanation is confusing.
I think it could be solved by making the UrlParamterFormatter aware of if it's formatting the key or the value. Right now it says "I have something to format... how do I format it?" And instead of should say "I have a key to format? I'll do it like this; I have a value to format? I'll do it like that."
Having not yet contributed to Refit, I'm not sure if I've understood the architecture. If what I'm saying makes sense, @clairernovotny, then I'd be happy to try my hand at a PR for it. My gut says it would be some kind of breaking change, though, as I expect the underlying interface would need to change, or be broken out into two parts (Key formatter vs Value formatter).
@grexican @HosseinSalmanian Hi, I have the same issue, could you share your solution here, please? If it exists, of course
I think it can be useful for many refit users
@kruzzze no I never did find a solution. I ended up circumventing the issue by declaring all of the individual filters I needed and specifying the querystring param, e.g. a DTO with { Key1 { get; set; } { Key2 { get; set; } }
and decorating each param with the url param "filter[Key1]" and "filter[Key2]" for example. My needs were limited to a few keys, so I could get away with it.
Hi there, were any customizable formatter been added? I also would like to know how such kind of Query params customization can be achieved?
I have a similar problem. Is this issue resolved?
I read the source code and this can't be done cleanly (even with v7 UrlParameterKeyFormatter). It would have been better if it was just a UrlParameterKeyValuePairFormatter to provide a bit more flexibility but it would break a bunch of existing functionalities that they currently have.
After reading the source code, I did write a very hacky UrlParameterFormatter
to get this issue to work. It's very specific/hardcoded to the api that I needed to call. It requires the URI to be unescaped and a DelegatingHandler
to clean up the query string since you can't do much with the formatter.
I've got the following QueryParams object:
`public class GetLocationsQueryParams { public GetLocationsQueryParams() { LocationDeviceData = new List();
}
LocationDeviceData is as follows:
public class LocationDeviceData { public string ServiceProvider { get; set; } public string VendorDeviceId { get; set; } public string VendorRepairId { get; set; } }
When I pass this into a Get call, the query string generated is as follows:
repair/locations?Address.AddressType=None&Address.Line1=1407 Fleet St.&Address.Line2=&Address.Region=MD&Address.City=Baltimore&Address.Country=US&Address.PostalCode=21231&Distance=30&DistanceType=Miles&LocationDeviceData=LocationDeviceData&Limit=20&ProgramId=a4e24585-a63c-4597-be12-a6cfdafa15ee&FulfillmentOption=WalkInRepair
Is refit unable to parse query string objects like this into a proper query string?