我正在寻找在我的. 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中所做的那样。


当前回答

控制器动作返回类型在ASP。NET核心web API 02/03/2020

6分钟阅读 + 2

作者:斯科特·艾迪·林克

同步动作

[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<Product> GetById(int id)
{
    if (!_repository.TryGetProduct(id, out var product))
    {
        return NotFound();
    }

    return product;
}

异步操作

[HttpPost]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<Product>> CreateAsync(Product product)
{
    if (product.Description.Contains("XYZ Widget"))
    {
        return BadRequest();
    }

    await _repository.AddProductAsync(product);

    return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
}

其他回答

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

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

ASP。NET Core 2.0,从Web API(与MVC统一并使用相同的基类Controller)返回对象的理想方式是

public IActionResult Get()
{
    return new OkObjectResult(new Item { Id = 123, Name = "Hero" });
}

请注意,

它返回200个OK状态码(这是ObjectResult的OK类型) 它进行内容协商,即它将根据请求中的Accept报头返回。如果在请求中发送Accept: application/xml,它将以xml的形式返回。如果不发送任何内容,则默认为JSON。

如果需要发送特定的状态代码,则使用ObjectResult或StatusCode。两者都做同样的事情,并支持内容协商。

return new ObjectResult(new Item { Id = 123, Name = "Hero" }) { StatusCode = 200 };
return StatusCode( 200, new Item { Id = 123, Name = "Hero" });

或者更细粒度的ObjectResult:

 Microsoft.AspNetCore.Mvc.Formatters.MediaTypeCollection myContentTypes = new Microsoft.AspNetCore.Mvc.Formatters.MediaTypeCollection { System.Net.Mime.MediaTypeNames.Application.Json };
 String hardCodedJson = "{\"Id\":\"123\",\"DateOfRegistration\":\"2012-10-21T00:00:00+05:30\",\"Status\":0}";
 return new ObjectResult(hardCodedJson) { StatusCode = 200, ContentTypes = myContentTypes };

如果您特别希望以JSON形式返回,有几种方法

//GET http://example.com/api/test/asjson
[HttpGet("AsJson")]
public JsonResult GetAsJson()
{
    return Json(new Item { Id = 123, Name = "Hero" });
}

//GET http://example.com/api/test/withproduces
[HttpGet("WithProduces")]
[Produces("application/json")]
public Item GetWithProduces()
{
    return new Item { Id = 123, Name = "Hero" };
}

请注意,

两者都以两种不同的方式强制执行JSON。 两者都忽略了内容协商。 第一种方法使用特定的序列化器JSON (object)强制执行JSON。 第二种方法通过使用products()属性(这是一个ResultFilter)和contentType = application/json来实现同样的功能

在官方文档中阅读更多关于它们的信息。点击这里了解过滤器。

示例中使用的简单模型类

public class Item
{
    public int Id { get; set; }
    public string Name { get; set; }
}

我发现的最干净的解决方案是在Startup.cs中的ConfigureServices方法中设置以下内容(在我的情况下,我希望剥离TZ信息。我总是希望看到用户看到的日期时间)。

   services.AddControllers()
                .AddNewtonsoftJson(o =>
                {
                    o.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Unspecified;
                });

DateTimeZoneHandling选项有Utc、Unspecified、Local或RoundtripKind

我仍然想找到一种方法,能够在每个呼叫的基础上请求这一点。

类似的

  static readonly JsonMediaTypeFormatter _jsonFormatter = new JsonMediaTypeFormatter();
 _jsonFormatter.SerializerSettings = new JsonSerializerSettings()
                {DateTimeZoneHandling = DateTimeZoneHandling.Unspecified};

return Ok("Hello World", _jsonFormatter );

我从ASP转换。NET,在那里我使用了下面的helper方法

public static ActionResult<T> Ok<T>(T result, HttpContext context)
    {
        var responseMessage = context.GetHttpRequestMessage().CreateResponse(HttpStatusCode.OK, result, _jsonFormatter);
        return new ResponseMessageResult(responseMessage);
    }

而不是使用404/201状态代码使用enum

     public async Task<IActionResult> Login(string email, string password)
    {
        if (string.IsNullOrWhiteSpace(email) || string.IsNullOrWhiteSpace(password))
        { 
            return StatusCode((int)HttpStatusCode.BadRequest, Json("email or password is null")); 
        }

        var user = await _userManager.FindByEmailAsync(email);
        if (user == null)
        {
            return StatusCode((int)HttpStatusCode.BadRequest, Json("Invalid Login and/or password"));

        }
        var passwordSignInResult = await _signInManager.PasswordSignInAsync(user, password, isPersistent: true, lockoutOnFailure: false);
        if (!passwordSignInResult.Succeeded)
        {
            return StatusCode((int)HttpStatusCode.BadRequest, Json("Invalid Login and/or password"));
        }
        return StatusCode((int)HttpStatusCode.OK, Json("Sucess !!!"));
    }

请参考以下代码,您可以管理多个状态代码与不同类型的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.");
    }
}