Extending from base response to a model in C# MVC

Viewed 439

I'm processing responses from an API. API always returns results in the following JSON format:

{
    "Message": null,
    "Sucess: true,
    "Exception": null
    "Result": null
}

So i have created the model BaseResponse for it.

public class BaseResponse
{
    [JsonProperty("Success")]
    public static bool Success { get; set; }

    [JsonProperty("Message")]
    public dynamic Message { get; set; }

    [JsonProperty("Exception")]
    public dynamic Exception { get; set; }
}

Depending on the request i'm sending, the result field can contain data in various formats. Let's say Animal and Car.

e.g. Animal

{
    "Message": null,
    "Sucess: true,
    "Exception": null
    "Result": {"animal_type": "dog", "animal_name": "bobby"}
}

e.g. Car

{
    "Message": null,
    "Sucess: true,
    "Exception": null
    "Result": {"car_type": "4x4", "car_name": "jeep"}
}

So i have also created the models for these various formats.

Animal Model

public class Animal
{
    [JsonProperty("animal_type")]
    public string AnimalType{ get; set; }

    [JsonProperty("animal_name")]
    public string AnimalName{ get; set; }
}

Car Model

public class Car
{
    [JsonProperty("car_type")]
    public string CarType{ get; set; }

    [JsonProperty("car_name")]
    public string CarName{ get; set; }
}

I also extended the BaseResponse so i can cast to the models. e.g.:

public class CarResponse : BaseResponse
{
    [JsonProperty("Result")]
    public Car Car{ get; set; }

    public static CarResponse FromJson(string json) => JsonConvert.DeserializeObject<CarResponse>(json, Converter.Settings);
}

I am sending a HTTP request, reading the response string and casting to corresponding model using JsonConvert. e.g:

string responseBody = await result.Content.ReadAsStringAsync();
CarResponse carResponse = CarResponse.FromJson(responseBody);

I am wondering what is the best practice to cast from the BaseResponse's result field to a model. Is extending BaseResponse and casting the JSON to corresponding response extension the right approach? Or do i cast to BaseResponse and map from the Result field to a model?

2 Answers

This would be a good case for generics. You could for example declare you base class like so:

public class BaseResponse<TResult>
{
    public bool Success { get; set; }
    public dynamic Message { get; set; }
    public dynamic Exception { get; set; }
    public TResult Result { get; set; }
}

That way you could declare your CarResponse class as

public class CarResponse : BaseResponse<Car>
{
}

Or simply deserialize into that generic type

JsonConvert.DeserializeObject<BaseResponse<Car>>(responseBody);

You could go a bit further and make Exception and Message typed as well:

public class BaseResponse<TResult, TMessage, TException>
{
    public bool Success { get; set; }
    public TMessage Message { get; set; }
    public TException Exception { get; set; }
    public TResult Result { get; set; }
}

If you specifically want to call the property Car, you could go with the following (although I would simply use the Result property myself)

public class CarResponse : BaseResponse<Car>
{
    public Car Car => Result;
}

This design is my opinion :

    public class BaseResponse
    {
        [JsonProperty("Success")]
        public static bool Success { get; set; }

        [JsonProperty("Message")]
        public dynamic Message { get; set; }

        [JsonProperty("Exception")]
        public dynamic Exception { get; set; }
    }

    public abstract class BaseObject
    {
        public abstract BaseObject FromJson(string json);
    }
  
    public class Car : BaseObject
    {
        public override BaseObject FromJson(string json)
        {
            return JsonConvert.DeserializeObject<Car>(json);
        }
        [JsonProperty("car_type")]
        public string CarType { get; set; }

        [JsonProperty("car_name")]
        public string CarName { get; set; }
    }

    public class Animal : BaseObject
    {
        public override BaseObject FromJson(string json)
        {
            return JsonConvert.DeserializeObject<Animal>(json);
        }
        [JsonProperty("animal_type")]
        public string AnimalType { get; set; }

        [JsonProperty("animal_name")]
        public string AnimalName { get; set; }
    }

for use:

string responseCar = @"{'car_type': '4x4', 'car_name': 'jeep'}";
Car myCar = new Car();
myCar = (Car)myCar.FromJson(responseCar);

Console.WriteLine(myCar.CarName + "---------" + myCar.CarType);


string responseAnimal = @"{'animal_type': 'dog', 'animal_name': 'bobby'}";
Animal myAnimal = new Animal();
myAnimal = (Animal)myAnimal.FromJson(responseAnimal);

Console.WriteLine(myAnimal.AnimalName + "---------" + myAnimal.AnimalType);
Related