英文:
How to returned a typed single result from ASP.NET Core API using IResult?
问题
Background, 我想使用ASP.NET Core 7开发新的API,并使用控制器来实现最佳实践,以返回已定义类型的结果,以简化文档,例如:
如果我想从API返回已定义类型的结果,可以这样做:
[HttpGet()]
public ActionResult<List<Products>> GetAllProducts()
{
var beers = repository.GetAllProducts();
return beers;
}
但是,如果出于一致性原因,我想要返回并使用IResult的派生类之一,那么下面的方法将不起作用,因为Results需要两个返回类型:
[HttpGet()]
public Results<Products> GetAllProducts()
{
var beers = repository.GetAllProducts();
return beers;
}
当然,你可以像这样使用一个小技巧:
[HttpGet()]
public Results<Products, BadRequest> GetAllProducts()
{
var beers = repository.GetAllProducts();
return beers;
}
但这听起来有点奇怪。
如果我想要使用IResult,并且只想返回一个类型,那么建议使用哪种类型呢?或者是ActionResult<List
我觉得为了写更整洁的代码并跟上现代化的趋势,我想坚持使用基于IResult的类型,而不与IActionResult混合使用。
英文:
Background, I want to develop a new API using ASP.NET Core 7 and using controllers and I want to use best practices to return typed results to simplify the documentation for example.
If I want to return a typed result from an API, I can do:
[HttpGet()]
public ActionResult<List<Products>> GetAllProducts()
{
var beers = repository.GetAllProducts();
return beers;
}
but, my question is if I want to return and use one of the derived classes from IResult instead (for consistency reasons), then the following below will not work, because Results requires two return types.:
[HttpGet()]
public Results<Products> GetAllProducts()
{
var beers = repository.GetAllProducts();
return beers;
}
Sure, I could do a hack like this:
[HttpGet()]
public Results<Products,BadRequest> GetAllProducts()
{
var beers = repository.GetAllProducts();
return beers;
}
But that sounds a bit silly.
What is the recommended type to result if I want to use IResult and I only want to return one type? Or is ActionResult<List<Products>> the only option?
I feel that to get a bit more clean code and be modern that I want to stick with IResult based types and not mix with IActionResult.
答案1
得分: 1
这是您需要的吗?
[HttpGet()]
public IResult GetAllProducts()
{
var beers = repository.GetAllProducts();
return Results.Ok(beers);
}
英文:
Is this what you need
[HttpGet()]
public IResult GetAllProducts()
{
var beers = repository.GetAllProducts();
return Results.Ok(beers);
}
答案2
得分: 0
From ASP.NET Core 7, you can use typed HttpResult.
So you can specify in the action method signature the expected HTTP result :
using Microsoft.AspNetCore.Http.HttpResults;
public class FoosController
{
...
[HttpGet]
// When the action has one result type
// specify directly the result type
public Ok<List<Foo>> Get()
{
List<Foo> foos = ...
return TypedResult.Ok(foos);
}
[HttpGet("{id}")]
// When the action has several result types
// use the generic Results
public Results<Ok<Foo>, NotFound, BadRequest> Get(int id)
{
Foo? foo = ...
if(foo == null)
return TypedResult.NotFound();
return TypedResult.Ok(foo);
}
}
Actually, the action metadatas aren't correctly inferred from typed HttpResult Swashbuckle don't the generate the expected OpenApi schema. See this GitHub issue for more detail :
TypedResults metadata are not inferred for API Controllers
While waiting for a resolution, I do a operation filter to generate OpenApi response from HttpResults type and I wrapped it in a NuGet package :
Vernou.Swashbuckle.HttpResultsAdapter
You can add the package :
dotnet add package Vernou.Swashbuckle.HttpResultsAdapter
So you can register the filter :
var builder = WebApplication.CreateBuilder(args);
...
builder.Services.AddSwaggerGen(options =>
{
...
options.OperationFilter<Vernou.Swashbuckle.HttpResultsAdapter.HttpResultsOperationFilter>();
});
If you prefer, you can just copy/paste the filter file from the package repository :
HttpResultsOperationFilter.cs
英文:
From ASP.NET Core 7, you can use typed HttpResult.
So you can specify in the action method signature the expected HTTP result :
using Microsoft.AspNetCore.Http.HttpResults;
public class FoosController
{
...
[HttpGet]
// When the action has one result type
// specify directly the result type
public Ok<List<Foo>> Get()
{
List<Foo> foos = ...
return TypedResult.Ok(foos);
}
[HttpGet("{id}")]
// When the action has several result types
// use the generic Results
public Results<Ok<Foo>, NotFound, BadRequest> Get(int id)
{
Foo? foo = ...
if(foo == null)
return TypedResult.NotFound();
return TypedResult.Ok(foo);
}
}
Actually, the action metadatas aren't correctly inferread from typed HttpResult Swashbuckle don't the generate the expected OpenApi schema. See this GitHub issue for more detail :
TypedResults metadata are not inferred for API Controllers
While waiting for a resolution, I do a operation filter to generate OpenApi response from HttpResults type and I wrapped it in a NuGet package :
Vernou.Swashbuckle.HttpResultsAdapter
You can add the package :
dotnet add package Vernou.Swashbuckle.HttpResultsAdapter
So you can register the filter :
var builder = WebApplication.CreateBuilder(args);
...
builder.Services.AddSwaggerGen(options =>
{
...
options.OperationFilter<Vernou.Swashbuckle.HttpResultsAdapter.HttpResultsOperationFilter>();
});
If you prefer, you can just copy/paste the filter file from the package repository :
HttpResultsOperationFilter.cs
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论