简体   繁体   中英

Strange Breeze error when query DOES return data (update: Metadata not loading correctly)

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

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?

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