Оберните ответ API (ответ на проверку, ответ на исключение и ответ об успешном выполнении) с единообразием - PullRequest
0 голосов
/ 06 февраля 2020

Я пытаюсь вернуть согласованный ответ с аналогичной структурой, возвращаемой для всех запросов.

Объект, который я хочу вернуть, будет инкапсулирован в элемент Result.

Я хотел имеют одинаковую структуру во время:

  1. результат успеха
  2. проверка модели
  3. исключение

Я создал 3 отдельных middleware для этой цели.

Но в моем случае middleware для обёртывания responses обернул результат из exceptionc filter, а также ответы из ValidationFilter.

Вывод, который я получил во время исключения:

{
    "Result": {
        "Result": null,
        "StatusCode": 0,
        "Message": "Identification id Invalid!",
        "Errors": null
    },
    "StatusCode": 500,
    "Message": null,
    "Errors": null
}

Вывод во время исключения должен выглядеть следующим образом:

{
    "Result": null,
    "StatusCode": 0,
    "Message": "Identification id Invalid!",
    "Errors": null
}

Аналогично, у меня та же проблема для модели ошибка валидации:

{
    "Result": {
        "Result": null,
        "StatusCode": 200,
        "Message": "{\"Errors\":[{\"FieldName\":\"State\",\"Message\":\"'State' must not be empty.\"}]}",
        "Errors": "Invalid Request"
    },
    "StatusCode": 200,
    "Message": null,
    "Errors": null
}

Класс Wrapper

public class ValidationFilter : IAsyncActionFilter
{
    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        if (!context.ModelState.IsValid)
        {
            var errorsInModelState = context.ModelState
                .Where(x => x.Value.Errors.Count > 0)
                .ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Errors.Select(x => x.ErrorMessage)).ToArray();

            var errorResponse = new ErrorResponse();

            foreach (var error in errorsInModelState)
            {
                foreach (var subError in error.Value)
                {
                    var errorModel = new ErrorModel
                    {
                        FieldName = error.Key,
                        Message = subError
                    };

                    errorResponse.Errors.Add(errorModel);
                }
            }
            var responseModel = new ApiResponseModel("Invalid Request", JsonConvert.SerializeObject(errorResponse), (int)HttpStatusCode.OK);
            context.Result = new ObjectResult(responseModel);

            return;
        }

        await next();

        // after controller
    }
}

ApiExceptionFilter

    public class ApiExceptionFilter : ExceptionFilterAttribute
{
    public override void OnException(ExceptionContext context)
    {
        ApiResponseModel responseModel = null;
        if (context.Exception is ApiException)
        {
            // handle explicit 'known' API errors
            var ex = context.Exception as ApiException;
            context.Exception = null;
            responseModel = new ApiResponseModel(ex.Message);
            context.HttpContext.Response.StatusCode = ex.StatusCode;
        }
        else
        {
            var msg = "An unhandled error occurred.";
            string stack = null;

            responseModel = new ApiResponseModel(msg);


            context.HttpContext.Response.StatusCode = 500;

            // handle logging here
        }

        // always return a JSON result
        context.Result = new JsonResult(responseModel);

        base.OnException(context);
    }
}

Как можно объединить все фильтры в одном коде и обработать все ответы из одного фильтра, сохранив согласованность во всех ответах?

...