1
votes

I have a Breeze dataservice (aka datacontext) in my Single Page Application. I want to get a list of Runs from a WebAPI controller along with a list of OutlineItems for each run.

The controller is returning the list of open Runs with child OutlineItems with this method on the BreezeController.

[AcceptVerbs("GET")]
public IQueryable<Run> Runs()
{
return _contextProvider.Context.Runs
    .Include("RunOutlineItems")
    .AsQueryable()
    .Where(r => r.RunStatusId < 4);    // 4 is the cutoff for open items             

}

Here is the data model.

namespace PilotPlantBreeze
{
    public class Run
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Rundate { get; set; }
        public DateTime? RunStart { get; set; }
        public int MachineId { get; set; }
        public int ProductId { get; set; }
        public int RunStatusId { get; set; }
        public string Comments { get; set; }

        // Nav props
        public IList<OutlineItem> RunOutlineItems { get; set; }
    }
}       

When I look at the Response data from the WebAPI request, the list of RunOutlineItems is in the JSON. Here is one item for example:

{
    "$id":"27",
    "$type":"PilotPlantBreeze.OutlineItem,PilotPlantBreeze.Model",
    "Id":22,
    "RunId":5,
    "TankId":4,
    "OutlineTopicId":1,
    "OutlineDescriptionId":9,
    "PersonId":1,
    "Value":"23"
}

Here is my client side javascript code to get the data from the WebAPI. Error checking and local cache checking omitted for clarity.

var getRuns = function () {
    // The EntityQuery is defined at the beginning of the dataservice
    //  Here I am asking for a query on the server.  Note the .expand 
    //  which is supposed to avoid lazy loading.  Lazy loading is turned off 
    //  on the WebAPI already.
    var query = EntityQuery
    .from("Runs")
    .expand("RunOutlineItems")
    .orderBy("rundate");

    // The manager is defined at the beginning of the dataservice
    //  Here I am asking the manager to execute the query with a promise
    return manager.executeQuery(query)
    .then(runsQuerySucceeded)
    .fail(runsQueryFailed);

    // The promise does not fail, but I would put an error in here if it ever does
    function runsQueryFailed(data) {
    }
    // When the promise succeeds, the data parameter is the JSON from the WebAPI
    function runsQuerySucceeded(data) {
        //
        // When I stop the debugger here data.results holds the entities, but
        //  the child entities for the RunOutlineItems is an observableArray with 
        //  nothing in it.
        //
        app.vm.runs.runs(data.results);
    }
};

So my question is how to get the child items into my viewModel. I have a workaround which gets the child Items in a separate call to the WebAPI on the server and processes them with a custom ko.bindHandler, but it would be convenient to have the navigation technology working.

1
Please check the checkmark under Jay's answer if it answered your question. That way we'll know the issue is closed. If it isn't closed, let us know so we can follow up. Thanks.Ward

1 Answers

2
votes

You shouldn't need both the 'include' (server side) and the expand (client side); either one should do the trick.

So I'd leave you client side query alone and modify the server side query to just this:

[AcceptVerbs("GET")]
public IQueryable<Run> Runs() {
    return _contextProvider.Context.Runs
      .Where(r => r.RunStatusId < 4);    // 4 is the cutoff for open items             

}

Note that the AsQueryable() is gone as well.

If this doesn't work, please post back.