Преобразовать ASP. NET Core ActionResult <T>объект в фильтр другого типа - PullRequest
1 голос
/ 06 марта 2020

У меня есть обобщенный тип c Result<T>, который я использую в своих службах бизнес-уровня для возврата результатов. Этот тип включает свойство с фактическим значением (public T Value {get;}), а также свойство состояния, которое указывает Успех, NotFound, ValidationError или другие параметры.

В контроллере API я могу оценить результат вызов службы и возврат соответствующего ActionResult, например NotFound или Ok или BadRequest.

. Я могу вручную делать то, что хочу, в методе

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);
}

На основе примера по источнику здесь

но я бы хотел вместо этого сделать это из ActionFilter.

Проблема в том, что у меня нет большого успеха, чтобы понять, как разыграть значение, так как я хочу, чтобы фильтр работал для любого вида T. Некоторый псевдокод может помочь:

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

  return Ok(result);
}

В моем TranslateResultToHttpAttribute мне нужно было бы взять полученный результат, посмотреть на его значение, и если бы оно действительно было ОК, я бы заменил Result<Customer> только на Customer. Но если бы это был NotFound, я бы возвратил NotFound и т. Д. c.

. Проблема в том, что фильтр не знает, каким может быть T Result<T>, поэтому мне сложно распаковать результат чтобы получить его значение, et c.

1 Ответ

0 голосов
/ 06 марта 2020

Предполагая, что ваш тип Result<T> имеет базовый интерфейс не-общего c, который содержит чистый статус, вы можете просто вернуть результат напрямую, получив неявный результат объекта. И затем вы можете реализовать фильтр результатов для обновления кода состояния:

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;
        }
    }
}

В конце концов, это то же самое, что возвращать указанные c результаты, такие как NotFoundResult или BadRequestResult, потому что они просто StatusCodeResult с с предопределенным кодом состояния.

...