.NET 7 中的 HttpResult 接口
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了.NET 7 中的 HttpResult 接口相关的知识,希望对你有一定的参考价值。
.NET 7 中的 HttpResult 接口
Intro
在前面的文章中,我们提到了 .NET 7 引入了 Endpoint Filter 来支持 Endpoint 的过滤器,有了这个接口就想着把之前的统一 API response 的 filter 改造一下支持 endpoint filter,然而这个一直等到了 .NET 7 Preview 7 才得以实现,在 .NET 7 Preview 7 中引入了一些接口使得我们可以匹配 HttpResult
的类型
HttpResult Interface
.NET 6 开始引入了 Minimal API, 但是要匹配一系列 IResult 相关的 response 比如 Results.Ok, Results.NotFound 会比较困难,在 .NET 7 有了一些改进
在 .NET 7 Preview 3 中,出于方便单元测试的考虑,开放了一些 HttpResult
的类型比如:OkObjectHttpResult
/NotFoundHttpResult
等,但是始终没有一个类似于 MVC 里的 ObjectResult
一样的类型,使得我们如果想要匹配 response 的类型就会很麻烦,终于在 .NET 7 Preview 7,引入了一系列的接口,我们可以通过这些接口进行模式匹配来获取这些 HttpResult
中的 Value
/StatusCode
等等,新增加的接口如下:
Microsoft.AspNetCore.Http.IContentTypeHttpResult
Microsoft.AspNetCore.Http.IFileHttpResult
Microsoft.AspNetCore.Http.INestedHttpResult
Microsoft.AspNetCore.Http.IStatusCodeHttpResult
Microsoft.AspNetCore.Http.IValueHttpResult
Microsoft.AspNetCore.Http.IValueHttpResult<TValue>
可以参考 PR:https://github.com/dotnet/aspnetcore/pull/42385/files
如果我们想要匹配 response 的返回值就可以使用 IValueHttpResult
来匹配,比如:
if (result is IValueHttpResult valueHttpResult)
return valueHttpResult.Value;
也可以使用 IStatusCodeHttpResult
来匹配 response status
if (result is IStatusCodeHttpResult statusCodeResult)
return statusCodeResult.StatusCode;
ApiResultFilter
实现了一个简单的统一 response 的 ApiResultFilter
,在原来的基础上增加了 EndpointFilter
的支持,实现如下:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class ApiResultFilter : Attribute
, IResultFilter, IExceptionFilter
#if NET7_0_OR_GREATER
, IEndpointFilter
#endif
public void OnResultExecuting(ResultExecutingContext context)
if (context.Result is ObjectResult Value: not Result objectResult)
var result = new Result<object>()
Data = objectResult.Value,
Status = HttpStatusCode2ResultStatus(objectResult.StatusCode)
;
objectResult.Value = result;
public void OnResultExecuted(ResultExecutedContext context)
public void OnException(ExceptionContext context)
var result = Result.Fail(context.Exception.ToString(), ResultStatus.ProcessFail);
context.Result = new ObjectResult(result) StatusCode = 500 ;
#if NET7_0_OR_GREATER
public async ValueTask<object> InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next)
try
var result = await next(context);
if (result is Result or ObjectResult Value: Result or IValueHttpResult Value: Result )
return result;
if (result is ObjectResult Value: not Result objectResult)
return new Result<object>()
Data = objectResult.Value, Status = HttpStatusCode2ResultStatus(objectResult.StatusCode)
;
if (result is IValueHttpResult Value: not Result valueHttpResult)
var status = result is IStatusCodeHttpResult statusCodeHttpResult
? HttpStatusCode2ResultStatus(statusCodeHttpResult.StatusCode)
: HttpStatusCode2ResultStatus(200);
return new Result<object>() Data = valueHttpResult.Value, Status = status ;
return new Result<object>()
Data = result, Status = HttpStatusCode2ResultStatus(context.HttpContext.Response.StatusCode)
;
catch (Exception ex)
return Result.Fail(ex.ToString(), ResultStatus.ProcessFail);
#endif
private static ResultStatus HttpStatusCode2ResultStatus(int? statusCode)
statusCode ??= 200;
var status = ResultStatus.Success;
if (Enum.IsDefined(typeof(ResultStatus), statusCode.Value))
status = (ResultStatus)statusCode.Value;
if (status == ResultStatus.None)
status = ResultStatus.Success;
return status;
下面看一个使用的示例:
var app = WebApplication.Create(args);
app.Map("/Hello", () => "Hello Minimal API!")
.AddEndpointFilter<ApiResultFilter>();
app.Map("/HelloV3", () => Results.Ok(new Name = "test" ))
.AddEndpointFilter<ApiResultFilter>();
app.Map("/HelloV4", () => Results.Ok(Result.Success(new Name = "test" )))
.AddEndpointFilter<ApiResultFilter>();
await app.RunAsync();
访问一个直接返回一个字符串的接口:
访问返回一个 IResult
的接口
访问返回一个 ResultModel
的 API
使用控制器 API 示例:
[Route("api/[controller]")]
public class ValuesController: ControllerBase
[HttpGet("[action]")]
public IActionResult Test()
return Ok(new Name = "Amazing .NET" );
API response 示例:
References
https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-7-preview-7/#new-httpresults-interfaces
https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-7-preview-3/#improved-unit-testability-for-minimal-route-handlers
https://github.com/dotnet/aspnetcore/issues/41470
https://github.com/dotnet/aspnetcore/issues/42187
https://github.com/dotnet/aspnetcore/pull/42385/files
https://github.com/WeihanLi/WeihanLi.Web.Extensions/tree/dev/samples/WeihanLi.Web.Extensions.Samples
以上是关于.NET 7 中的 HttpResult 接口的主要内容,如果未能解决你的问题,请参考以下文章