【发布时间】:2013-09-26 06:20:51
【问题描述】:
我使用 ServiceStack 构建了一个 RESTful 服务,该服务将数据发送到数据库。我在本地测试过,效果很好。当我将它部署到服务器并运行相同的代码(即 jQuery $.ajax 调用)时,我收到“拒绝访问”错误。我在我的 ServiceStack 配置中设置了 CORS,使用插件为explained here。我还在我的 ajax 调用中将 crossDomain 设置为 true。我想不出还有什么办法可以让它工作,老实说,我不确定这个错误是在哪里引发的。我已经通过了 Javascript,它甚至没有到达 ajax 调用的“失败”块,在此之前抛出了错误......我正在使用 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;
}
这是我调用网络服务的 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 是 Access-Control-Allow-Origin 不允许的。 XMLHttpRequest 无法加载 http://servicedomain.com//citations。 Access-Control-Allow-Origin 不允许来源 http://callingdomain.com。
但我明确允许标题中的所有域:
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 获得有效响应。这是响应标头:
状态码:200 日期:格林威治标准时间 2013 年 9 月 20 日星期五 19:54:26 服务器:Microsoft-IIS/6.0 X-AspNet-版本:4.0.30319 X-Powered-By: ASP.NET, ServiceStack/3.948 Win32NT/.NET 访问控制允许方法:POST、GET、OPTIONS、GET、POST、PUT、DELETE、OPTIONS 内容类型:应用程序/json;字符集=utf-8 访问控制允许来源:*,* 缓存控制:私有 内容长度: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 中选项卡的屏幕截图:
【问题讨论】:
-
注意:CorsFeature 已经将 CORS 标头添加到
Config.GlobalResponseHeaders,因此请从其他任何地方(即 GlobalResponseHeaders 和 RequestFilters 内部)删除它们。如果您仍然有问题,可以在 Chrome 开发工具中发布网络控制台的屏幕截图,并选择错误(红色)请求的详细信息。 -
对标题的神话建议可能是解决方案。
标签: javascript jquery ajax rest servicestack