2

I have web api controller like this:

public class ParentController : ApiController
{
    [HttpGet]
    public IHttpActionResult GetParent()
    {
        //instatiating child class
        var child = new Child
        {
            ChildProp1 = "childValue1",
            ChildProp2 = "childValue2",
            ParentProp1 = "parentValue1",
            ParentProp2 = "parentValue2"
        };

        //up casting is implicit
        Parent parent = child;

        //returning parent as Json http request
        return Ok(parent);
    }

    private class Child : Parent
    {
        public string ChildProp1 { get; set; }
        public string ChildProp2 { get; set; }
    }

    private class Parent
    {
        public string ParentProp1 { get; set; }
        public string ParentProp2 { get; set; }
    }
}

and it works perfectly except it return Json result of both parent and child properties and What I need is only properties of parent class

Output response body:

{
    "childProp1": "childValue1",
    "childProp2": "childValue2",
    "parentProp1": "parentValue1",
    "parentProp2": "parentValue2"
}   

Thanks!

Behzad Bahmanyar
  • 6,195
  • 4
  • 35
  • 41
  • 1
    Your not casting it, you're assigning the child object to a reference of Parent object. It's still a child object underneath. The serialisation class obviously understands this. – Liam Dec 04 '15 at 14:01
  • 2
    If you need only the properties of the parent class, then why are you creating a child? – crashmstr Dec 04 '15 at 14:01

2 Answers2

3
  1. You could return an anonymous type

    return Ok(new { ParentProp1 = parent.ParentProp1, ParentProp2 = parent.ParentProp2 });

  2. You could add the JsonIgnore attribute to the Child properties (though this would mean that you wont be able to return them as JSON in other pieces of code.)

    [JsonIgnore]
    public string ChildProp1 { get; set; }
    
    [JsonIgnore]
    public string ChildProp2 { get; set; }
    
  3. You could create an interface IParent with only the parent properties ParentProp1 and ParentProp2 and then use a custom contract resolver (as seen in this question) with JsonSerializerSettings.ContractResolver to tell it to serialize only the interface properties.

    return Json(parent, new JsonSerializerSettings {
      ContractResolver = new InterfaceContractResolver (typeof(IParent))
    });
    

Option #3 is probably the best because unlike Option #1 you would only have to redefine your properties in the interface instead of possibly in multiple HttpGet methods that return anonymous types. Also, unlike Option #2, you wouldn't be restricted from returning your child properties as JSON from other HttpGet methods.

Community
  • 1
  • 1
skeletank
  • 2,880
  • 5
  • 43
  • 75
  • Thanks for extended answer. I agree with with on choosing option #3. but after testing it the response body in PostMan now looks like this `{\"ParentProp1\":\"parentValue1\",\"ParentProp2\":\"parentValue2\"}`. I haven't test it on real client yet but why it has different format compare to default format in my post? – Behzad Bahmanyar Dec 04 '15 at 15:01
  • 1
    @BehzadBahmanyar Try returning from your `GetParent` method using `return Json(parent, new JsonSerializerSettings { ContractResolver = ... })`. If you return it as a string through the `Ok` method then it is probably using the default serializer and not the JSON.NET one. I'll update my answer accordingly. – skeletank Dec 04 '15 at 15:21
1

Although you are casting it, the instance is still actually a Child so when the JSON serializer does parent.GetType() it ends up with Child and gets the properties of Child.

If you want the result to just be the properties of Parent then you need to just create an instance of Parent to start with.

Trevor Pilley
  • 16,156
  • 5
  • 44
  • 60
  • He's not casting it, casts are always explicit. An implicit conversion isn't a cast – Liam Dec 04 '15 at 14:03
  • @Liam you're wrong, copy that code into a console app and do `parent.GetType()` and it'll return `Child` - it isn't doing a conversion it's doing a cast – Trevor Pilley Dec 04 '15 at 14:05
  • You mean instantiate the Parent then map the child properties one by one to it Or use libraries like automapper for mapping.is there any other way? – Behzad Bahmanyar Dec 04 '15 at 14:07
  • @BehzadBahmanyar or just create the parent initially, why create the child if you only care about the parent? – Trevor Pilley Dec 04 '15 at 14:08
  • Because technicality all of of parent properties are in it's child too. – Behzad Bahmanyar Dec 04 '15 at 14:09
  • Yes but if you don't need the extra properties of `Child` why are you creating a `Child`? – Trevor Pilley Dec 04 '15 at 14:10
  • Consider I have a method with Child return type that is called from two part of server. In one part I need to use the Child properties too but in the other part I only need the Parent props. – Behzad Bahmanyar Dec 04 '15 at 14:14
  • your missing my point, your answer is right, but this isn't a cast per se, [Explicit conversions (casts): Explicit conversions require a cast operator](https://msdn.microsoft.com/en-us/library/ms173105.aspx). A cast is a conversion, not every conversion is a cast – Liam Dec 04 '15 at 16:07
  • @Liam - this is not a conversion because the underlying object isn't converted from a `Child` to a `Parent` it's just the variable that is changed if you did `Parent parent = (Parent)child;` it would behave exactly the same as it does here. – Trevor Pilley Dec 04 '15 at 16:33