Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to deserialize ProblemDetails in ASP.NET Core 2.2

Tags:

asp.net-core

I have a C# client app that calls an ASP.NET Core REST service. If the REST service fails on the server it is configured to return a 'problem details' json response as per rfc7807, e.g.:

{
    "type": "ServiceFault",
    "title": "A service level error occurred executing the action FooController.Create
    "status": 500,
    "detail": "Code=ServiceFault; Reference=5a0912a2-df17-4f27-8e5a-0d4828022306; Message=An error occurred creating a record.",
    "instance": "urn:foo-corp:error:5a0912a2-df17-4f27-8e5a-0d4828022306"
}

In the client app I would like to deserialize this json message to an instance of ProblemDetails as a convenient way of accessing the details. E.g.:

ProblemDetails details = await httpResp.Content.ReadAsAsync<ProblemDetails>();

However, the deserialization throws the following exception:

System.Net.Http.UnsupportedMediaTypeException: No MediaTypeFormatter is available to read an object of type 'ProblemDetails' from content with media type 'application/problem+json'.

like image 705
redcalx Avatar asked Oct 31 '19 14:10

redcalx


2 Answers

ReadAsAsync<T> is unfamiliar with the application/problem+json media type, and does not have a formatter that can handle that type by default, hence the error

You can use the long approach and get the string first then use Json.Net

string json = await httpResp.Content.ReadAsStringAsync();
ProblemDetails details = JsonConvert.DeserializeObject<ProblemDetails>(json);
like image 117
Nkosi Avatar answered Nov 15 '22 10:11

Nkosi


You can define a ProblemDetailsMediaTypeFormatter that will inherit from JsonMediaTypeFormatter.

    public class ProblemDetailsMediaTypeFormatter : JsonMediaTypeFormatter
    {
        public ProblemDetailsMediaTypeFormatter()
        {
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/problem+json"));
        }
    }

Usage:

var problemDetails = await response.Content
    .ReadAsAsync<ProblemDetails>(new [] { new ProblemDetailsMediaTypeFormatter() }, cancellationToken);
like image 32
Toé Avatar answered Nov 15 '22 10:11

Toé