简体   繁体   English

将数据发送到ServiceStack RESTful服务,获得“访问被拒绝”

[英]Sending Data to ServiceStack RESTful service, getting 'Access is denied'

I built a RESTful service with ServiceStack which sends data to a database. 我使用ServiceStack构建了RESTful服务,该服务将数据发送到数据库。 I've tested it locally and it works great. 我已经在本地测试过,效果很好。 When I deploy it to a server and run the same code, which is a jQuery $.ajax call, I get an 'Access is denied' error. 当我将其部署到服务器并运行相同的代码(即jQuery $ .ajax调用)时,出现“拒绝访问”错误。 I have setup CORS in my ServiceStack config using the plugin as explained here . 我已经使用插件在ServiceStack配置中设置了CORS,如此处所述 I also set the crossDomain to true in my ajax call. 我还在ajax调用中将crossDomain设置为true。 I can't think of what else to do to get this to work, and I'm honestly not sure where this error is being thrown. 我想不出要怎么做才能使它正常工作,老实说,我不确定在哪里抛出该错误。 I've stepped through the Javascript and it doesn't even get to the 'failure' block of the ajax call, the error is thrown before that... I am using IE9 to test, if that's pertinent...? 我已经遍历了Javascript,它甚至没有到达ajax调用的“ failure”块,在此之前引发了错误……我正在使用IE9进行测试,是否相关……?

Any idea what might be going on? 知道会发生什么吗?

Here's my ServiceStack POST method: 这是我的ServiceStack POST方法:

    public CitationResponse Post(Citation citation)
    {
        var response = new CitationResponse { Accepted = false };

        if (string.IsNullOrEmpty(citation.ReportNumber))
        {
            response.Accepted = false;
            response.Message = "No data sent to service.  Please enter data in first.";
            return response;
        }

        try
        {
            response.ActivityId = Repository.CreateCitation(citation.ReportNumber, citation.ReportNumber_Prefix, citation.ViolationDateTime, citation.AgencyId, citation.Status);
            response.Accepted = true;
        }
        catch (Exception ex)
        {
            response.Accepted = false;
            response.Message = ex.Message;
            response.RmsException = ex;
        }

        return response;
    }

Here's my Javascript function which calls the web service: 这是调用Web服务的Javascript函数:

   SendCitationToDb: function(citation, callback) {
        $.ajax({
            type: "POST",
            url: Citations.ServiceUrl + "/citations",
            data: JSON.stringify(citation),
            crossDomain: true,
            contentType: "application/json",
            dataType: "json",
            success: function (data) {
                if (!data.Accepted) {
                    Citations.ShowMessage('Citation not added', 'Citation not added to database.  Error was: ' + data.Message, 'error');
                } else {
                    citation.ActivityId = data.ActivityId;
                    callback(data);
                }
            },
            failure: function(errMsg) {
                Citations.ShowMessage('Citation not added', 'Citation not added to database.  Error was: ' + errMsg.Message, 'error');
            }
        });
    }

Thanks for your help! 谢谢你的帮助!

Update: I just ran the same app in Chrome 29 and I get these errors (replaced real URLs for security): 更新:我只是在Chrome 29中运行了同一个应用程序,但遇到了以下错误(为安全起见,替换了真实URL):

OPTIONS http://servicedomain.com/citations Origin http://callingdomain.com is not allowed by Access-Control-Allow-Origin.

XMLHttpRequest cannot load http://servicedomain.com//citations. Origin http://callingdomain.com is not allowed by Access-Control-Allow-Origin.

But I am clearly allowing all domains in my headers: 但我显然允许标题中包含所有域:

            Plugins.Add(new CorsFeature()); //Enable CORS

            SetConfig(new EndpointHostConfig {
                DebugMode = true, 
                AllowJsonpRequests = true,
                WriteErrorsToResponse = true,
                GlobalResponseHeaders =
                {
                    { "Access-Control-Allow-Origin", "*" },
                    { "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" }
                }
            });

NOW, if I run the same service call through the REST Console app in Chrome I get a valid response from ServiceStack. 现在,如果我通过Chrome中的REST控制台应用程序运行相同的服务调用,我将收到ServiceStack的有效回复。 Here's the response header: 这是响应头:

Status Code: 200
Date: Fri, 20 Sep 2013 19:54:26 GMT
Server: Microsoft-IIS/6.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET, ServiceStack/3.948 Win32NT/.NET
Access-Control-Allow-Methods: POST,GET,OPTIONS, GET, POST, PUT, DELETE, OPTIONS
Content-Type: application/json; charset=utf-8
Access-Control-Allow-Origin: *, *
Cache-Control: private
Content-Length: 58

So I'm totally lost as to why it works in a pure REST request, but not from the application?? 所以我完全迷失了为什么它可以在纯REST请求中工作,而不是在应用程序中工作?

Update: 更新:

After spending many hours trying many different solutions I've found online, my Configure method now looks like this: 在花了很多时间尝试了许多我在网上找到的不同解决方案之后,我的Configure方法现在看起来像这样:

        public override void Configure(Container container)
        {
            SetConfig(new EndpointHostConfig
            {
                DefaultContentType = ContentType.Json,
                ReturnsInnerException = true,
                DebugMode = true, //Show StackTraces for easier debugging (default auto inferred by Debug/Release builds)
                AllowJsonpRequests = true,
                ServiceName = "SSD Citations Web Service",
                WsdlServiceNamespace = "http://www.servicestack.net/types",
                WriteErrorsToResponse = true,
                GlobalResponseHeaders = 
                { 
                    { "Access-Control-Allow-Origin", "*" },
                    { "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" }
                }
            });

            container.RegisterAutoWired<Citation>();
            container.RegisterAutoWired<Driver>();
            container.RegisterAutoWired<Vehicle>();
            container.RegisterAutoWired<Violations>();

            using (var getAttributes = container.Resolve<AttributesService>())
                getAttributes.Get(new AttributesQuery());

            Plugins.Add(new CorsFeature());
            RequestFilters.Add((httpReq, httpRes, requestDto) =>
            {
                httpRes.AddHeader("Access-Control-Allow-Origin", "*");
                httpRes.AddHeader("Access-Control-Allow-Methods", "POST, GET, DELETE, OPTIONS");
                httpRes.AddHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type");

                if (httpReq.HttpMethod == "OPTIONS")
                    httpRes.EndServiceStackRequest(); //   extension method
            });

            Routes
              .Add<Attribute>("/attributes", "GET, OPTIONS")
              .Add<Citation>("/citations", "POST, GET, OPTIONS, DELETE")
              .Add<Driver>("/driver", "POST, OPTIONS")
              .Add<Vehicle>("/vehicle", "POST, OPTIONS")
              .Add<Violations>("/violations", "POST, OPTIONS");

            var config = new AppConfig(new ConfigurationResourceManager());
            container.Register(config);
        }
    }

At this point I'm not sure what to do. 在这一点上,我不确定该怎么办。 I've tried everything, but am still getting the same errors. 我已经尝试了所有方法,但是仍然遇到相同的错误。 The methods continue to work fine using the REST Console in Chrome, which is a little infuriating, since I can never get them to work calling them from a web page. 使用Chrome中的REST控制台,这些方法仍然可以正常工作 ,这有点令人生气,因为我永远无法让他们使用它们来从网页调用它们。 I'm almost ready to re-write the whole thing in WCF, but I really would love to get the ServiceStack version working, since I know it works locally! 我几乎准备好用WCF重写整个过程,但是我真的很想让ServiceStack版本开始工作,因为我知道它可以在本地工作! If anyone has any other suggestions I can try, I would SO appreciate your help! 如果有人有其他建议可以尝试,非常感谢您的帮助!

Update: See comment at the bottom for details. 更新:有关详细信息,请参见底部的评论。 I had to remove headers from the HTTP Headers tab in IIS. 我必须从IIS的HTTP标头选项卡中删除标头。 Not sure when I put those in, but for anyone else who might face the same issue, here's a screenshot of the tab in IIS: 不知道何时将它们放进去,但是对于可能遇到相同问题的其他人,这是IIS中选项卡的屏幕截图:

自定义Http标头

I had the same problem with you, in my previous question 我有同样的问题与你,在我以前的问题

You can read very helpful answers of #mythz here and here . 您可以在此处此处阅读#mythz的非常有用的答案。

The code I use in the AppHost 我在AppHost中使用的代码

          using System.Web;
          using ServiceStack.WebHost.Endpoints.Extensions;  // for  httpExtensions methods  
    //  => after  v.3.9.60,  =>using ServiceStack;

and

          public override void Configure(Container container)
          {   

                SetConfig(new ServiceStack.WebHost.Endpoints.EndpointHostConfig
                {
                 DefaultContentType = ContentType.Json,
                  ReturnsInnerException = true,
                  WsdlServiceNamespace = "http://www.servicestack.net/types"
                });

             Plugins.Add(new CorsFeature()); 
             this.RequestFilters.Add((httpReq, httpRes, requestDto) =>
             {
                //Handles Request and closes Responses after emitting global HTTP Headers
                   if (httpReq.HttpMethod == "OPTIONS")
                           httpRes.EndServiceStackRequest();  //httpExtensions method
               //  =>after  v.3.9.60, => httpRes.EndRequestWithNoContent(); 
              });

            Routes
             .Add<TestRequest>("/TestAPI/Reservation", "POST, OPTIONS");   // OPTIONS is mandatory for CORS
          }

and in JavaScript like you 和像你一样的JavaScript

  jQuery.support.cors = true;

    function TestRequestCall() {
       var  TestRequest = new Object();                
           TestRequest.Id = 11111;
           TestRequest.City = "New York";



      $.ajax({
          type: 'Post',
          contentType: 'application/json',         
          url: serverIP +'/TestAPI/Reservation',
          data: JSON.stringify( TestRequest ),
          dataType: "json",
          success: function (TestResponse, status, xhr) {

                 if(TestResponse.Accepted)  doSomething();

           },
           error: function (xhr, err) {
              alert(err);
           }
      });
   }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM