我正在寻找在我的. 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");
}

其他回答

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

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

控制器动作返回类型在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);
}

而不是使用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 !!!"));
    }

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

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)应该没问题了。