PJDev
PJDev

Reputation: 983

ASP.NET WebApi - two possible JSON "return" types?

A little intro

Hello, I'm developing a WebApi Rest Service and currently I'm working on an endpoint which returns different dictionaries (arrays of entities, don't confuse with Dictionary data type) in JSON format. Dictionaries can be retrieved by name: /dictionaries/:dictName. The problem is that items kept in dictionaries can be of two types:

First type of entities

class Item {
    public long ID { get; set; }
    public string Name { get; set; }
}

Second type of entities - extended item

class ExtendedItem : Item {
    public string AdditionalProperty { get; set; } // Let's name it this way just for example
}

The problem

I'd like to avoid sending AdditionalProperty for dictionaries which don't need it.


Current solution

I've developed a simple method in ApiController:

public IHttpActionResult GetDict(string name)
{
    try
    {
        object outDict = null;

        switch(name) {
            case "simpleDict":
                IList<Item> simpleDict = _dataLayer.GetSimpleDict();
                // ...
                outDict = simpleDict;
                break;
            case "extDict":
                IList<ExtendedItem> extDict = _dataLayer.GetExtDict();
                // ...
                outDict = extDict;
                break;

            // ... and a few more dictionaries
        }

        SomeLogger.SomeLogging(name, outDict);
        return Ok(outDict);
    } 
    catch (Exception ex) 
    {
        // Just returning error
        return BadRequest(ex.Message);
    }

}

Conclusion and questions

Although I managed to find a solution for the problem, I'm not fully satisfied with it. Personally, I'd like to find a simple way to avoid using object data type, however couldn't figure any. And now come the questions:

  1. What would be a better programmatic way of implementing such solution? For me better means solution without using the object type. Is there any easy way to restrict IList to contain either Item or ExtendedItem and no other types?
  2. Or maybe I should completely change the approach to the problem?
  3. Or... Maybe this approach is correct and I'm a bit oversensitive? ;-)

I'll be grateful for any help.

Upvotes: 0

Views: 813

Answers (3)

The Pax Bisonica
The Pax Bisonica

Reputation: 2164

You could just return in the switch statement as well:

public IHttpActionResult GetDict(string name)
{
    try
    {
        switch(name) {
            case "simpleDict":
               return Ok(_dataLayer.GetSimpleDict());
            case "extDict":
               return Ok(_dataLayer.GetExtDict());
        }

        SomeLogger.SomeLogging(name, outDict);
        return Ok(new List<Item>());
    } 
    catch (Exception ex) 
    {
        // Just returning error
        return BadRequest(ex.Message);
    }
}

Upvotes: 0

krillgar
krillgar

Reputation: 12805

If you declare your outDict variable as a collection instead of object, then you'll be able to assign directly.

IEnumerable<Base> outDict = null;

switch(name) {
    case "simpleDict":
        IList<Item> simpleDict = _dataLayer.GetSimpleDict();
        // ...
        outDict = simpleDict;
        break;
    case "extDict":
        IList<ExtendedItem> extDict = _dataLayer.GetExtDict();
        // ...
        outDict = extDict;
        break;

    // ... and a few more dictionaries
}

Upvotes: 1

display name
display name

Reputation: 4185

Try use Interface to free up the implementation for ExtendedItem. Using Object for API return can be useful if you need Type dynamic to process things differently before sending back the callback response.

interface Item {
    public long ID { get; set; }
    public string Name { get; set; }
}

class SimpleItem : Item {
    public long ID { get; set; }
    public string Name { get; set; }
}

class ComplicateItem: Item {
    public long ID { get; set; }
    public string Name { get; set; }
    public string AdditionalProperty { get; set; }
}

Then in the api controller,

    Item outDict;

    switch(name) {
        case "simpleDict":
            var simpleDict = _dataLayer.GetSimpleDict();
            // ...
            outDict = simpleDict;
            break;
        case "extDict":
            var extDict = _dataLayer.GetExtDict();
            // ...
            outDict = extDict;
            break;

        // ... and a few more dictionaries
    }

Upvotes: 0

Related Questions