小编典典

ASP.NET Core 返回带有状态码的 JSON

all

我正在寻找在我的 .NET Core Web API 控制器中返回带有 HTTP 状态代码的 JSON 的正确方法。我曾经这样使用它:

public IHttpActionResult GetResourceData()
{
    return this.Content(HttpStatusCode.OK, new { response = "Hello"});
}

这是在 4.6 MVC 应用程序中,但现在使用 .NET Core
我似乎没有这个IHttpActionResult我拥有ActionResult并像这样使用:

public ActionResult IsAuthenticated()
{
    return Ok(Json("123"));
}

但是服务器的响应很奇怪,如下图所示:

在此处输入图像描述

我只希望 Web API 控制器返回带有 HTTP 状态代码的 JSON,就像我在 Web API 2 中所做的那样。


阅读 89

收藏
2022-06-24

共1个答案

小编典典

以 a 响应的最基本版本JsonResult是:

// GET: api/authors
[HttpGet]
public JsonResult Get()
{
    return Json(_authorRepository.List());
}

但是,这对您的问题没有帮助,因为您无法明确处理自己的响应代码。

控制状态结果的方法是您需要返回 a ActionResult,然后您可以在其中利用该StatusCodeResult类型。

例如:

// GET: api/authors/search?namelike=foo
[HttpGet("Search")]
public IActionResult Search(string namelike)
{
    var result = _authorRepository.GetByNameSubstring(namelike);
    if (!result.Any())
    {
        return NotFound(namelike);
    }
    return Ok(result);
}

请注意,上述两个示例都来自 Microsoft 文档中的一个很好的指南:格式化响应数据


额外的东西

我经常遇到的问题是,我希望对我的 WebAPI 进行更精细的控制,而不是仅仅使用 VS 中“新项目”模板中的默认配置。

让我们确保您掌握了一些基础知识…

第 1 步:配置您的服务

为了让您的 ASP.NET Core WebAPI 响应 JSON
序列化对象以及对状态代码的完全控制,您应该首先确保已将AddMvc()服务包含在您ConfigureServices通常在Startup.cs.

需要注意的是,AddMvc()它将自动包含 JSON 的输入/输出格式化程序以及响应其他请求类型。

如果您的项目需要 完全控制 并且您想要严格定义您的服务,例如您的 WebAPI
将如何处理各种请求类型,包括application/json而不响应其他请求类型(例如标准浏览器请求),您可以使用以下代码:

public void ConfigureServices(IServiceCollection services)
{
    // Build a customized MVC implementation, without using the default AddMvc(), instead use AddMvcCore().
    // https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc/MvcServiceCollectionExtensions.cs

    services
        .AddMvcCore(options =>
        {
            options.RequireHttpsPermanent = true; // does not affect api requests
            options.RespectBrowserAcceptHeader = true; // false by default
            //options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();

            //remove these two below, but added so you know where to place them...
            options.OutputFormatters.Add(new YourCustomOutputFormatter()); 
            options.InputFormatters.Add(new YourCustomInputFormatter());
        })
        //.AddApiExplorer()
        //.AddAuthorization()
        .AddFormatterMappings()
        //.AddCacheTagHelper()
        //.AddDataAnnotations()
        //.AddCors()
        .AddJsonFormatters(); // JSON, or you can build your own custom one (above)
}

您会注意到,我还提供了一种添加您自己的自定义输入/输出格式化程序的方法,以防您可能想要响应另一种序列化格式(protobuf、thrift 等)。

上面的代码块大部分是该AddMvc()方法的副本。但是,我们通过定义每个服务而不是使用带有模板的预发布服务来自行实现每个“默认”服务。我已经在代码块中添加了存储库链接,或者您可以AddMvc()
从 GitHub
存储库中签出。
.

请注意,有一些指南会尝试通过“撤消”默认设置来解决这个问题,而不是一开始就不实施它......如果你考虑到我们现在正在使用开源,这是多余的工作,糟糕的代码,坦率地说,这是一个很快就会消失的旧习惯。


第 2 步:创建控制器

我将向您展示一个非常直截了当的问题,只是为了解决您的问题。

public class FooController
{
    [HttpPost]
    public async Task<IActionResult> Create([FromBody] Object item)
    {
        if (item == null) return BadRequest();

        var newItem = new Object(); // create the object to return
        if (newItem != null) return Ok(newItem);

        else return NotFound();
    }
}

第 3 步:检查您的Content-TypeAccept

您需要确保您的 请求*Content-Type中的标头和Accept标头设置正确。在您的情况下(JSON),您需要将其设置为.
*application/json

如果您希望您的 WebAPI 默认以 JSON 响应,无论请求标头指定什么,您都可以通过 几种方式来实现

方式 1 如我之前推荐的文章(格式化响应数据)所示,您可以在控制器/操作级别强制使用特定格式。我个人不喜欢这种方法......但这里是为了完整性:

强制使用特定格式 如果您想限制特定操作的响应格式,您可以应用 [Produces] 过滤器。[Produces]
过滤器指定特定操作(或控制器)的响应格式。像大多数过滤器一样,这可以应用于操作、控制器或全局范围。

[Produces("application/json")]
public class AuthorsController

[Produces]过滤器将强制 中的所有操作 返回AuthorsControllerJSON
格式的响应,即使为应用程序配置了其他格式化程序并且客户端提供了Accept请求不同的可用格式的标头。

方式 2 我的首选方法是让 WebAPI 以请求的格式响应所有请求。但是,如果它不接受请求的格式,则 回退到 默认值(即 JSON)

首先,您需要在您的选项中注册它(我们需要修改默认行为,如前所述)

options.RespectBrowserAcceptHeader = true; // false by default

最后,通过简单地重新排序服务构建器中定义的格式化程序列表,Web 主机将默认使用您位于列表顶部的格式化程序(即位置 0)。

2022-06-24