Формат FilterAttribute результат, используя шаблон стратегии в ASP. NET Core - PullRequest
0 голосов
/ 11 апреля 2020

Я создал фильтр действий для возврата пользовательского результата в ActionFilterAttribute, используя context.result:

public class ResultApi : ActionFilterAttribute
{
    private readonly ResposeFormat resposeFormat;

    public ResultApi(ResposeFormat resposeFormat)
    {
        this.resposeFormat = resposeFormat;
    }
    public override void OnResultExecuting(ResultExecutingContext context)
    {
        resposeFormat.ContextResult(context);
        base.OnResultExecuting(context);
    }
}

Я использую шаблон стратегии для форматирования результата:

public abstract class ResposeFormat
{
    public abstract void ContextResult(ResultExecutingContext context);
}

И, вот различные реализации моего Formatter:

OkResult:

public abstract class OkResultFormatter : ResposeFormat
{
    public override void ContextResult(ResultExecutingContext context)
    {
        if (context.Result is OkResult okResult)
            context.Result = new JsonResult(new ReturnResult(true, StatusCode.Success)) { StatusCode = okResult.StatusCode };
    }
}

BadRequestResult:

public abstract class BadRquestObjectresultFormatter : ResposeFormat
{
    public override void ContextResult(ResultExecutingContext context)
    {
        if (context.Result is BadRequestObjectResult badRequestObjectResult)
        {
            var message = badRequestObjectResult.Value.ToString();
            if (badRequestObjectResult.Value is SerializableError errors)
            {
                var errorMessages = errors.SelectMany(p => (string[])p.Value).Distinct();
                message = string.Join(" | ", errorMessages);
            }
            context.Result = new JsonResult(new ReturnResult(false, StatusCode.BadRequest, message)) { StatusCode = badRequestObjectResult.StatusCode };
        }
    }
}

Когда я передаю context в resposeFormat.ContextResult(context);, я хочу, чтобы он нашел тип запроса и использовал OkResultFormatter или BadRquestObjectresultFormatter.

Как я могу это сделать?

1 Ответ

1 голос
/ 11 апреля 2020

Вам нужно немного изменить вещи.

Прежде всего, вы должны добавить абстрактное свойство get-only к вашему ResultTypeToFormat, чтобы определить, какой тип ObjectResult должен обрабатывать каждая реализация:

public abstract class ResponseFormatter
{
    public abstract Type ResultTypeToFormat { get; }

    public abstract void ContextResult(ResultExecutingContext context);
}

И, соответственно, вы должны изменить реализации, как показано ниже:

public class OkResultFormatter : ResponseFormatter
{
    public override Type ResultTypeToFormat => typeof(OkObjectResult);

    public override void ContextResult(ResultExecutingContext context)
    {
        context.Result = new JsonResult(new ReturnResult(HttpStatusCode.OK));
    }
}

public class BadRequestResultFormatter : ResponseFormatter
{
    public override Type ResultTypeToFormat => typeof(BadRequestObjectResult);

    public override void ContextResult(ResultExecutingContext context)
    {
        // Perform other bad request stuff here ...
        context.Result = new JsonResult(new ReturnResult(HttpStatusCode.BadRequest));
    }
}

С этими изменениями теперь вы должны зарегистрировать все средства форматирования результатов в вашем контейнере DI следующим образом:

services.AddScoped<ResponseFormatter, OkResultFormatter>();
services.AddScoped<ResponseFormatter, BadRequestResultFormatter>();

Наконец, вы можете динамически форматировать результаты в своем Атрибуте фильтра :

public class CustomResultFilterAttribute : ActionFilterAttribute
{
    private readonly IEnumerable<ResponseFormatter> _responseFormatters;

    public CustomResultFilterAttribute(IEnumerable<ResponseFormatter> responseFormatters)
    {
        _responseFormatters = responseFormatters;
    }

    public override void OnResultExecuting(ResultExecutingContext context)
    {
        Type resultType = context.Result.GetType();

        ResponseFormatter appropriateFormatter = _responseFormatters
            .Single(formatter => formatter.ResultTypeToFormat == resultType);

        appropriateFormatter.ContextResult(context);
    }
}

Вот также пример проекта в Github: Пример проекта

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...