I am creating a sample app using angularjs, entity framework code-first, and webapi. I am running into an issue when binding data. I have a view with a HTML table that displays a list of "court" entities. There is also a district entity that has a one-to-many relationship to the courts (districts on the "one" side) represented by navigation properties in my models. What is happeneing is the web api controller is returning all the data but by the time it gets to the angular controller most of the results, not all, end up as "undefined".
Web api controller:
[HttpGet]
[Route("api/court/search/district/{DistrictId}/")]
public HttpResponseMessage GetCourtsByDistrict(string DistrictId)
{
DistrictId = DistrictId == "0" ? null : DistrictId;
HttpResponseMessage response = null;
IEnumerable<Court> courts;
courts = courtService.FindBy(d => d.DistrictId.Contains(DistrictId));
response = Request.CreateResponse(HttpStatusCode.OK, courts);
return response;
}
Court Service Find By method:
public IEnumerable<Court> FindBy(Expression<Func<Court, bool>> predicate)
{
IEnumerable<Court> query = CourtRepository.FindBy(predicate);
return query;
}
Angular factory:
factory.getCourtsByDistrict = function (districtId) {
url = baseAddress + "court/search/district/" + districtId;
return $http.get(url);
};
Angular controller:
$scope.getCourtsByDistrict = function (DistrictID) {
courtFactory.getCourtsByDistrict(DistrictID)
.success(function (data) {
$scope.courts = data;
})
.error(function (error) {
alertService.add('danger', 'Unable to load district data: ' + JSON.stringify(error));
});
};
Models: public partial class Court { public Court() { Employees = new HashSet(); }
[Key]
public string CourtId { get; set; }
public string CourtName { get; set; }
public string DistrictId { get; set; }
public virtual District District { get; set; }
[ForeignKey("CourtId")]
public ICollection<Employee> Employees { get; set; }
}
public partial class District
{
public District()
{
Courts = new HashSet<Court>();
Employees = new HashSet<Employee>();
}
[Key]
public string DistrictId { get; set; }
public string DistrictName { get; set; }
[ForeignKey("DistrictId")]
public virtual ICollection<Court> Courts { get; set; }
[ForeignKey("DistrictId")]
public ICollection<Employee> Employees { get; set; }
}
If I remove the following line from the Court model or remove the virtual property:
public virtual District District { get; set; }
then all the court entity data returns correctly. However, I want to return the district name property from the district entity also, for each court in the view's table, so I kind of need the virtual district property. I am not sure what is happening. There is also an employee entity which is on the one side of a one to many with both the district and courts entity. It is almost like angularJS cannot handle the level of relationshsips the nav properties are creating.
I looked further into the issue with fiddler and if you look at the image below you can see adding the (virtual) navigation property to my class changes the structure of the JSON returned by the web api controller, which seems to be producing the "undefined" items:
Ok, the virtual keyword when omitted will prevent EF from loading that data into your collection. In that case, if you really want the data to be loaded, you must tell it to EF, more or less like this:
var query = Db.District.Include(f => f.Courts) //this will populate the Courts collection for you in the case your property is not virtual
Check Scott's answer here
Also, maybe you should create a DTO to send data back to the client the way you want, that is also a good practice to model the data you want to send instead of sending the entire graph of the object, this will work like a ViewModel.