我正在寻找返回JSON的正确方法,其中包含一个HTTP状态码.NET核心Web API控制器.我经常这样使用它:

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

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

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

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

enter image description here

我只想让Web API控制器返回JSON和HTTP状态代码,就像我在Web API 2中所做的那样.

推荐答案

The most basic version responding with a JsonResult is:

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

However, this isn't going to help with your issue because you can't explicitly deal with your own response code.

The way to get control over the status results, is you need to return a ActionResult which is where you can then take advantage of the StatusCodeResult type.

for example:

// 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);
}

Note both of these above examples came from a great guide available from Microsoft Documentation: Formatting Response Data


额外的东西

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

让我们确保你有一些基础知识...

第1步:配置您的服务

In order to get your ASP.NET Core WebAPI to respond with a JSON Serialized Object along full control of the status code, you should start off by making sure that you have included the AddMvc() service in your ConfigureServices method usually found in Startup.cs.

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

如果您的项目需要full control,并且您希望严格定义您的服务,例如您的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()from the GitHub repository..

Note that there are some guides that will try to solve this by "undoing" the defaults, rather than just not implementing it in the first place... If you factor in that we're now working with Open Source, this is redundant work, bad code and frankly an old habit that will disappear soon.


步骤2:创建控制器

I'm going to show you a really straight-forward one just to get your question sorted.

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();
    }
}

Step 3: Check your Content-Type and Accept

You need to make sure that your Content-Type and Accept headers in your request are set properly. In your case (JSON), you will want to set it up to be application/json.

If you want your WebAPI to respond as JSON as default, regardless of what the request header is specifying you can do that in a couple ways.

Way 1

Forcing a Particular Format If you would like to restrict the response formats for a specific action you can, you can apply the [Produces] filter. The [Produces] filter specifies the response formats for a specific action (or controller). Like most Filters, this can be applied at the action, controller, or global scope.

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

The [Produces] filter will force all actions within the AuthorsController to return JSON-formatted responses, even if other formatters were configured for the application and the client provided an Accept header requesting a different, available format.

Way 2 My preferred method is for the WebAPI to respond to all requests with the format requested. However, in the event that it doesn't accept the requested format, then fall-back to a default (ie. JSON)

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

options.RespectBrowserAcceptHeader = true; // false by default

最后,只需重新排序在services builder中定义的格式化程序列表,web主机将默认为列表顶部的格式化程序(即位置0).

更多信息可以在这.NET Web Development and Tools Blog entry页中找到

Json相关问答推荐

如何在数组抖动中按值分组

如何在VegaLite中应用Times New Roman,CaliBiri字体

ArcGIS json到Geojson的变换

集成wix.comstore API|变音符号问题

在Zig中解析JSON失败

go 语言中的 JSON 到 XML

Vega-Lite规范:尽管在规范中提供了数据,但显示空图表

Jolt 不打印任何东西

我如何将 JSON 格式与 flutter 一起使用?帮助使用 Gamebanana api

将具有多个级别的 json 读入 DataFrame [python]

从 JSON 响应中获取最新版本发布字段

流导入错误:重新上传时不存在布局释放 UUID

从 json 数组中仅提取一个值导致 vb6

使用 JQ 从文件中删除重复的 JSON 块

如何使用 Serde 使用顶级数组反序列化 JSON?

Retrofit 2.0 如何解析嵌套的 JSON 对象?

在 JavaScript 中从 Json 数据中删除反斜杠

JSON 到 JSON 转换器

Jackson:忽略 Json 配置值

我应该如何在 JSON 中表示表格数据?