猿问

.NET Core Web API:返回内容类型为 application/problem+json

ControllerBaseConflict()包含诸如返回ConflictResult派生自 的对象(表示 HTTP 409 响应)之类的方法StatusCodeResult。生成的响应正文具有内容类型application/problem+json,如下所示:


{

    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.8",

    "title": "Conflict",

    "status": 409,

    "traceId": "0HLO99QHFC9QI:00000001"

}

没有用于 HTTP 410 响应的内置方法/类,因此我创建了一个:


[DefaultStatusCode(410)]

public class GoneResult : StatusCodeResult

{

    public GoneResult() : base(410)

    {}

}

...

public static class ControllerBaseExtensions

{

    public static GoneResult Gone(this ControllerBase controllerBase) // this doesn't give all the problem+JSON attributes

    {

        return new GoneResult();

    }

}

然而,这给出了


{

    "type": "about:blank",

    "status": 410

}

即,type值不同并且缺少title和字段。traceId


我还想为 HTTP 500 响应创建一个自定义类,其中包含message带有错误消息的字段。我尝试过 return ,这给了我与我的方法StatusCode(StatusCodes.Status500InternalServerError)相同的最小响应;我也尝试过 return ,这给了我错误消息,但将响应格式设置为.application/problem+jsonGone()StatusCode(StatusCodes.Status500InternalServerError, message)text/plain


慕仙森
浏览 157回答 2
2回答

PIPIONE

生成响应的代码ProblemDetails不知道状态代码,因此在构建响应对象时410没有关联的Link和属性。Title要添加此感知,请ApiBehaviorOptions在 中进行配置ConfigureServices,如下所示:services.Configure<ApiBehaviorOptions>(options =>{    options.ClientErrorMapping[410] = new ClientErrorData    {        Title = "Gone",        Link = "https://tools.ietf.org/html/rfc7231#section-6.5.9"    };});ClientErrorMappingint是(状态代码) 到的字典ClientErrorData。请注意,我在上面使用的值Link确实指向 RFC 的正确部分。

智慧大石

简单地说,您必须实际返回ProblemDetails响应正文。我必须仔细研究代码才能确定,但我认为 ASP.NET Core 通过中间件执行此操作只是为了获得特定的结果。他们说4xx 范围内的任何内容,但我认为这实际上仅限于返回该范围内的状态代码的内置结果类型,而不是任何具有 4xx 状态代码的结果。再说一遍,这是猜测,因为我还没有确切地了解他们在做什么,尽管它没有作为实际结果类的一部分发生。出于您的目的,您可以采用几种不同的方法来处理此问题。您可以编写自己的中间件来捕获出站响应并重写它们。您可以使用自定义异常处理程序。您可以简单地继承ObjectResult,然后ProblemDetails自己创建一个实例并将其放入基础中。您甚至可以ProblemDetails直接从操作中返回(尽管这显然是最不理想的方式)。
随时随地看视频慕课网APP
我要回答