0
votes

I've got a C# based OData source and I'm having problems getting $expand to work. All the related posts to StackOverFlow seem to refer to pre-OData V4 because a lot of the controller method patterns that just do not apply/work under OData V4.

My problem: I have two entities Table1 and Table2, where there is a many-to-one relationship between them. Table1 has a navigation property called Table2 with FK Table2Id used to facilitate that relationship.

  [Serializable, DataContract]
  public class Table1
  {
    [DataMember, Key]
    public int Id { get; set }
    [DataMember]
    public Table2 Table2 { get; set; }
    [DataMember, ForeignKey("Table2")]
    public int Table2Id { get; set;} 
  }

  [Serializable, DataContract]
  public class Table2
  {
    [DataMember, Key]
    public int Id { get; set }
    public string Name { get; set;} 
  }

When I send the URL:

http://localhost/OData4/api/Table1s?$expand=Table2

I get an error:

The query specified in the URI is not valid. Could not find a property named 'Table2' on type 'System.Web.OData.Query.Expressions.SelectAllAndExpand_1OfTable1

Here's my controller:

[EnableQuery]
public IHttpActionResult Get(ODataQueryOptions<Table1> queryOptions)
{
  IQueryable result;

  // validate the query.
  try
  {
    queryOptions.Validate(_validationSettings);

    var dataSet = container.Get().AsQueryable();  // I can see Table1.Table2 here
    result = queryOptions.ApplyTo(dataSet);  // result has list of Table1 with Table2 nav property
  }
  catch (ODataException ex)
  {
    throw new HttpRequestException(ex.Message);
  }

  return Ok(result, result.GetType());
}

protected IHttpActionResult Ok(object content, Type type)
{
  Type resultType = typeof (OkNegotiatedContentResult<>).MakeGenericType(type);
  return Activator.CreateInstance(resultType, content, this) as IHttpActionResult;
}

This seems related to the ApplyTo casting the results into something that isn't a Table1 type anymore, but a wrapper for such. But with no exception thrown in the method, I can't figure out where the problem actually is.

I'm using nuGet package 'Microsoft ASP.Net Web API 2.2. for OData V4.0' V5.9.0.

1

1 Answers

0
votes

If i'm reading correctly, I think the issue resides in your declaration of the Foreign Key in Table1. You have it listed with the name 'Table2', but the property below it, which I imagine is the foreign key id from table 2, is named 'Table2ID'.

Try this:

  [Serializable, DataContract]
  public class Table1
  {
    [DataMember, Key]
    public int Id { get; set }
    [DataMember]
    public Table2 Table2 { get; set; }
    [DataMember, ForeignKey("Table2Id")]
    public int Table2Id { get; set;} 
  }

Where your [DataMember, ForeignKey("Table2")] should be changed to [DataMember, ForeignKey("Table2Id")]