I'm trying to consume a REST API using curly braces, but I can't figure out how to send them unescaped through HttpClient.GetFromJsonAsync.
string readKey = "1VQXp8053OlOs05XcoWX3L46TEQ4JaPnPtJMwUH6k0xUkgXWMd";
string endpoint = "https://api.cosmicjs.com/v2/buckets/ffm-blog-blog/objects?read_key={readKey}";
string queryOperator = "&query=";
string query = "{type:"posts"}";
//Working URI (in browser and Postman) : https://api.cosmicjs.com/v2/buckets/ffm-blog-blog/objects?read_key=1VQXp8053OlOs05XcoWX3L46TEQ4JaPnPtJMwUH6k0xUkgXWMd&query={"type":"posts"}
I tried different approaches:
string uriA = endpoint queryOperator query;
string uriB = endpoint queryOperator Uri.UnescapedDataString(query);
Uri uriC = new Uri(endpoint queryOperator query);
Uri uriD = new Uri(endpoint queryOperator Uri.UnescapedDataString(query);
Uri uriE = new Uri(Uri.UnescapedDataString(endpoint queryOperator query);
...
Whatever method I try with HttpClient:
CosmicResponse cosmicReponse = await _http.GetFromJsonAsync<CosmicResponse>(uri);
I always get the same result:
System.Net.Http.HttpRequestException: TypeError: Failed to fetch
The URI sent by HttpClient always is :
https://api.cosmicjs.com/v2/buckets/ffm-blog-blog/objects?read_key=xxxx&query={"type":"posts"}
and, of course, I doesn't work.
It works when sending a request without the query part:
string uri = "https://api.cosmicjs.com/v2/buckets/ffm-blog-blog/objects?read_key=xxxx";
CosmicResponse cosmicReponse = await _http.GetFromJsonAsync<CosmicResponse>(uri);
However, I need to use the query part.
I know using curly braces in an API is bad practice, but I didn't write the API and I'm just trying to consume it.
Would someone happen to know how to send "{" and "}" instead of "{" and "}" with HttpClient?
FULL CODE
public async Task<List<Post>> GetAllPosts()
{
HttpClient http = new();
string _rootUrl = "https://api.cosmicjs.com/v2/buckets/ffm-blog-blog";
string _readKey = "1VQXp8053OlOs05XcoWX3L46TEQ4JaPnPtJMwUH6k0xUkgXWMd";
string endpoint = $"{_rootUrl}/objects?read_key={_readKey}";
string query = "{type:"posts"}";
Uri uri = new Uri(Uri.UnescapeDataString(endpoint "&query=" query));
CosmicResponse cosmicReponse = await http.GetFromJsonAsync<CosmicResponse>(uri);
List<Post> posts = new();
foreach (CosmicPost c in cosmicReponse.Objects)
{
posts.Add(GetPostFromCosmic(c));
}
return posts;
}
FINAL WORDS
It turns out it was a CORS issue. As Postman doesn't enforce CORS policy, I falsely thought the problem was linked to HttpClient. I solved the problem by going through a proxy.
CodePudding user response:
Better let the library does the work for you. Use NameValueCollection
returned by HttpUtility.ParseQueryString
(note that they return a different derived type HttpValueCollection
which you cannot initialize by yourself). See more here.
Since you didn't give the class definition, I switched the type to object
so the test code can run:
static async Task<object> GetAllPosts()
{
HttpClient http = new();
string _rootUrl = "https://api.cosmicjs.com/v2/buckets/ffm-blog-blog";
string _readKey = "1VQXp8053OlOs05XcoWX3L46TEQ4JaPnPtJMwUH6k0xUkgXWMd";
var query = HttpUtility.ParseQueryString("");
query.Add("read_key", _readKey);
query.Add("query", "{\"type\":\"posts\"}");
string endpoint = $"{_rootUrl}/objects?" query.ToString();
return (await http.GetFromJsonAsync<object>(endpoint))!;
}