简体   繁体   中英

Breeze.js to ODATA Web API - CORS requests are failing

I am experimenting with Breeze.js queries against ODATA service built on Microsoft Web API 2.

Everything worked as expected when both UI and ODATA controllers lived in the same web application.

Then I decided to put my data service and the web app into separate projects. I installed required CORS packages. My data service is fully functional when I send queries from LinqPad.

However, Breeze is failing to parse arriving response payload.

This is my relevant Console trace:

XHR finished loading: GET "http://localhost:63494/odata/$metadata". (index):1
XHR finished loading: GET "http://localhost:63494/odata/Positions?$filter=(PeriodEndDate%20eq%20dateti…ue%2CCustodianAccountCode%2CCustodianCode%2CSubBusinessUnit%2CStrategyCode".
[Q] Unhandled rejection reasons (should be empty): 
["Error↵    at createError (http://localhost:57299/S…/localhost:57299/Scripts/datajs-1.1.3.js:2587:25)"]
 q.js:989

In debugger I can see that response with data is arriving from the server, but Breeze fails to parse data out of json.

My environment:

On the ODATA server side I have the following relevant packages installed:

<package id="Breeze.EdmBuilder" version="1.0.5" targetFramework="net45" />
  <package id="Breeze.Server.ContextProvider" version="1.4.12" targetFramework="net45" />
  <package id="Breeze.Server.ContextProvider.EF6" version="1.4.12" targetFramework="net45" />
  <package id="Breeze.Server.WebApi2" version="1.4.12" targetFramework="net45" />
  <package id="EntityFramework" version="6.1.0" targetFramework="net45" />
  <package id="jQuery" version="1.8.2" targetFramework="net40" />
  <package id="jQuery.UI.Combined" version="1.8.24" targetFramework="net40" />
  <package id="knockoutjs" version="2.2.0" targetFramework="net40" />
  <package id="Microsoft.AspNet.Cors" version="5.2.0-rtm-140522" targetFramework="net45" />
  <package id="Microsoft.AspNet.Mvc" version="5.2.0-rtm-140521" targetFramework="net45" />
  <package id="Microsoft.AspNet.OData" version="5.2.0-rtm-140521" targetFramework="net45" />
  <package id="Microsoft.AspNet.Providers.Core" version="1.2" targetFramework="net40" />
  <package id="Microsoft.AspNet.Providers.LocalDB" version="1.1" targetFramework="net40" />
  <package id="Microsoft.AspNet.Razor" version="3.2.0-rtm-140521" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi" version="5.2.0-rtm-140521" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.0-rtm-140522" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.0-rtm-140522" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Cors" version="5.2.0-rtm-140522" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.OData" version="5.2.0-rtm-140521" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Tracing" version="5.2.0-rtm-140521" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.0-rtm-140521" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages" version="3.2.0-rtm-140521" targetFramework="net45" />
  <package id="Microsoft.Data.Edm" version="5.6.1" targetFramework="net45" />
  <package id="Microsoft.Data.OData" version="5.6.1" targetFramework="net45" />
  <package id="Microsoft.OData.Core" version="6.3.0" targetFramework="net45" />
  <package id="Microsoft.OData.Edm" version="6.3.0" targetFramework="net45" />
  <package id="Microsoft.Spatial" version="6.3.0" targetFramework="net45" />
  <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net40" />
  <package id="Newtonsoft.Json" version="6.0.3" targetFramework="net45" />
  <package id="System.Spatial" version="5.6.1" targetFramework="net45" />
  <package id="WebActivator" version="1.5.3" targetFramework="net45" />

On the web application (ODATA client) side I have:

<package id="Antlr" version="3.5.0.2" targetFramework="net45" />
  <package id="Breeze.Client" version="1.4.12" targetFramework="net45" />
  <package id="Breeze.Server.ContextProvider" version="1.4.12" targetFramework="net45" />
  <package id="Breeze.Server.WebApi2" version="1.4.12" targetFramework="net45" />
  <package id="datajs" version="1.1.3" targetFramework="net40" />
  <package id="DotNetOpenAuth.AspNet" version="4.3.4.13329" targetFramework="net40" requireReinstallation="True" />
  <package id="DotNetOpenAuth.Core" version="4.3.4.13329" targetFramework="net40" requireReinstallation="True" />
  <package id="DotNetOpenAuth.OAuth.Consumer" version="4.3.4.13329" targetFramework="net40" requireReinstallation="True" />
  <package id="DotNetOpenAuth.OAuth.Core" version="4.3.4.13329" targetFramework="net40" requireReinstallation="True" />
  <package id="DotNetOpenAuth.OpenId.Core" version="4.3.4.13329" targetFramework="net40" requireReinstallation="True" />
  <package id="DotNetOpenAuth.OpenId.RelyingParty" version="4.3.4.13329" targetFramework="net40" requireReinstallation="True" />
  <package id="EntityFramework" version="6.1.1-beta1" targetFramework="net45" />
  <package id="jQuery" version="2.1.1" targetFramework="net40" />
  <package id="jquery.event.drag" version="2.2.0" targetFramework="net40" />
  <package id="jQuery.UI.Combined" version="1.10.4" targetFramework="net40" />
  <package id="jQuery.Validation" version="1.12.0" targetFramework="net40" />
  <package id="knockoutjs" version="3.1.0" targetFramework="net40" />
  <package id="Microsoft.AspNet.Mvc" version="5.2.0-rtm-140523" targetFramework="net45" />
  <package id="Microsoft.AspNet.Mvc.FixedDisplayModes" version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.Razor" version="3.2.0-rtm-140523" targetFramework="net45" />
  <package id="Microsoft.AspNet.Web.Optimization" version="1.1.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi" version="5.2.0-rtm-140523" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.0-rtm-140523" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.0-rtm-140523" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.OData" version="5.2.0-rtm-140523" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.0-rtm-140523" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages" version="3.2.0-rtm-140523" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages.Data" version="3.2.0-rtm-140523" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages.OAuth" version="3.2.0-rtm-140523" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages.WebData" version="3.2.0-rtm-140523" targetFramework="net45" />
  <package id="Microsoft.Bcl" version="1.1.9" targetFramework="net40" requireReinstallation="True" />
  <package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net40" />
  <package id="Microsoft.Data.Edm" version="5.6.1" targetFramework="net45" />
  <package id="Microsoft.Data.OData" version="5.6.1" targetFramework="net45" />
  <package id="Microsoft.jQuery.Unobtrusive.Ajax" version="3.2.0-rtm-140523" targetFramework="net45" />
  <package id="Microsoft.jQuery.Unobtrusive.Validation" version="3.2.0-rtm-140523" targetFramework="net45" />
  <package id="Microsoft.Net.Http" version="2.2.22" targetFramework="net40" requireReinstallation="True" />
  <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net40" />
  <package id="Modernizr" version="2.7.2" targetFramework="net45" />
  <package id="Newtonsoft.Json" version="6.0.3" targetFramework="net45" />
  <package id="Q" version="1.0.0" targetFramework="net45" />
  <package id="SlickGrid" version="2.2.20140120" targetFramework="net40" />
  <package id="System.Spatial" version="5.6.1" targetFramework="net45" />
  <package id="WebActivator" version="1.5.3" targetFramework="net45" />
  <package id="WebGrease" version="1.6.0" targetFramework="net45" />

My Controller on ODATA side looks like this:

public class PositionsController : ODataController
    {
        private AG_DWEntities db = new AG_DWEntities();

        public PositionsController()
        {
            db.Database.Log = s => Debug.WriteLine(s);
        }

        // GET odata/Positions
        [EnableQuery]
        public IQueryable<Position> GetPositions()
        {
            return db.Positions;
        }

        // GET odata/Positions(5)
        [EnableQuery]
        public SingleResult<Position> GetPosition([FromODataUri] string key)
        {
            return SingleResult.Create(db.Positions.Where(position => position.CCY == key));
        }

I use Breeze's EdmBuilder on the data server side (instead of ODataConventionModelBuilder):

private static IEdmModel GetEdmModelModelForBreeze()
        {
            return EdmBuilder.GetEdm<AG_DWEntities>();
        }

CORS is enabled by:

config.EnableCors(new EnableCorsAttribute("*", "*", "*", "*"){ SupportsCredentials = true, PreflightMaxAge = long.MaxValue});

In the Web app, query looks like this:

 var serverAddress = "http://localhost:63494/odata/";

               breeze.config.initializeAdapterInstances({ dataService: "webApiOData" });
               var manager = new breeze.EntityManager(serverAddress);
               my.vm = {
                   positions: ko.observableArray([]),                      
                   load: function () {
                       var query = breeze.EntityQuery
                           .from("Positions")
                           .where("PeriodEndDate", "==", new Date(Date.UTC(2014, 0, 30, 0, 0, 0, 0)))
                           .where("Portfolio", "==", "SUPR")
                           .take(200)
                           .orderBy("AGPositionKeyId")
                           .select("ID,Portfolio,AGPositionKeyId,BookEndingMarketValue,CustodianAccountCode,CustodianCode,SubBusinessUnit,StrategyCode");
                       try {
                           manager.executeQuery(query)
                               .then(function(data) {
                                   $.each(data.results, function(i, c) {
                                           my.vm.positions.push(c);
                                       })
                                       .fail(function(e) {
                                           alert(e);
                                       });
                               });
                       } catch (e) {
                           alert(e);
                       };
                   },
                }
                my.vm.load();
                ko.applyBindings(my.vm);

I've seen this post , and tried to inherit my controller from ApiController and use Breeze attribute, but it didn't work either - I started getting different server error.

Thanks for reading my long question!

This answer provided solution to my issue.

From WebApiConfig.cs:

//THIS DOESN'T WORK:
//var cors = new EnableCorsAttribute("*", "*", "*", null) { SupportsCredentials = true };
//NEITHER DOES THIS:
//var cors = new EnableCorsAttribute("*", "*", "*", "*") { SupportsCredentials = true };

//THIS WORKS:
var cors = new EnableCorsAttribute("*","*","*","DataServiceVersion, MaxDataServiceVersion"){SupportsCredentials = true};

config.EnableCors(cors);

These headers on responses are required by datajs: another discussion .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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