Как вернуть BadRequestObjectResult из метода Invoke - PullRequest
0 голосов
/ 22 апреля 2019

Я разрабатываю API, который первоначально проверяет заголовок Accept из запроса https, а затем отвечает через промежуточное ПО. Я добавил логику для проверки заголовка Accept в методе Invoke, как показано ниже. Как вернуть неверный объект запроса, если результатом проверки (сравнения строк) является false.

//Invoke method 
public async Task<ObjectResult> Invoke(HttpContext context)
{
   bool result = context.Request.Headers["Accept"].ToString() == 
   "app/version.abc-ghi-api.v";
   if (result == true)
   {
     await  _next(context);   
   }
   ObjectResult objectResult = await 
   Error.GenerateErrorMessage("Accept header validation 
   failed", Log.Logger);
   return objectResult;  
}

//Error class
public class Error
{
    public async static Task<ObjectResult> Error(string message, logger log)
    {
       //logic for creating the payload
       return new BadRequestObjectResult(errorMessagePayload)
    }
}

//Startup class configure method
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
     app.UseMiddleware<AcceptHeaderMiddleware>();
     if (env.IsDevelopment())
     {   
         app.UseDeveloperExceptionPage();
     }
     else
     {          
         app.UseHsts();
     }

     app.UseMvc();
}

Я ожидаю badObjectResult (когда проверка не пройдена) в качестве ответа, но я получаю ответ 200 OK и пустое тело ответа.

1 Ответ

1 голос
/ 22 апреля 2019

Типы IActionResult используются только в конвейере MVC.Как часть этого конвейера, объекты результата из действий или фильтров MVC затем выполняются для создания фактического ответа на HttpResponse объект .

Это, однако, означает, что вы фактически не можете использовать действиеобъекты результата за пределами конвейера MVC.Поэтому, если у вас есть специальное промежуточное программное обеспечение, вы не сможете использовать эти результаты, поскольку они не будут обрабатываться конвейером MVC (технически вы могли бы выполнить результаты самостоятельно, но я бы не рекомендовал делать это).это).

Так что вместо этого вам придется установить результат самостоятельно.Если вы просто хотите установить какой-то код состояния (сбой), это очень легко сделать:

public async Task<ObjectResult> Invoke(HttpContext context)
{
    bool result = context.Request.Headers["Accept"].ToString() == "app/version.abc-ghi-api.v";
    if (result)
    {
        await  _next(context);   
    }
    else
    {
        context.Result.StatusCode = 500;
    }
}

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

Поэтому вместо того, чтобы делать это в пользовательском промежуточном программном обеспечении, я бы предложил вам сделать это внутри фильтра MVC.Как упоминалось выше, фильтры работают как часть конвейера MVC, поэтому они работают только с промежуточным программным обеспечением MVC.Это означает, что вы не сможете таким образом защитить свои статические файлы, но обычно это не так уж и важно.

В вашем случае, поскольку вы хотите авторизовать клиента через заголовок HTTP, япредложил бы вам создать фильтр авторизации :

public class AcceptHeaderAuthorizationFilter : IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        bool result = context.HttpContext.Request.Headers["Accept"].ToString() == "app/version.abc-ghi-api.v";
        if (!result)
        {
            var result = new Error.GenerateErrorMessage("Accept header validation failed", Log.Logger);
            context.Result = result;
        }
    }
}

Теперь он использует конвейер MVC, так что вы можете использовать IActionResult объекты.Так как вы устанавливаете результат в фильтре авторизации, вы также закорачиваете оставшийся конвейер, поэтому впоследствии ничего не будет выполнено.Выполнение остановится и немедленно выдаст ваш результат.


Последнее замечание: заголовок Accept имеет очень специфический вариант использования, который предназначен для согласования содержимого.Это означает, что когда вы устанавливаете какой-либо пользовательский тип контента, сервер должен возвращать результат с таким типом контента.Использование его в целях авторизации здесь не совсем подходит.

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