15

可能重复:
CORS 与 WebAPI for XmlHttpRequest



我正在尝试将跨域 ajax 发布到我的 webApi 项目。我对此几乎没有什么问题:
1. 在更改我的 webapi 操作之前,我总是收到 204 错误

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请求:

变种模型 = {
        "类型": $("#model-type").val(),
        "主题": $("#subject-text").val(),
        "正文": $("#body-text").val()
    };

    $.ajax({
        类型:“发布”,
        数据类型:'JSONP',
        url: $("#submit-url").val(),
        数据:模型,
        成功:函数(){
            alert("提交成功");
        },
        错误:函数(){
            alert("错误...");
        }
    });

我做错了什么?

解决了

感谢大家帮助我。我在其中一个评论链接中找到了解决方案。我使用了以下方法,我觉得这很简单。

资料来源:
在 ASP.NET Web API 中实现 CORS 支持


我做了什么:

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);
            }
        }
    }

  1. 打开我的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 兼容。效果很好,现在我可以在 ajax 中处理“成功”和“错误”回调。

4

2 回答 2

1

分别回答你的问题:

  1. 状态 204 不是错误,这意味着没有要返回的内容,但一切都很好。这是RFC2616中 204 的定义

10.2.5 204 无内容

服务器已完成请求,但不需要返回实体主体,并且可能希望返回更新的元信息。响应可能包括实体头形式的新的或更新的元信息,如果存在,应该与请求的变体相关联。

如果客户端是用户代理,它不应该改变导致请求被发送的文档视图。这个响应主要是为了允许输入动作发生而不导致用户代理的活动文档视图发生变化,尽管任何新的或更新的元信息应该应用于当前在用户代理的活动视图中的文档。

204 响应不能包含消息体,因此总是由头字段之后的第一个空行终止。

  1. 你能说出你遇到的错误是什么吗?ASP.NET Web API 当前没有开箱即用的 JSONP 格式化程序。这是一些第三部分的实现:
  1. 在 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;
    }
}
于 2012-10-22T20:02:54.027 回答
0

如果您想从 ajax 向另一个域发送信息,那么您需要使用 jsonp(注意这仅适用于 get 请求而不是 post 请求)。另一种选择(如果您控制两个域)是使用 ARR(应用程序请求路由)来欺骗浏览器认为请求是本地的,然后使用 ARR 将请求重写到另一个域。使用这种技术,您可以像平常一样使用简单的 ajax 获取和发布。

于 2012-10-22T19:18:32.280 回答