Заголовки ответов ASP.NET Core API не находятся в ожидаемом месте - PullRequest
0 голосов
/ 08 февраля 2019

У меня есть ASP.NET Core API, который добавляет два заголовка к своему ответу callback_uri и redirect_uri.

Странная вещь (для меня) состоит в том, что в моем вызове AJAX к службе,Заголовки являются частью данных JSON в виде массива заголовков, а не самого объекта request.Я не могу использовать jqxhr.getResponseHeader(...) и поэтому должен вручную запрашивать массив заголовков в данных ответа.

Поскольку StatusCode также является частью данных, это означает, что мой обратный вызов AJAX всегда вызывается, даже когда я 'm тестирование 400 неправильных ответов на запросы, что делает тестирование менее простым.

Действие контроллера Web API:

[HttpGet, Route("Authenticate")]
public HttpResponseMessage Authenticate(string applicationId)
{
    HttpResponseMessage response;

    if(!_security.IsApplicationIdValid(applicationId))
    {
        response = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest);

        response.ReasonPhrase = ErrorMessages.INVALID_APPLICATION_ID;

        return response;
    }

    IAuthenticationProvider authProvider = _security.GetAuthenticationProvider();

    response = new HttpResponseMessage(System.Net.HttpStatusCode.Redirect);

    response.Headers.Add(HeaderKeyNames.CALLBACK_URI_KEY_NAME, authProvider.GetCallbackUrl());

    response.Headers.Add(HeaderKeyNames.AUTHENTICATION_SERVICE_REDIRECT_URI_KEY_NAME, authProvider.GetUrl());

    return response;
}

Код AJAX:

var settings = {

    data: { "applicationId": applicationId },
    success: successCallback, // at the moment just writes to console
    error: errorCallback, // at the moment just writes to console
    method: "GET"
};

$.ajax(url, settings);

Я что-то не так делаю на стороне сервера?

Ответы [ 3 ]

0 голосов
/ 08 февраля 2019

Вы можете использовать комбинацию ResultFilters и ServiceFilterAttribute для добавления пользовательских заголовков.Это особенно полезно, потому что:

  1. ServiceFilter позволяет вам иметь доступ к DI в вашем ResultFilter.
  2. Вы можете применить его как Attribute в нужных вам действиях
  3. Вы можете проверить это.

Соединить все вместе:

  1. Создание пользовательского класса фильтра результатов
public class CustomHeadersResultFilter : IResultFilter
{
    private readonly IMyService _myService;

    public CustomHeadersResultFilter(IMyService myService)
    {
        _myService = myService;
    }

    public void OnResultExecuting(ResultExecutingContext context)
    {
        context.HttpContext.Response.Headers.Add("my-header", _myService.GetData());

        // if under CORS, this need to be added otherwise you can't read the headers using xhr.getResponseHeader('my-header')
        context.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "my-header");
    }

    public void OnResultExecuted(ResultExecutedContext context)
    {
        // can't add headers here, since it's too late in the pipeline
    }
}
Зарегистрируйте его в своем Startup.ConfigureServices
services.AddTransient<IMyService, MyService>();

// our custom result filter
services.AddTransient<CustomHeadersResultFilter>();
Примените атрибут в действии, которое вы хотите вернуть пользовательские заголовки
[HttpGet("{id}")]
[ServiceFilter(typeof(CustomHeadersResultFilter))]
public ActionResult Get(string id)
{
    if (id == "something-bad")
    {
        return BadRequest("invalid application id");
    }

    // return a 200 Ok. Check the other types if you want something different
    return Ok();
}

Тестируя все это в отдельном веб-приложении, выполняя запрос ajax к API, вы можетеполучить доступ к заголовкам:

<script>

    var settings = { method: "GET" };

    $.ajax('http://localhost:61284/api/values/test', settings)
        .done(function (data, textStatus, xhr) {
            alert(xhr.getResponseHeader('my-header'));
        })
        .fail(function () {
            alert("error");
        });

</script>
0 голосов
/ 09 февраля 2019

Что вы делаете, это создаете объект HttpResponseMessage, сериализуете его в json и затем возвращаете его.
Именно поэтому заголовки находятся в содержимом json, а не в ответе http.

Что вы можете сделать, это что-то вроде этого:

[HttpGet, Route("Authenticate")]
public IActionResult Authenticate(string applicationId)
{

    if(!_security.IsApplicationIdValid(applicationId))
    {
        return BadRequest(ErrorMessages.INVALID_APPLICATION_ID);
    }

    IAuthenticationProvider authProvider = _security.GetAuthenticationProvider();

    this.Response.Headers.Add(HeaderKeyNames.CALLBACK_URI_KEY_NAME, authProvider.GetCallbackUrl());

    this.Response.Headers.Add(HeaderKeyNames.AUTHENTICATION_SERVICE_REDIRECT_URI_KEY_NAME, authProvider.GetUrl());

    return StatusCode(302);
}
0 голосов
/ 08 февраля 2019

Добавьте заголовки следующим образом: (ofc измените тип при необходимости или определите свой собственный)

response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");

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