3

I'm using a ODataController to return data to the breeze dataservice, this is the dataservice

app.dataservice = (function (breeze) {    
    breeze.config.initializeAdapterInstances({ dataService: "OData" });

    var manager = new breeze.EntityManager('/api/v1/');

    return {
        getRecipePage: getRecipePage
    };

    function getRecipePage(skip, take, searchText) {
        var query = breeze.EntityQuery
                .from("Recipes")
                .orderBy("Name")
                .skip(skip).take(take)
                .inlineCount(true);
        if (searchText) {
            query = query.where("Name", "contains", searchText);
        }

        return manager.executeQuery(query);
    }
})(breeze);

when calling the getRecipePage function in my controller, it seems to return data properly, but the exceptions is strange

getDataFunction(skip, take)
        .then(function (largeLoad) {
            $scope.setPagedData(largeLoad, currentPage, pageSize);
        })
        .fail(function (e) {
            debugger;
        });

The e variables has the message "; ", which makes no sense. The status is "200 OK" which is good.

The body contains my two entities and the url appers correct "/api/v1/Recipes?$orderby=Name&$top=2&$inlinecount=allpages", if I navigate to it, the json looks good:

{
    "$id": "1",
    "$type": "Breeze.WebApi2.QueryResult, Breeze.WebApi2",
    "Results": [
        {
            "$id": "2",
            "$type": "RecipeBook.Web.Angular.Models.RecipeBook.Recipe, RecipeBook.Web.Angular",
            "Name": "1 Boiled Water",
            "Description": "6 Steamy goodness!",
            "Id": 1
        },
        {
            "$id": "3",
            "$type": "RecipeBook.Web.Angular.Models.RecipeBook.Recipe, RecipeBook.Web.Angular",
            "Name": "2 Hot Chocolate",
            "Description": "5 Chocolatey Chocolateness!",
            "Id": 2
        }
    ],
    "InlineCount": 6
}

...what is this error? Lastly, here is the stack:

Error
    at createError (http://localhost:62576/Scripts/breeze.debug.js:15182:22)
    at http://localhost:62576/Scripts/breeze.debug.js:14971:40
    at http://localhost:62576/Scripts/datajs-1.1.1.js:1671:17
    at XMLHttpRequest.odata.defaultHttpClient.request.xhr.onreadystatechange (http://localhost:62576/Scripts/datajs-1.1.1.js:2587:25)

Thoughts as to what is going on???

EDIT: After a ton of digging, I've somewhat narrowed down the issue to be related to the handler that reads the response. In datajs-1.1.1.js ~line 8100 there is a dispatchHandler function. I have a requestOrResponse that came back from the OData call:

It has a body property with the above json text. The data property is undefined however, but I think that's what it's trying to translate the body into...and is looking for a handler to do so. It's statusCode is 200, and statusText is OK. But the method doesn't find an appropriate handler and throws:

  throw { message: "no handler for data" };

...this appears to be where the error originates. I just have no clue what's not setup correctly so that I can remedy the situation.

EDIT2: It might actually be caused because the metadata (xml) isn't being parsed correctly..., this is what it looks like (taken from the datajs handlerRead function while debugging)

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
  <edmx:DataServices m:DataServiceVersion="3.0" m:MaxDataServiceVersion="3.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
    <Schema Namespace="RecipeBook.Web.Angular.Models.Recipe" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
      <EntityType Name="Recipe">
        <Key>
          <PropertyRef Name="Id" />
        </Key>
        <Property Name="Id" Type="Edm.Int32" Nullable="false" />
        <Property Name="Name" Type="Edm.String" />
        <Property Name="Description" Type="Edm.String" />
        <Property Name="Steps" Type="Collection(Edm.String)" />
        <NavigationProperty Name="Ingredients" Relationship="RecipeBook.Web.Angular.Models.Recipe.RecipeBook_Web_Angular_Models_Recipe_Recipe_Ingredients_RecipeBook_Web_Angular_Models_Recipe_RecipeIngredient_IngredientsPartner" ToRole="Ingredients" FromRole="IngredientsPartner" />
      </EntityType>
      <EntityType Name="RecipeIngredient">
        <Key>
          <PropertyRef Name="Id" />
        </Key>
        <Property Name="Id" Type="Edm.Int32" Nullable="false" />
        <Property Name="IngredientId" Type="Edm.Int32" Nullable="false" />
        <Property Name="Quantity" Type="Edm.Int32" Nullable="false" />
        <Property Name="UnitOfMeasureId" Type="Edm.Int32" Nullable="false" />
        <Property Name="Notes" Type="Edm.String" />
      </EntityType>
      <Association Name="RecipeBook_Web_Angular_Models_Recipe_Recipe_Ingredients_RecipeBook_Web_Angular_Models_Recipe_RecipeIngredient_IngredientsPartner">
        <End Type="RecipeBook.Web.Angular.Models.Recipe.RecipeIngredient" Role="Ingredients" Multiplicity="*" />
        <End Type="RecipeBook.Web.Angular.Models.Recipe.Recipe" Role="IngredientsPartner" Multiplicity="0..1" />
      </Association>
      <EntityContainer Name="Container" m:IsDefaultEntityContainer="true">
        <EntitySet Name="Recipes" EntityType="RecipeBook.Web.Angular.Models.Recipe.Recipe" />
      </EntityContainer>
    </Schema>
  </edmx:DataServices>
</edmx:Edmx>

EDIT3:

...so, if I use OData, as my dataService I need json metadata found at $metadata. If I use WebAPI it looks for metadata at /Metadata, and this can be Edmx or json. However, my metadata is returned as Edmx at $metadata ... which is the one thing not supported?

http://www.breezejs.com/documentation/breeze-metadata-details

I'm about to throw all this out (angular, breeze, odata) and just do it the old way.

Edit4: This isn't a fix, but if I turn off metadata it "works"...so my issue is definitely related to Metadata not loading properly.

var dataService = new breeze.DataService({
    serviceName: "/api/v1/",
    hasServerMetadata: false 
});
CaffGeek
  • 21,856
  • 17
  • 100
  • 184
  • Have you included Data.js before Breeze? Also consider using Brian Noyes' OData walk-thru to set up Breeze.js - http://briannoyesblogwp.azurewebsites.net/2013/02/16/consuming-an-asp-net-web-api-odata-service-with-breeze/ – PW Kad Dec 12 '13 at 17:37
  • Yes I did, and using that as a reference is how I got it working as far as I have, I can't copy that exactly however, as we aren't using EF. – CaffGeek Dec 12 '13 at 17:45
  • @PWKad, and we use angular not ko, which changes things as well. – CaffGeek Dec 12 '13 at 17:52
  • 1
    I am getting this same error when I try to use the BreezeSimpleCorsHandler on my Odata service. It fails with this cryptic error when requesting the data "cross-domain" but works fine if I request from localhost. I know it doesn't seem to apply to the question specifically, but I thought it was interesting. – jsuddsjr Oct 03 '14 at 16:59

1 Answers1

1

It looks like you are using Web API. Consider that you could decorate your controllers with the [BreezeController] attribute and instead of specifying OData you could use webApi which extends the configuration a bit. It's worth trying.

Also you probably need to configure the Breeze adapter to use backingStore which pairs well with Angular. - http://www.breezejs.com/samples/todo-dataservice (this link has some helpful tips to guide you through setting up Breeze to work well with Angular)

Last, remember that setting up any library the first time you use it always seems more difficult than it really is. Once you get it configured you almost never touch configuration again and instead Breeze just works and is really awesome.

EDIT

Check this link which has a brief walk-thru on Breeze, Angular, OData, and Web API - http://sravi-kiran.blogspot.com/2013/11/UsingBreezeJsToConsumeAspNetWebApiODataInAnAngularJsApplication.html

Another good 'How do I...' answer here by Ward -

How to consume OData service with Html/Javascript?

Community
  • 1
  • 1
PW Kad
  • 14,953
  • 7
  • 49
  • 82
  • I'm using the BreezeController attribute. I'm used to "teething" issues with a new library, no worries there. How do I configure breeze to use backingStore, I had `breeze.config.initializeAdapterInstance("modelLibrary", "backingStore", true);`, but removed it because I couldn't seem to merge it with the `breeze.config.initializeAdapterInstances({ dataService: "OData" });` line? – CaffGeek Dec 12 '13 at 18:01
  • Actually, if I put the two lines in succession, I get the same error I outlined above. – CaffGeek Dec 12 '13 at 18:06
  • None of that seems to help. I get data back from the service...it just hits `.fail()` instead of `.then()` with the error message `"; "` which doesn't make any sense, even though the error ('e') body contains the entities returned by my OData service. – CaffGeek Dec 12 '13 at 19:22
  • I have edit the question with more info as to where the root of the exception appears to be. – CaffGeek Dec 12 '13 at 19:40