Open rafikiassumani-msft opened 3 years ago
@bradygaster is interested in this as well
@davidfowl I just assigned it to him. We had a conversation on this.
Just putting down some thoughts that came to mind today.
Would't it be possible to use a Source generator for this case?
Using Attributes in a way of something like this:
//Example partially taken from reactiveui/refit
public interface IGithubApi
{
[Get("/users")]
[Response(ResponseType.Xml)] //Using XmlDeserializer on this endpoint
public IAsyncEnumerable<User> GetUserAsync();
[Get("/users")]
[Response(ResponseType.Json)] //Using JsonDeserializer
public IAsyncEnumerable<User> GetUsersAsync(CancellationToken cancellationToken);
[Get("/users/{user}")]
public Task<User> GetUserAsync(string user, CancellationToken cancellationToken);
[Get("/users/{user}")]
public Stream GetUserStreamAsync(string user, CancellationToken cancellationToken);
}
[Apiclient<IGithubApi>] //[ApiClient(typeof(IGithubClient))]
public partial class GithubApi
{
}
which would result in something like this:
public partial class GithubApi : IGithubApi
{
private readonly HttpClient _client;
public GithubApi(HttpClient client)
{
_client = client;
}
public async IAsyncEnumerable<User> GetUsersAsync()
{
using var responseMessage = await _client.GetAsync("/users");
if (!responseMessage.IsSuccessStatusCode)
{
//something doing here?
}
await using var stream = await responseMessage.Content.ReadAsStreamAsync();
var reader = XmlReader.Create(stream);
var serializer = new XmlSerializer(typeof(User[]));
if (!serializer.CanDeserialize(reader))
{
throw new InvalidOperationException("Not Deserializable");
}
var entries = (User[])serializer.Deserialize(reader);
if (entries == null) yield break;
foreach (var entry in entries)
{
yield return entry;
}
}
public async IAsyncEnumerable<User> GetUsersAsync([EnumeratorCancellation]CancellationToken cancellationToken)
{
using var responseMessage = await _client.GetAsync("/users", cancellationToken);
if (!responseMessage.IsSuccessStatusCode)
{
//something doing here?
}
await using var stream = await responseMessage.Content.ReadAsStreamAsync(cancellationToken);
var entries = JsonSerializer.DeserializeAsyncEnumerable<User>(stream, JsonSerializerOptions.Default, cancellationToken);
await foreach (var entry in entries.WithCancellation(cancellationToken))
{
yield return entry;
}
}
public Task<User> GetUserAsync(string user, CancellationToken cancellationToken)
{
}
public async Task<Stream> GetUserStreamAsync(string user, CancellationToken cancellationToken)
{
using var responseMessage = await _client.GetAsync($"/users/{user}", cancellationToken);
if (!responseMessage.IsSuccessStatusCode)
{
//something doing here?
}
return await responseMessage.Content.ReadAsStreamAsync(cancellationToken);
}
public async Task<string> GetUserStringAsync(string user, CancellationToken cancellationToken)
{
using var responseMessage = await _client.GetAsync($"/users/{user}", cancellationToken);
if (!responseMessage.IsSuccessStatusCode)
{
//something doing here?
}
return stream = await responseMessage.Content.ReadAsStringAsync(cancellationToken);
}
}
It's just something to show what I had in mind and maybe it's something worth thinking about?
I was also thinking of a way to proccess different StatusCodes, and thought of the TypedResults.NotFound, Ok etc.... When using Results<> With the corresponding Typed parameters as returnparameter, then based on that the StatusCode could be filtered out when processing the responsemessage and returned, but I haven't thought of it any further.
I love the idea of a source generator that outputs Refit clients. I spoke with @clairernovotny about this a few times. My goal would be to have a Refit provider for the REST API client generation feature in VS Connected Services. So, cc @vijayrkn, with whom I've discussed this idea a few times and seemed receptive to it.
Is your feature request related to a problem? Please describe.
Investigate how retrofit or refit can be used for REST Client generations with dotnet-api tooling.
Describe the solution you'd like
Retrofit or refit are great libraries for generating REST clients for mostly android apps. They allow you to define an interface containing a set of endpoints that your application will be interacting with, and then you can generate the implementation code. We would like to investigate the possibility of using retrofit/refit/or something new for generating REST Client implementations with dotnet-api tooling.
Additional context