我使用ServiceStack构建了一个RESTful服务,该服务将数据发送到数据库。我在本地进行了测试,效果很好。当我将它部署到服务器并运行相同的代码(这是一个jQuery $ .ajax调用)时,我得到一个“访问被拒绝”错误。我使用插件explained here在我的ServiceStack配置中设置了CORS。我还在我的ajax调用中将crossDomain设置为true。我想不出还有什么可以让它发挥作用,而且老实说我不确定这个错误被扔到哪里。我已经逐步完成了Javascript,它甚至没有进入ajax调用的'failure'块,在此之前抛出错误...我正在使用IE9进行测试,如果那是相关的......?
知道可能会发生什么吗?
这是我的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;
}
这是我调用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');
}
});
}
感谢您的帮助!
更新的 我刚刚在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.
但我明确允许我标题中的所有域名:
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" }
}
});
现在,如果我通过Chrome中的REST Console app运行相同的服务电话,我会收到ServiceStack的有效回复。这是响应头:
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
所以我完全迷失了为什么它在纯REST请求中工作,而不是从应用程序中工作?
更新
我花了很多时间尝试在网上找到的许多不同解决方案后,我的配置方法现在看起来像这样:
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);
}
}
此时我不知道该怎么做。我已经尝试了一切,但我仍然遇到同样的错误。这些方法继续使用Chrome中的REST控制台正常工作,这有点令人生气,因为我永远无法让他们从网页上调用它们。我几乎准备好在WCF中重写整个内容,但我真的很想让ServiceStack版本正常工作,因为我知道它在本地工作!如果有人有任何其他建议我可以尝试,我会非常感谢你的帮助!
更新 有关详细信息,请参阅底部的评论。我不得不从IIS中的HTTP标头选项卡中删除标头。我不知道什么时候把它们放进去,但是对于其他可能遇到同样问题的人来说,这里是IIS中标签的截图:
答案 0 :(得分:2)
在我之前的question
中,我遇到了同样的问题您可以阅读#mythz here和here的非常有用的答案。
我在AppHost中使用的代码
using System.Web;
using ServiceStack.WebHost.Endpoints.Extensions; // for httpExtensions methods
// => after v.3.9.60, =>using ServiceStack;
和
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
}
和像你一样的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);
}
});
}