首页 > 解决方案 > JsonResult 和 ObjectResult 不是相互派生的——为什么?

问题描述

我团队中的人写的东西是这样的:

[HttpPost("do")]
public async Task<ActionResult> DoAsync()
{
    try
    {
        var obj = await this.DoThing();

        return new JsonResult(obj);
    }
    catch (StatusCodeException x)
    {
        return StatusCode(x.StatusCode, new { x.Message, x.StackTrace });
    }
    catch (Exception x)
    {
        return StatusCode(500, x.GenerateMessage(" "));
    }
}

这意味着JsonResultObjectResult可以返回,这使测试变得复杂。这是因为JsonResultObjectResult相互派生。有谁知道为什么会这样?

我必须编写一个小包装类进行测试,以使生活更轻松:

/// <summary>
/// Defines all subclasses of <see cref="ActionResult"/>
/// that have status codes and <see cref="object"/> values.
/// </summary>
public class ObjectValueActionResult
{
    /// <summary>
    /// Initializes a new instance of the <see cref="ObjectValueActionResult"/> class.
    /// </summary>
    /// <param name="result">The result.</param>
    /// <remarks>
    /// The majority of <see cref="IActionResult"/> instances like <see cref="OkObjectResult"/> derive
    /// from <see cref="ObjectResult"/>.
    /// </remarks>
    public ObjectValueActionResult(IActionResult result)
    {
        Assert.NotNull(result);
        switch (result)
        {
            case JsonResult j:
                this.Value = j.Value;
                this.StatusCode = j.StatusCode;
                break;
            case NoContentResult n:
                this.StatusCode = n.StatusCode;
                break;
            case ObjectResult o:
                this.Value = o.Value;
                this.StatusCode = o.StatusCode;
                break;
            default:
                throw new NotImplementedException($"The expected {nameof(IAsyncResult)} type is not here.");
        }
    }
    /// <summary>
    /// Gets or sets the value.
    /// </summary>
    /// <value>
    /// The value.
    /// </value>
    public object Value { get; set; }
    /// <summary>Gets or sets the HTTP status code.</summary>
    public int? StatusCode { get; set; }
}

有没有替代方案?

标签: asp.net-mvcasp.net-core

解决方案


JsonResult旨在返回 JSON 格式的数据,无论通过 Accept 标头请求什么格式,它都会返回 JSON。当我们使用 JsonResult 时,不会发生内容协商。

内容协商是确定浏览器通过其 Http 请求 Accept 标头请求的数据类型的过程。例如,这是一个请求 HTML: 类型内容的接受标头,Accept: application/xml, */*; q=0.01操作结果为 JsonResult 类型,不会发生内容协商。这意味着服务器会忽略用户请求的类型并返回 JSON 。

ObjectResult是一个内置内容协商的 IActionResult。通常,除非您指定 Accept 标头,否则 API 会将响应序列化为 JSON。如果您指定例如 'application/xml' ,它将返回 XML 。

参考 :

http://hamidmosalla.com/2017/03/29/asp-net-core-action-results-explained/

https://docs.microsoft.com/en-us/aspnet/core/web-api/advanced/formatting?view=aspnetcore-2.2


推荐阅读