Search code examples
c#jsonserializationsuperclassrefit

Refit - Deserialize response to supertype


This question does not necessarily relate to Refit itself but here we go. The built-in ApiResponse from Refit does not do exactly what I need. There seems to be no way of accessing the raw response to deserialize it to a ProblemDetails which my API does return in case of failures. I can make due with changing my method signature to something like this :

[Multipart]
[Post("/api/importSomething")]
Task<HttpResponseMessage>ImportSomething(string someID, ByteArrayPart File);

This does give you access to the raw response. However, this type is not generic and it makes converting to my Result object implementation very ugly for the caller client. What I would like is to subclass HttpResponseMessage and make it generic so the Refit interface method could look like this :

[Multipart]
[Post("/api/importSomething")]
Task<CustomAPIResponse<SomeResponseDTO>>ImportSomething(string someID, ByteArrayPart File);

Something like this would be perfect as the caller would not need to supply the generic type for an extension method to convert to my Result object. Obviously with this code as-is, refit is throwing an exception because it's trying to deserialize to this CustomAPIResponse type and what's coming in is an HttpReponseMessage. How do I tell Refit that I want it to deserialize my custom response as the superclass?


Solution

  • This can be achieved by returning Task<IApiResponse>, Task<IApiResponse<T>>, or Task<ApiResponse<T>>

    In the documentation of refit there is a chapter about Handling Exceptions which covers exactly your use case.

    The main takeaways from it are that any ApiException when processing the response, and any errors that occur when attempting to deserialize the response to ApiResponse, are populated into the Error property on ApiResponse without throwing the exception.

    var response = await _myRefitClient.GetSomeStuff();
    if(response.IsSuccessStatusCode)
    {
       //do your thing
    }
    else
    {
       _logger.LogError(response.Error, response.Error.Content);
    }