Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OData include "Custom Properties" added to Entity Framework models via Partial Classes

I made a partial class file to add new properties to my Entity-Framework generated model.

I am using WebAPI + OData, and the $metadata doesn't list my new/custom properties, and so the JSON it returns doesn't include my new/custom properties.

For example, let's say my Entity is "Person"

"Person" has one Database property; NumSpouses; an int which is returned in $metadata like this: <Property Name="NumSpouses" Type="Edm.Int32"/>

That's great, but I added a property like this to a separate file, with a partial class:

public partial class Person {
  ...
  public string MarriedStatus { 
     get { return this.NumSpouses==0 ? "Single" : "Married"; }
  }
  ... 
}

How can I get this Property available in my OData responses?

<Property Name="MarriedStatus" Type="Edm.String"/>

Currently, if I asked for MarriedStatus in $expand (as if it were a NavigationProperty.... which it's not [I thought I'd try $expand anyway as if it magically provided custom properties]), I'd get a message like this:

{
  "odata.error":{
    "code":"","message":{
      "lang":"en-US","value":"The query specified in the URI is not valid. Could not find a property named 'MarriedStatus' on type 'fakeDataModels.Person'."
},"innererror":{
  "message":"Could not find a property named 'MarriedStatus' on type 'fakeDataModels.Person'.","type":"Microsoft.Data.OData.ODataException","stacktrace":"   at ..."
    }
  }
}
like image 815
The Red Pea Avatar asked Mar 31 '16 22:03

The Red Pea


2 Answers

MarriedStatus is a calculated/readonly property. The ASP.NET implementation of OData does not currently support such properties. As a workaround, add a setter that throws NotImplementedException.

    public string MarriedStatus {
        get { return this.NumSpouses > 0 ? "Married" : "Single"; }
        set { throw new NotImplementedException(); }
    }

Optionally, if you are using OData V4, you can annotate MarriedStatus to specify that it is calculated. See Yi Ding's answer to OData read-only property. But the annotation is advisory only; it does not prevent clients from attempting to set a calculated property (e.g., in a POST request).

like image 105
lencharest Avatar answered Sep 22 '22 15:09

lencharest


In addition to the answer of lencharest. You should use the Ignore() function of the Entity Framework fluent API instead of the [NotMapped] attribute. Because OData looks for this attribute to ignore properties for serialization. If you use the fluent API you will not have this problem.

dbModelBuilder.Entity<TEntity>()
    .Ignore(i => i.ComputedProperty);
like image 30
bdebaere Avatar answered Sep 21 '22 15:09

bdebaere