Breeze executeQuery Q promise失败CORS [英] Breeze executeQuery Q promise fails CORS

查看:281
本文介绍了Breeze executeQuery Q promise失败CORS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用Breeze消耗OData服务时遇到问题,我通过以下方式设置了Web API OData服务:,并为ASP.NET Web API项目添加Breeze Nuget包并添加以下控制器: / p>

 命名空间CORSBreezeTest1.Controllers 
{
[BreezeController]
public class BreezeValuesController:ApiController
{
readonly EFContextProvider< ValuesDbContext> _context =
new EFContextProvider< ValuesDbContext>();

[HttpGet]
public string元数据()
{
return _context.Metadata();
}

[HttpGet]
public IQueryable< Value>值()
{
return _context.Context.Values;
}

[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return _context.SaveChanges(saveBundle);
}

protected override void Dispose(bool disposal)
{
base.Dispose(disposal);
}
}
}

  // breeze.config.initializeAdapterInstances({dataService:OData}); 
var manager = new breeze.EntityManager(http:// serverAddress / breeze / BreezeValues)

然后请求变化:





一切正常...我不知道是否部分是 EntitySetController 请求不同或是Breeze在更改 dataService 时发出不同请求。

解决方案

使用它的唯一方法是使用 BreezeControllerAttribute =nofollow> Breeze.WebApi 遵循使用api的微风的确切方法。不使用 EntitySetController 并返回常规 ApiController 。详细解释问题本身。

  [BreezeController] 
public class BreezeValuesController:ApiController
{
//这里的方法
}


I'm having a problem with consuming OData Services using Breeze, I set up a Web API OData service by following this guide, from Fiddler it works excellent as expected, but when I try to use it with breeze it fails and gives an error message of "OK":

[Q] Unhandled rejection reasons (should be empty):Error: OK

Using fiddler I see it goes and queries for metadata and then it queries for the entities which are returned correctly, what could be the problem here?

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);
});

I enabled CORS by using the nightly build of ASP.NET Web API CORS support, it all works fine and I can retrieve the entities since I can see in fiddler that they are returned ... it's just that it doesn't go to the then promise instead it lands in fail.

UPDATE:

In response to @Ward testing from newly created projects I did the following:

PROJECT 1

Created a Web API Project.

Added Microsoft ASP.MET Web API Cross-Origin Resource Sharing (CORS) Reference from Nuget.

Added the following Controller:

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);
        }
    }
}

And the following Code First Database:

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; }
    }
}

Added the following lines in 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();
}

PROJECT 2 Then created another Web API Project.

Added Breeze for ASP.NET Web API Projects Nuget Package

Added datajs Nuget Package.

Added the following lines of code to 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>
}

Tested as is and it worked since both websites are on localhost.

Published PROJECT 1 to a web server so that the test will actually see different origins, and tested.

And this is what Nugget saw:

The first request headers are OPTIONS

OPTIONS /odata/Values HTTP/1.1

And the second request headers are GET

GET /odata/Values HTTP/1.1

And if I change my fail code to:

fail(function (e) {
 ko.applyBindings(e.body.value);
});

And my knockout code to:

<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>

Voila! It came through with the data:

And this is what the Console saw:

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 

PROJECTS 1 & 2 using the BreezeControllerAttribute

If I in another test add a new controller following Breeze Nuget example and add Breeze for ASP.NET Web API project Nuget package and add the following controller:

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);
        }
    }
}

And then modify the client as following:

//breeze.config.initializeAdapterInstances({ dataService: "OData" });
var manager = new breeze.EntityManager("http://serverAddress/breeze/BreezeValues")

Then the requests change:

And everything works ... I'm not sure if in part is something that EntitySetController handles requests differently or is Breeze making different requests when changing the dataService.

解决方案

The only way to get it to work was to use the BreezeControllerAttribute from Breeze.WebApi following the breeze exact way of using the api. Not using EntitySetController and going back to a regular ApiController. Detailed explanation in the question itself.

[BreezeController]
public class BreezeValuesController : ApiController
{
    // Methods here
}

这篇关于Breeze executeQuery Q promise失败CORS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆