mvc web api跨域帖子

时间:2012-10-22 19:03:58

标签: asp.net-web-api cors

  

可能重复:
  CORS with WebAPI for XmlHttpRequest



 我正在尝试将跨域ajax帖子实现到我的webApi项目中。我没有遇到什么麻烦:
 1.在改变我的webapi动作之前,我总是遇到204错误

public void submit(Submission model)

public bool submit(Submission model)

不知道为什么,但现在我得到200 OK状态

 2.仍然是我的ajax发射错误回调。

 很久以前,我通过添加解决了跨域发布的这种错误

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

我做错了什么?

解决

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

来源:
Implementing CORS support in ASP.NET Web APIs


我做了什么:

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
  2. 
    protected void Application_Start()
            {
                AreaRegistration.RegisterAllAreas();
    
                RegisterGlobalFilters(GlobalFilters.Filters);
                RegisterRoutes(RouteTable.Routes);
    
                GlobalConfiguration.Configuration.MessageHandlers.Add(new CorsHandler());
            }
    
    

    注意最后一行。

     此方法与MVC3和.NET 4.0兼容。效果很好,现在我可以在ajax中处理“成功”和“错误”回调。

2 个答案:

答案 0 :(得分:1)

分别回答你的问题:

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

    10.2.5 204无内容

         

    服务器已完成请求但不需要返回     entity-body,可能想要返回更新的元信息。该     响应可能包括新的或更新的元信息形式     实体标题,如果存在,应该与...相关联     要求的变体。

         

    如果客户端是用户代理,它不应该更改其文档视图     从导致请求发送的那个。这个回应是     主要是为了允许在没有的情况下进行动作的输入     但是,导致更改用户代理的活动文档视图     任何新的或更新的元信息应该应用于文档     目前在用户代理的活动视图中。

         

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

    1. 你能说清楚你遇到的错误是什么吗? ASP.NET Web API目前没有开箱即用的JSONP格式化程序。这是第三部分实现:

    2. 在Web API中,您引用Response的方式不是通过HttpContext。有多种访问方式。

    3. 第一个选项是直接定义动作返回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;
          }
      }
      

答案 1 :(得分:0)

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