API 控制器的通用 ActionResult 返回类型

Ree*_*eed 3 c# .net-core asp.net-core asp.net-core-webapi

我有该GetProducts()方法的以下用例。

好的路径:返回产品类型的数组: Product[]

错误路径:返回 500 的状态代码和描述性字符串错误消息。

<?Type?>下面是我自己的标记,用于这篇文章)

[Route("api/[controller]/[action]")]
[ApiController]
public class ProductsController : ControllerBase
{
    [HttpGet]
    public ActionResult<?Type?> GetProducts()
    {
        try
        {
            Product[] products = DataAccess.GetProductsFromDb();
            return products;
        }
        catch 
        {
            Response.StatusCode = 400;
            return "Error retrieving products list"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法可以声明一个泛型类型或两种类型的操作结果,以便它可以工作?

Art*_*tak 6

您可以ActionResult<Product[]>按照自己的意愿返回。不过,对于错误场景,您可以使用StatusCode()辅助方法返回错误消息,如下所示:

[Route("api/[controller]/[action]")]
[ApiController]
public class ProductsController : ControllerBase
{
    [HttpGet]
    public ActionResult<Product[]> GetProducts()
    {
        try
        {
            Product[] products = DataAccess.GetProductsFromDb();
            return products;
        }
        catch 
        {
            return StatusCode(500, "Error retrieving products list");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


nel*_*ran 5

您将返回一个 IActionResult。我强烈建议制作也是异步的。以下是通过控制器方法返回任何内容的方法:

[Route("api/{controller}")]
public class ProductsController : Controller
{
    [HttpGet]
    public async Task<IActionResult> GetProducts()
    {
        var products = await DataAccess.GetProductsFromDb();
        if (products is null)
        {
            return NotFound("Item not found!");
        }
        else
        {
            return Ok(products);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意抽象类中的Okand NotFoundare 方法,Controller它允许您返回任何您想要的对象,或者根本不返回任何对象。

我强烈建议您在继续使用 .net core 之前快速查看 Visual Studio 中的示例项目模板,或者如果您正在dotnet new mvc终端中运行的另一个 IDE 中进行开发。

如果你想处理一个异常,你应该在最低级别处理它。假设 GetProductsFromDb() 是最低级别并且您没有服务层(您以后会后悔这个设计选择!),您将尝试/捕获。

[Route("api/{controller}")]
public class ProductsController : Controller
{
    [HttpGet]
    public async Task<IActionResult> GetProducts()
    {
        Products[] products;
        try
        {
            products = await DataAccess.GetProductsFromDb();
        }
        catch(Exception e)
        {
            Log.Error(e, "Unable to receive products");
            return InternalServerError("Unable to retrieve products, please try again later");
        }
        if (!products.Any())
        {
            return NotFound("No products were found");
        }
        else
        {
            return Ok(products);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在大多数情况下,速度并不比稳定性更重要,在开发的这个阶段肯定不是。捕获异常的成本在如此高的级别上是微不足道的,特别是因为您的数据库调用将比捕获单个异常的开销慢几个数量级。