如何从ASP.NET Core API中使用IResult返回一个类型化的单个结果?

huangapple go评论115阅读模式
英文:

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&lt;List&lt;Products&gt;&gt; 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&lt;Products&gt; GetAllProducts()
{
    var beers = repository.GetAllProducts();

    return beers;
}

Sure, I could do a hack like this:

[HttpGet()]  
public Results&lt;Products,BadRequest&gt; 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&lt;List&lt;Foo&gt;&gt; Get()
    {
        List&lt;Foo&gt; foos = ...
        return TypedResult.Ok(foos);
    }

    [HttpGet(&quot;{id}&quot;)]
    // When the action has several result types
    // use the generic Results
    public Results&lt;Ok&lt;Foo&gt;, NotFound, BadRequest&gt; 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 =&gt;
{
    ...
    options.OperationFilter&lt;Vernou.Swashbuckle.HttpResultsAdapter.HttpResultsOperationFilter&gt;();
});

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&lt;List&lt;Foo&gt;&gt; Get()
    {
        List&lt;Foo&gt; foos = ...
        return TypedResult.Ok(foos);
    }

    [HttpGet(&quot;{id}&quot;)]
    // When the action has several result types
    // use the generic Results
    public Results&lt;Ok&lt;Foo&gt;, NotFound, BadRequest&gt; 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 =&gt;
{
    ...
    options.OperationFilter&lt;Vernou.Swashbuckle.HttpResultsAdapter.HttpResultsOperationFilter&gt;();
});

If you prefer, you can just copy/paste the filter file from the package repository :
HttpResultsOperationFilter.cs

huangapple
  • 本文由 发表于 2023年4月10日 18:59:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/75976492.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定