我正在寻找在我的. net核心Web API控制器中返回带有HTTP状态代码的JSON的正确方法。我以前是这样用的:

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

这是在一个4.6 MVC应用程序,但现在与。net核心,我似乎没有这个IHttpActionResult,我有ActionResult和使用像这样:

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

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

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


当前回答

您已经为大多数常见的状态代码预定义了方法。

result返回200 CreatedAtRoute返回201 +新的资源URL NotFound返回404 BadRequest返回400等等。

所有方法的列表请参见baseconcontroller .cs和Controller.cs。

但如果你真的坚持你可以使用StatusCode来设置一个自定义代码,但你真的不应该这样做,因为它使代码可读性较差,你将不得不重复代码来设置头部(如CreatedAtRoute)。

public ActionResult IsAuthenticated()
{
    return StatusCode(200, "123");
}

其他回答

我在我的Asp Net Core Api应用程序中所做的是创建一个从ObjectResult扩展的类,并提供许多构造函数来定制内容和状态代码。 然后我所有的控制器动作都使用适当的构造函数之一。 你可以看看我的实现: https://github.com/melardev/AspNetCoreApiPaginatedCrud

and

https://github.com/melardev/ApiAspCoreEcommerce

下面是类的样子(去我的回购完整代码):

public class StatusCodeAndDtoWrapper : ObjectResult
{



    public StatusCodeAndDtoWrapper(AppResponse dto, int statusCode = 200) : base(dto)
    {
        StatusCode = statusCode;
    }

    private StatusCodeAndDtoWrapper(AppResponse dto, int statusCode, string message) : base(dto)
    {
        StatusCode = statusCode;
        if (dto.FullMessages == null)
            dto.FullMessages = new List<string>(1);
        dto.FullMessages.Add(message);
    }

    private StatusCodeAndDtoWrapper(AppResponse dto, int statusCode, ICollection<string> messages) : base(dto)
    {
        StatusCode = statusCode;
        dto.FullMessages = messages;
    }
}

注意用对象替换dto的基数(dto)应该没问题了。

我想到的最简单的方法是:

var result = new Item { Id = 123, Name = "Hero" };

return new JsonResult(result)
{
    StatusCode = StatusCodes.Status201Created // Status code here 
};

使用JsonResult响应的最基本版本是:

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

但是,这对您的问题没有帮助,因为您不能显式地处理自己的响应代码。

控制状态结果的方法是,你需要返回一个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);
}

注意以上两个例子都来自微软文档:格式化响应数据


额外的东西

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

让我们来确保你掌握了一些基本知识……

步骤1:配置服务

为了得到你的ASP。NET核心WebAPI响应一个JSON序列化对象以及完全控制状态代码,你应该首先确保你在你的ConfigureServices方法中包含了AddMvc()服务,通常在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()方法的副本。但是,我们通过定义每个服务来实现每个“默认”服务,而不是使用预先发布的模板。我已经在代码块中添加了存储库链接,或者你可以从GitHub存储库中查看AddMvc() ..

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


步骤2:创建Controller

我要给你们看一个非常简单的例子来解决你们的问题。

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-Type和Accept标头设置正确。在您的示例中(JSON),您将希望将其设置为application/ JSON。

如果你想让你的WebAPI默认响应JSON,不管请求头指定什么,你可以通过几种方式来做到这一点。

方法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.

方法2 我的首选方法是让WebAPI以所请求的格式响应所有请求。然而,如果它不接受所请求的格式,那么就会退回到默认格式(例如。JSON)

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

options.RespectBrowserAcceptHeader = true; // false by default

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

更多信息可以在.NET Web开发和工具博客中找到

我在这里找到了很棒的答案,我还尝试了这个返回语句,见StatusCode(任何你想要的代码),它工作了!!

return Ok(new {
                    Token = new JwtSecurityTokenHandler().WriteToken(token),
                    Expiration = token.ValidTo,
                    username = user.FullName,
                    StatusCode = StatusCode(200)
                });

请参考以下代码,您可以管理多个状态代码与不同类型的JSON

public async Task<HttpResponseMessage> GetAsync()
{
    try
    {
        using (var entities = new DbEntities())
        {
            var resourceModelList = entities.Resources.Select(r=> new ResourceModel{Build Your Resource Model}).ToList();

            if (resourceModelList.Count == 0)
            {
                return this.Request.CreateResponse<string>(HttpStatusCode.NotFound, "No resources found.");
            }

            return this.Request.CreateResponse<List<ResourceModel>>(HttpStatusCode.OK, resourceModelList, "application/json");
        }
    }
    catch (Exception ex)
    {
        return this.Request.CreateResponse<string>(HttpStatusCode.InternalServerError, "Something went wrong.");
    }
}