如何在 asp.net core 中编写自定义 actionResult
Posted
技术标签:
【中文标题】如何在 asp.net core 中编写自定义 actionResult【英文标题】:How to write custom actionResult in asp.net core 【发布时间】:2021-01-26 21:15:45 【问题描述】:在 webApi2 中,我可以通过继承 IHttpActionResult 来编写自定义 ActionResult。
示例:
public class MenivaActionResult : IHttpActionResult
private readonly HttpRequestMessage _request;
private readonly ServiceResponseBase _response;
public MenivaActionResult(HttpRequestMessage request, ServiceResponseBase response)
_request = request;
_response = response;
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken token)
HttpResponseMessage httpresponseMessage = _response.Exception != null
? _request.CreateErrorResponse((HttpStatusCode)_response.HttpCode,
_response.Exception.Message+":"+_response.Exception.HelpCode)
: _request.CreateResponse((HttpStatusCode)_response.HttpCode, _response.Data);
return Task.FromResult(httpresponseMessage);
ServiceResponseBase 类对象包含来自服务层的所有异常和数据..
如何将此代码移植到 asp.net 核心。我试过了,但我不知道如何从 .net 核心中的 HttpRequestMessage 对象创建响应消息。 IActionResult 只有Task ExecuteResultAsync(ActionContext context)
方法。我如何修改此方法的响应
【问题讨论】:
【参考方案1】:这是一个例子:
public class TestResult
public Exception Exception get; set;
public object Data get; set;
public class TestActionResult : IActionResult
private readonly TestResult _result;
public TestActionResult(TestResult result)
_result = result;
public async Task ExecuteResultAsync(ActionContext context)
var objectResult = new ObjectResult(_result.Exception ?? _result.Data)
StatusCode = _result.Exception != null
? StatusCodes.Status500InternalServerError
: StatusCodes.Status200OK
;
await objectResult.ExecuteResultAsync(context);
ObjectResult
是当您从操作返回非IActionResult
时转换结果的类型。它将为您进行内容协商。
您也可以从ObjectResult
继承并设置要写入构造函数的状态码和数据。
更多关于 ASP.NET Core 中的内容协商:https://docs.microsoft.com/en-us/aspnet/core/mvc/models/formatting#content-negotiation
【讨论】:
但是我需要传递对象而不是简单的字符串,我需要使用默认的内容协商功能,因此无法将对象转换为任何形式的字符串表示形式,如 json 或 xml。 _request.CreateResponse((HttpStatusCode)_response.HttpCode, _response.Data);我的 webapi2 中的这一行会自动协商数据 @BinsonEldhose 查看我更新的示例。那将是ObjectResult
的工作。
很好的例子,但是像这样的自定义操作结果的文件夹结构呢?
你的意思是这个类的文件夹名称应该是什么?这取决于您和您的团队 :) 我通常使用 Results 文件夹。
如何对 TestActionResult 进行单元测试?我很想确保 ActionContext 被模拟并断言预期的结果;【参考方案2】:
尽管@juunas 的回答在技术上是正确的,但您真正尝试实现的是自定义错误处理。更好的方法是使用动作过滤器、中间件过滤器或单独的中间件来解耦这个逻辑(取决于你要覆盖什么范围)。
主要思想是控制器不应该负责处理异常。它应该返回具有 OK 状态的预期结果,或者说有问题(抛出异常)并委托给管道的其他部分来处理问题。
查看 SO:Error handling in ASP.NET Core 1.0 Web API (Sending ex.Message to the client) 示例。 Error Handling in ASP.NET Core doc 也可能有用。
【讨论】:
当然,您可以使用异常过滤器来实现同样的目的。【参考方案3】:为什么不直接使用 StatusCode 方法呢?像这样的例子:
public async Task<IActionResult> ExamleEndpoint()
// ... some code here which concatenates result string and selects a status code
var statusCode = HttpStatusCode.OK;
var message = "Some string response here but StatusCode also accepts Object value";
return StatusCode((int) statusCode, message);
【讨论】:
以上是关于如何在 asp.net core 中编写自定义 actionResult的主要内容,如果未能解决你的问题,请参考以下文章
在 Asp.net Core MVC 中定义自定义客户端验证规则
如何在 ASP.NET Core 控制器中返回自定义 HTTP 响应?
如何在 ASP.NET Core 的自定义 TagHelper 中呈现 Razor 模板?