Как сделать AJAX POST кросс-домен с пользовательскими заголовками

Я искал все вокруг, и я не могу найти окончательного ответа на этот вопрос.

Мне нужно выполнить AJAX POST и отправить пользовательские заголовки. Я полностью контролирую как клиентскую сторону script, так и службу на стороне сервера, поэтому, если мне нужно внести какие-либо изменения в обе стороны, чтобы выполнить эту работу, я могу внести эти изменения.

В настоящее время я использую jQuery, но если jQuery не может этого сделать, и мне нужно использовать другую библиотеку, которая тоже не проблема. В идеале я бы предпочел придерживаться одной библиотеки (jQuery), но я более чем счастлив использовать вторую, если она решает мою проблему.

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

$.ajax({
    type: 'POST',
    url: 'http://localhost:65079/TestHandler',
    crossDomain: true,
    data: myVariableOfData,
    dataType: 'json',
    beforeSend: function(xhr) {
        xhr.setRequestHeader('MessageId', 'abc123');
    },
    success: function(responseData, textStatus, messageId) {
        console.log("success");
    },
    error: function(responseData, textStatus, errorThrown) {
        console.log(textStatus);
        console.log(responseData);
        console.log(errorThrown);
    }
});

и, к сожалению, jQuery даже не пытается отправить запрос на сервер, однако, как только я удаляю заголовки, он отправляет запрос. Мне действительно нужны эти заголовки, поэтому любая помощь будет высоко оценена.

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

Ответ 1

Я не знаю, продолжаете ли вы искать способ сделать это. Это можно сделать. Вот пример обработчика CORS

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Api.Handlers
{
    /// <summary>
    /// 
    /// </summary>
    public class CorsHandler : DelegatingHandler
    {
        const string Origin = "Origin";
        const string AccessControlRequestMethod = "Access-Control-Request-Method";
        const string AccessControlRequestHeaders = "Access-Control-Request-Headers";
        const string AccessControlAllowOrigin = "Access-Control-Allow-Origin";
        const string AccessControlAllowMethods = "Access-Control-Allow-Methods";
        const string AccessControlAllowHeaders = "Access-Control-Allow-Headers";

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            bool isCorsRequest = request.Headers.Contains(Origin);
            bool isPreflightRequest = request.Method == HttpMethod.Options;

            if (isCorsRequest)
            {
                if (isPreflightRequest)
                {
                    HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
                    response.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First());

                    string accessControlRequestMethod = request.Headers.GetValues(AccessControlRequestMethod).FirstOrDefault();
                    if (accessControlRequestMethod != null)
                    {
                        response.Headers.Add(AccessControlAllowMethods, accessControlRequestMethod);
                    }

                    string requestedHeaders = string.Join(", ", request.Headers.GetValues(AccessControlRequestHeaders));
                    if (!string.IsNullOrEmpty(requestedHeaders))
                    {
                        response.Headers.Add(AccessControlAllowHeaders, requestedHeaders);
                    }

                    TaskCompletionSource<HttpResponseMessage> tcs = new TaskCompletionSource<HttpResponseMessage>();
                    tcs.SetResult(response);
                    return tcs.Task;
                }

                return base.SendAsync(request, cancellationToken).ContinueWith<HttpResponseMessage>(t =>
                {
                    HttpResponseMessage resp = t.Result;
                    resp.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First());
                    return resp;
                });
            }

            return base.SendAsync(request, cancellationToken);
        }
    }
}

Как только вы это добавите, зарегистрируйте обработчик в файле Global.asax внутри метода Application_Start

GlobalConfiguration.Configuration.MessageHandlers.Add(new CorsHandler());

Теперь вы можете отправить свои заголовки запросов. Надеюсь, это поможет. Это было протестировано с помощью Web API, MVC 4 и сайта из Google Chrome и Firefox.

Ответ 2

С риском полного звучания, как Siri, похоже, что вы ищете, как получить CORS для работы...

Вот несколько ресурсов, которые, надеюсь, помогут: