How do I get only a shadowed property, not the base property, to get JSON serialized?

406 views Asked by At

In my ASP.NET MVC web application, I am using the built in Controller.Json() method to serialize an object and send it back to the client in response to an AJAX call. The class of the object being serialized inherits from another class with some shared property names. This is intentional, as I need the property names to match for some reflection that's happening. I am "shadowing" those properties in the derived class so that they can be a different type from their same-name counterpart in the base class. Here's a simplified example:

public class BaseModel
{
    public string Title { get; set; }
    public decimal CleanUpHours { get; set; }
    public decimal InstallHours { get; set; }
}

public class DerivedModel : BaseModel
{
    public new BucketHoursWithCalculations CleanUpHours { get; set; }
    public new BucketHoursWithCalculations InstallHours { get; set; }
}

When I serialize an instance of DerivedModel, my JSON object on the client contains only the decimal versions of CleanUpHours and InstallHours, not my custom class BucketHoursWithCalculations.

Inspecting the object in Visual Studio before it gets serialized shows both the base and derived versions of those properties, as shown here (please excuse all the extra properties — my sample classes above are more simplified than what I'm actually using, but the principle is the same):

Visual Studio

Here's what that object looks like on the client once it's serialized into JSON:

ng-inspector in Chrome

As you can see, the derived/shadowed properties were not serialized, and the base properties were, but only in the cases where there was a name conflict (for example, the Title property in the base model serialized just fine).

How can I serialize only the shadowed properties where there's a name conflict? I don't believe changing the access modifiers (i.e. from public to protected or something) on the base properties will work in my case, because the BaseModel is used by Entity Framework, and must have public properties. Any help would be appreciated.

1

There are 1 answers

1
dana On BEST ANSWER

One idea is to define type parameter on the base model that is used for the hours properties. Then, define derived models for decimal and BucketHoursWithCalculations. I would be interested to see how BucketHoursWithCalculations serializes to JSON, but in any case the CleanUpHours and InstallHours properties should be serialized.

// use a type parameter on the base model that must be specified
// in derived models.
public class BaseModel<THours>
{
    public string Title { get; set; }
    public THours CleanUpHours { get; set; }
    public THours InstallHours { get; set; }
}

// hours are specified as decimals
public class DecimalModel : BaseModel<decimal>
{
}

// hours are specified as BucketHoursWithCalculations    
public class BucketHoursWithCalculationsModel : BaseModel<BucketHoursWithCalculations>
{
}

// usage
DecimalModel d = new DecimalModel();
d.CleanUpHours = 1.0M; // CleanUpHours is a decimal here

BucketHoursWithCalculationsModel b = new BucketHoursWithCalculationsModel();
b.CleanUpHours = new BucketHoursWithCalculations();
b.CleanUpHours.SomeProperty = 1.0M;