【问题标题】:Convert ASP.NET Core ActionResult<T> object to another type in a filter将 ASP.NET Core ActionResult<T> 对象转换为过滤器中的另一种类型
【发布时间】:2020-03-06 07:10:50
【问题描述】:

我有一个通用的 Result&lt;T&gt; 类型,我在业务级服务中使用它来返回结果。此类型包括具有实际值 (public T Value {get;}) 的属性以及指示 Success、NotFound、ValidationError 或其他选项的状态属性。

在 API 控制器中,我可以评估服务调用的结果并返回适当的 ActionResult,例如 NotFoundOkBadRequest

我可以在方法中手动做我想做的事

public ActionResult<Result<Customer>> GetCustomer(int id)
{
    Result<Customer> result = _someService.GetGetCustomer(id);
    if (result.Status == ResultStatus.NotFound) return NotFound();
    if (result.Status == ResultStatus.Invalid)
    {
        foreach (var error in result.ValidationErrors)
        {
            ModelState.AddModelError(error.Key, error.Value);
        }
        return BadRequest(ModelState);
    }

    return Ok(result.Value);
}

Example based on source here

但我希望能够在 ActionFilter 中执行此操作。

问题是我在弄清楚如何转换值方面没有取得多大成功,因为我希望过滤器适用于任何类型的T。一些伪代码可能会有所帮助:

[TranslateResultToHttp]
public ActionResult<Result<Customer>> GetCustomer(int id)
{
  Result<Customer> result = _someService.GetCustomer(int id);

  return Ok(result);
}

在我的TranslateResultToHttpAttribute 中,我需要获取结果,查看它的值,如果真的没问题,我会用Customer 替换Result&lt;Customer&gt;。但如果它是 NotFound,我会返回 NotFound,等等。

问题是过滤器不知道 Result&lt;T&gt; 可能是什么 T,所以我很难解压结果以获取其值等。

【问题讨论】:

  • 嗯,您是否考虑过自定义操作结果类型而不是过滤器?
  • 不,这有帮助吗?我仍然需要以某种方式从该操作结果类型转换为另一种类型(NotFoundResult、OkResults 等)。
  • 对,如果您想使用这些类型,那么它可能无济于事。虽然自定义的可能会使用这些结果用于根据需要编写结果的服务.. 只是在这里大声思考,不确定这是否真的有效:\
  • 还是将Result转换为IActionResult的扩展方法? :)
  • 您可以将 Result 类型设为 IActionResult 并直接使用它。或者您返回一个ObjectResult&lt;Result&lt;T&gt;&gt;,然后您可以在结果过滤器中更新结果。

标签: c# asp.net-core filter action-filter


【解决方案1】:

假设您的 Result&lt;T&gt; 类型具有包含纯状态的非泛型基接口,您可以直接返回结果,获得隐式对象结果。然后你可以实现一个结果过滤器来更新状态码:

public interface IResult
{
    int Result { get; set; } // could of course be something else
}

public class UpdateResultFilter : IResultFilter
{
    public void OnResultExecuting(ResultExecutingContext context)
    { }

    public void OnResultExecuted(ResultExecutedContext context)
    {
        if (context.Result is ObjectResult objectResult && objectResult.Value is IResult result)
        {
            // update status on object result
            objectResult.StatusCode = result.Status;
        }
    }
}

最后,这与返回 NotFoundResultBadRequestResult 之类的特定结果相同,因为这些只是带有预定义状态代码的 StatusCodeResults

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-23
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多