user1482939 user1482939 - 3 months ago 15
JSON Question

Include inner item when return JSon

I have an Employee class, taken from a database. In that Employee class, I want to add a Manager object, which is also an Employee, based on the managerCode that is in the Employee database. See below for the class.

The managerCode is not defined as a key, . I don’t need recursion, i.e. I don’t need the Manager’s manager, etc. Just one level, the Employee and his manager.

Using .NET 4.5, c#, OData v4

I am using OData to send back the Employee, but the Manager part isn’t added in the response, even if it’s there in the object I try to send.

What am I missing? Something in the WebApiConfig?

Thanks

Employee class, first 4 fields are directly taken from database.

Class Employee
{
[Key]
public int id { get; set; }
public string employeeCode { get; set; }
public string employeeName { get; set; }
public string managerCode { get; set; }

[NotMapped]
public Employee Manager { get; set; }
}


Controller class. GetEmployeeById(id) will get Employee(s) with their Manager.

[HttpGet]
[EnableQuery]
[ODataRoute("employeeById(id={id})")]
public IHttpActionResult employeeById([FromODataUri]int id)
{
var sets = dbContext.GetEmployeeById(id);
if (!sets.Any())
return NotFound();
return this.CreateOKHttpActionResult(sets);
}


WebApiConfig

public static void Register(HttpConfiguration config)
{
config.MapODataServiceRoute("ODataRoute", "odata",GetEdmModel(),
new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));
config.EnsureInitialized();
}

private static IEdmModel GetEdmModel()
{
var builder = new ODataConventionModelBuilder();
builder.Namespace = "employee_odata";
builder.ContainerName = "employee_odataContainer";
builder.EntitySet<Employee>("Employee");
builder.EnableLowerCamelCase();

var unboundGetEmployee = builder.Function("employeeById");
unboundGetEmployee.Returns<Employee>();
unboundGetEmployee.Parameter<int>("id");
unboundGetEmployee.Namespace = "employee_odata.Functions";

return builder.GetEdmModel();

}


SOLUTION

Remove
unboundGetEmployee
from WebApiConfig (not needed).

Make Manager item in Employee class virtual, without the
[NotMapped]
:

public virtual Manager Manager { get; set; }


Controller:

[EnableQuery]
[ODataRoute("Employee({id})")]
public IHttpActionResult employeeById([FromODataUri]int id)
{
//handle data return normally...
//I have to detect $expand=Manager, to fetch the actual Manager object.
//otherwise it's null (not linked with primary key)
}


With these fee changes, $expand is working well.

Answer

You need to add $expand to show navigation property, like

localhost\odata\employee_odata.Functions.employeeById(id=1)?$expand=Manager

And for get employee by Id, I suggest you to use this method in controller:

[EnableQuery]
public IHttpActionResult Get(int id)
{
    var sets = dbContext.GetEmployeeById(id);
    if (!sets.Any())
        return NotFound();
    return this.CreateOKHttpActionResult(sets);
}

Then request like localhost\odata\Employee(1) can route to that method.