Mvc webapi перекрестная доменная почта
Возможный дубликат:
CORS с WebAPI для XmlHttpRequest
Я пытаюсь реализовать кросс-доменную запись ajax в моем проекте webApi. У меня было немного проблем с этим:
1. Я всегда получал 204 ошибки до тех пор, пока не изменил действие webapi из
public void submit(Submission model)
в
public bool submit(Submission model)
не знаю почему, но теперь я получаю статус 200 OK
2. Все еще мой обратный вызов об ошибке активации ajax.
3. Давным-давно я решил такую ошибку междоменной проводки, добавив
HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
к моему контроллеру. Но теперь в webApi я присущ : ApiController
, и этот трюк не работает. Показывает мне компилятор Error an object reference is required for the non-static field, method, or property"System.Web.HttpContext.Response.get"
Я попытался отправить сообщение через dataType: 'JSONP'
, но я получил нулевую модель.
Вот запрос Javascript:
var model = {
"type": $("#model-type").val(),
"subject": $("#subject-text").val(),
"body": $("#body-text").val()
};
$.ajax({
type: "POST",
dataType: 'JSONP',
url: $("#submit-url").val(),
data: model,
success: function () {
alert("Succesfully submitted");
},
error: function () {
alert("Error...");
}
});
Что я делаю неправильно?
решаемые
Спасибо всем за то, что помогли мне. Я нашел решение в одной из ссылок комментариев. Я использовал следующий подход, который я считаю довольно простым.
Источник:
Внедрение поддержки CORS в веб-API ASP.NET
Что я сделал:
1. Создал новый класс в моем проекте: CorsHandler.cs
и просто скопировал следующий код:
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";
protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
bool isCorsRequest = request.Headers.Contains(Origin);
bool isPreflightRequest = request.Method == HttpMethod.Options;
if (isCorsRequest)
{
if (isPreflightRequest)
{
return Task.Factory.StartNew(() =>
{
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);
}
return response;
}, cancellationToken);
}
else
{
return base.SendAsync(request, cancellationToken).ContinueWith(t =>
{
HttpResponseMessage resp = t.Result;
resp.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First());
return resp;
});
}
}
else
{
return base.SendAsync(request, cancellationToken);
}
}
}
- Открыл мой
Global.asax
и изменил Application_Start
:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
GlobalConfiguration.Configuration.MessageHandlers.Add(new CorsHandler());
}
Обратите внимание на последнюю строку в действии.
Этот подход совместим с MVC3 и .NET 4.0. Отлично работает, теперь я могу обрабатывать обратные вызовы "success" и "error" в ajax.
Ответы
Ответ 1
Ответы на ваши вопросы соответственно:
- Статус 204 не является ошибкой, что означает, что контент не возвращается, но все хорошо. Здесь определение 204 в RFC2616
10.2.5 204 Без содержания
Сервер выполнил запрос, но ему не нужно возвращать сущность-тело и может захотеть вернуть обновленную метаинформацию. ответ МОЖЕТ включать новую или обновленную метаинформацию в форме сущности-заголовки, которые, если они ДОЛЖНЫ быть связаны с запрошенный вариант.
Если клиент является пользовательским агентом, он НЕ ДОЛЖЕН изменять вид своего документа от того, что вызвало отправку запроса. Этот ответ прежде всего предназначенные для того, чтобы позволить ввод действий без вызвав изменение активного просмотра документа агента, хотя любая новая или обновленная метаинформация ДОЛЖНА применяться к документу в настоящее время в активном режиме пользовательского агента.
Ответ 204 НЕ ДОЛЖЕН включать тело сообщения и, следовательно, всегда завершается первой пустой строкой после полей заголовка.
-
Не могли бы вы сформулировать, какую ошибку вы встретили? Веб-API ASP.NET в настоящее время не имеет форматирования JSONP. Здесь реализована реализация третьей части:
-
В Web API способ, которым вы ссылаетесь на ответ, не через HttpContext. Существует несколько способов доступа.
Первым вариантом является непосредственное определение действия HttpResponse.
public HttpResponseMessage Get(int id)
{
var response = this.Request.CreateResponse();
response.StatusCode = HttpStatusCode.OK;
response.Headers.Add("Access-Control-Allow-Origin", "*");
return response;
}
Второй вариант - использовать ActionFilter:
// define action filter for cross domain
public class CrossDomainActionFilter : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
bool needCrossDomain = true;
if (needCrossDomain)
{
actionExecutedContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
}
base.OnActionExecuted(actionExecutedContext);
}
}
// At Controller
// GET api/values/5
[CrossDomainActionFilter]
public string Get(int id)
{
return "value";
}
Последний вариант - использовать MessageHandler:
public class CrossDomainMessageHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
response.Headers.Add("Access-Control-Allow-Origin", "*");
return response;
}
}
Ответ 2
Если вы хотите отправить информацию в другой домен из ajax, тогда вам нужно использовать jsonp (обратите внимание, что это работает только с запросами на получение, а не с запросами по почте). Другой альтернативой (если вы контролируете оба домена) является использование ARR (маршрутизации запроса приложений), чтобы обмануть браузер, считая, что запрос является локальным, а затем с помощью ARR переписать запрос в другой домен. Используя эту технику, вы можете использовать простые ajax файлы и сообщения, как обычно.