【发布时间】:2013-06-28 04:14:06
【问题描述】:
我在使用 Breeze 使用 OData 服务时遇到问题,我按照 this guide 设置了一个 Web API OData 服务,来自 Fiddler,它按预期工作得很好,但是当我尝试使用它时,它会失败并且给出“OK”的错误信息:
[Q] Unhandled rejection reasons (should be empty):Error: OK
使用 fiddler 我看到它会查询元数据,然后查询正确返回的实体,这可能是什么问题?
breeze.config.initializeAdapterInstances({ dataService: "OData" });
var manager = new breeze.EntityManager(serverAddress);
var query = new breeze.EntityQuery.from("Laboratories");
manager.executeQuery(query).then(function (data) {
ko.applyBindings(data);
}).fail(function (e) {
alert(e);
});
我通过使用ASP.NET Web API CORS support 的每晚构建启用了 CORS,一切正常,我可以检索实体,因为我可以在提琴手中看到它们被返回......只是它没有到那时承诺反而失败了。
更新:
为了响应来自新创建项目的@Ward 测试,我执行了以下操作:
项目 1
创建了一个 Web API 项目。
添加了来自 Nuget 的 Microsoft ASP.MET Web API 跨域资源共享 (CORS) 参考。
添加了以下控制器:
namespace CORSBreezeTest1.Controllers
{
public class ValuesController : EntitySetController<Value, int>
{
ValuesDbContext _context = new ValuesDbContext();
[Queryable]
public override IQueryable<Value> Get()
{
return _context.Values;
}
protected override Value GetEntityByKey(int key)
{
return _context.Values.Find(key);
}
protected override Value CreateEntity(Value entity)
{
Value value = _context.Values.Find(entity.Id);
if (value != null)
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Conflict));
}
_context.Values.Add(entity);
_context.SaveChanges();
return entity;
}
protected override int GetKey(Value entity)
{
return entity.Id;
}
protected override void Dispose(bool disposing)
{
_context.Dispose();
base.Dispose(disposing);
}
}
}
还有以下 Code First 数据库:
namespace CORSBreezeTest1
{
public class ValuesDbContext : DbContext
{
public ValuesDbContext()
: base("DefaultConnection")
{
}
public DbSet<Value> Values { get; set; }
}
public class Value
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
}
}
在WebApiConfig.cs中添加了以下几行
public static void Register(HttpConfiguration config)
{
// Default code left out here ...
config.Routes.MapODataRoute("Values", "odata", GetEdmModel());
config.EnableQuerySupport();
config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
}
private static IEdmModel GetEdmModel()
{
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.Namespace = "CORSBreezeTest1";
builder.EntitySet<Value>("Values");
return builder.GetEdmModel();
}
项目 2 然后创建了另一个 Web API 项目。
为 ASP.NET Web API 项目 Nuget 包添加了微风
添加了 datajs Nuget 包。
将以下代码行添加到Index.cshtml:
<p data-bind="visible: !results">Fetching data ... </p>
<ul data-bind="foreach: results, visible: results" style="display: none">
<li>
<span data-bind="text: Name"></span>
<span data-bind="text: Quantity"></span>
</li>
</ul>
@section Scripts {
<script src="~/Scripts/knockout-2.2.0.debug.js"></script>
<script src="~/Scripts/q.js"></script>
<script src="~/Scripts/datajs-1.1.0.js"></script>
<script src="~/Scripts/breeze.min.js"></script>
<script type="text/javascript">
$(function () {
breeze.config.initializeAdapterInstances({ dataService: "OData" });
var manager = new breeze.EntityManager("http://serverAddress/odata")
var query = new breeze.EntityQuery.from("Values");
manager.executeQuery(query).then(function (data) {
ko.applyBindings(data);
}).fail(function (e) {
alert(e);
});
});
</script>
}
按原样测试,因为两个网站都在本地主机上,所以它可以正常工作。
将 PROJECT 1 发布到 Web 服务器,以便测试实际上会看到不同的来源并进行测试。
这就是 Nugget 看到的:
第一个请求头是 OPTIONS
OPTIONS /odata/Values HTTP/1.1
第二个请求头是GET
GET /odata/Values HTTP/1.1
如果我将 fail 代码更改为:
fail(function (e) {
ko.applyBindings(e.body.value);
});
还有我的淘汰代码:
<p data-bind="visible: !$data">Fetching data ... </p>
<ul data-bind="foreach: $data, visible: $data" style="display: none">
<li>
<span data-bind="text: Name"></span>
<span data-bind="text: Quantity"></span>
</li>
</ul>
瞧!它是通过数据得出的:
这就是控制台看到的:
SEC7118: XMLHttpRequest for http://serverAddress/odata/$metadata required Cross Origin Resource Sharing (CORS).
localhost:53317
SEC7119: XMLHttpRequest for http://serverAddress/odata/$metadata required CORS preflight.
localhost:53317
SEC7118: XMLHttpRequest for http://serverAddress/odata/Values required Cross Origin Resource Sharing (CORS).
localhost:53317
SEC7119: XMLHttpRequest for http://serverAddress/odata/Values required CORS preflight.
localhost:53317
[Q] Unhandled rejection reasons (should be empty):Error: OK
项目 1 和 2 使用 BreezeControllerAttribute
如果我在另一个测试中在Breeze Nuget example 之后添加一个新控制器并添加 Breeze for ASP.NET Web API 项目 Nuget 包并添加以下控制器:
namespace CORSBreezeTest1.Controllers
{
[BreezeController]
public class BreezeValuesController : ApiController
{
readonly EFContextProvider<ValuesDbContext> _context =
new EFContextProvider<ValuesDbContext>();
[HttpGet]
public string Metadata()
{
return _context.Metadata();
}
[HttpGet]
public IQueryable<Value> Values()
{
return _context.Context.Values;
}
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return _context.SaveChanges(saveBundle);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
}
}
然后修改客户端如下:
//breeze.config.initializeAdapterInstances({ dataService: "OData" });
var manager = new breeze.EntityManager("http://serverAddress/breeze/BreezeValues")
然后请求发生变化:
一切正常...我不确定是EntitySetController 处理请求的方式不同,还是Breeze 在更改dataService 时发出了不同的请求。
【问题讨论】:
-
每当我在 Chrome 中收到 [should be empty] 错误时,都是由于没有解决承诺。只是为了我的理解,您并没有说明要在本地或从本地缓存查询的任何地方,对吗?
-
不,我必须根据我发现的一些东西重写问题...我正在查询另一个网站,所以我在服务器上启用了 CORS ...使用提琴手查询可以正常工作,只是从另一个站点查询是失败的地方,尽管在提琴手中我可以看到,当它查询时它确实返回了结果......如果我使用指南中的 ASP.NET Web API OData nuget 包,它不适用于微风给结果,但如果我采用 Breeze Web API nuget 包的方式,它可以工作......
-
如果我在托管 Web API 的同一个站点中使用相同的代码,它也可以完美运行......
标签: asp.net-web-api odata cors breeze