关于Put的CORS问题

时间:2017-02-14 18:40:46

标签: asp.net-mvc api cors

当我向我的Api发送一个put我首先得到方法OPTIONS和一个错误。然后它再次点击我的选择操作方法,它包含put信息。

  public HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
        {
            var request = controllerContext.Request;
            if (request.IsInspectRequest())
            {
                var simulate = new ActionSelectSimulator();
                request.Properties[RequestHelper.ActionCache] = simulate.Simulate(controllerContext);
            }

            var selectedAction = _innerSelector.SelectAction(controllerContext);

            return selectedAction;
        }

我有一个处理我的预检请求的班级。

   public class XHttpMethodOverrideHandler : DelegatingHandler
    {
        static readonly string[] httpOverrideMethods = { "PUT", "DELETE" };
        static readonly string[] accessControlAllowMethods = { "POST", "PUT", "DELETE" };
        static readonly string httpMethodOverrideHeader = "X-HTTP-Method-Override";
        static readonly string ORIGIN_HEADER = "ORIGIN";
        static readonly string accessControlAllowOriginHeader = "Access-Control-Allow-Origin";
        static readonly string accessControlAllowMethodsHeader = "Access-Control-Allow-Methods";
        static readonly string accessControlAllowHeadersHeader = "Access-Control-Allow-Headers";

        protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            try
            {
                if (request.Method == HttpMethod.Post && request.Headers.Contains(httpMethodOverrideHeader))
                {
                    var httpMethod = request.Headers.GetValues(httpMethodOverrideHeader).FirstOrDefault();
                    if (httpOverrideMethods.Contains(httpMethod, StringComparer.InvariantCultureIgnoreCase))
                        request.Method = new HttpMethod(httpMethod);
                }

                var httpResponseMessage = base.SendAsync(request, cancellationToken);

                if (request.Method == HttpMethod.Options && request.Headers.Contains(ORIGIN_HEADER))
                {
                    httpResponseMessage.Result.Headers.Add(accessControlAllowOriginHeader, request.Headers.GetValues(ORIGIN_HEADER).FirstOrDefault());
                    httpResponseMessage.Result.Headers.Add(accessControlAllowMethodsHeader, String.Join(", ", accessControlAllowMethods));
                    httpResponseMessage.Result.Headers.Add(accessControlAllowHeadersHeader, httpMethodOverrideHeader);
                    httpResponseMessage.Result.StatusCode = HttpStatusCode.OK;
                }
                else if (request.Headers.Contains(ORIGIN_HEADER))
                    httpResponseMessage.Result.Headers.Add(accessControlAllowOriginHeader, request.Headers.GetValues(ORIGIN_HEADER).FirstOrDefault());

                return httpResponseMessage;
            }
            catch (Exception ex)
            {
                ILoggerService logger = IocContainer.Container.TryGetInstance<ILoggerService>();
                if (logger != null)
                {
                    logger.Error(ex);
                }
                return Task.FromResult<HttpResponseMessage>(request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex));
            }

我也加入了我的webconfig

 <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>

当我发送我的Put Ajax电话时,我收到一个错误。它命中我的方法并执行我的操作,但它发送错误。如果我通过邮递员发送放置请求,那么我没有问题。如果我从客户端发送它我得到一个错误,因为它得到的第一个方法是{OPTIONS}。我错过了什么? 这是我的Ajax put

  $.ajax({
                    url: "http://localhost:61148/api/mycontroller",
                    contentType: "application/x-www-form-urlencoded; charset=UTF-8",
                    async: true,
                    type: "PUT",
                    data: sendData,
                    datatype: 'json',
                    crossDomain: true,
                    success: function () {

1 个答案:

答案 0 :(得分:1)

我在其他几个问题中找到了答案。解决方案很简单,很痛。如果您遇到此问题,请在控制器中添加选项方法。

public HttpResponseMessage Options()
{
    var response = new HttpResponseMessage
    {
        StatusCode = HttpStatusCode.OK
    };
    return response;
}