Build JSON response in Web API controller

98,499

Solution 1

So here are the changes for your post:

First, you should make your api return Json by default when you pass a text/html request (is this you are looking for?), adding this line to your WebApiConfig class:

config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));

Second, I changed the code to return a real object, impersonating your response:

public class ProductApiCollection
{   
    public ProductApi[] Products { get; set; }      
    public byte Status { get; set; }
}

public class ProductApi
{
    public string Name { get; set; }
}

Method body:

public ProductApiCollection Get()
{
    var result = new ProductApiCollection();
    var dbProducts = db.Products;
    var apiModels = dbProducts.Select(x => new ProductApi { Name = x.Name } ).ToArray();
    result.Products = apiModels;

    var status = db.Status.Any() ? 1 : 0;
    result.Status = status;

    return result;
}

This will results in the following example json:

{
  "Products": [
    {
      "Name": "Pork"
    },
    {
      "Name": "Beef"
    },
    {
      "Name": "Chicken"
    },
    {
      "Name": "Salad"
    }
  ],
  "Status": 1
}

I strongly advise you not to do manual formatting for such things, and rely on built-in and 3rd party libraries. Otherwise, you will be reinventing the things already available, tested and ready to work.

Solution 2

Just as raderick mentioned, you don't need to create your own custom JSON infrastructure.

public class ProductApi
{
    public int Id {get;set;}
    public string Name { get; set; }
}

public class ResponseDTO
{
    public int Status {get;set;}
    public List<ProductApi> { get; set; }
}

And in your API action, return like this:

[Route("{value:int}")]
public ResponseDTO GetProducts(int value)
{
    ResponseDTO result = ...// construct response here 

    return result;
}
Share:
98,499
brother
Author by

brother

Updated on July 22, 2022

Comments

  • brother
    brother almost 2 years

    In a WebAPI project, i have a controller that checks a status of a product, based on a value the user enters.

    Lets say they enter "123" and the response should be "status": 1, AND a list of products. If they enter "321" the "status" is 0, AND a list of products.

    My question is, how do i build such a string correct in a WebAPI controller.

    [Route("{value:int}")]
    public string GetProducts(int value)
    {
        var json = "";
        var products = db.Products;
        if (products.Any())
        {
            foreach (var s in products)
            {
                ProductApi product = new ProductApi();
                product.Name = s.Name;
                json += JsonConvert.SerializeObject(supplier);
            }
        }
    
        var status = db.Status;
        if (status.Any())
        {
            json += "{status:1}";
        }
        else
        {
            json += "{status:0}";
        }
    
        return json;
    }
    
    public class ProductApi
    {
        public string Name { get; set; }
    }
    

    Also, is this output/response considered valid?

    [
        {
            "id":1,
            "name":"product name"
        },
        {
            "id":2,
            "name":"product name 2"
        },
        {
            "id":3,
            "name":"product name 3"
        }
    ]
    
    {
        "status": 0
    }
    
  • brother
    brother about 8 years
    Seems like what i am looking fore. Just one question though: How do i iterate through db.Products to add them, instead of the manual "new ProductApi" in your example? I need to wrap the new ProductApi in a ForEach basicly?
  • Red
    Red about 8 years
    @brother, I updated the answer with simple sample code using db, please take a look. Also consider that if you have a lot of products, this method will be very slow, so paging is a good thing to consider from the start.
  • brother
    brother about 8 years
    Thanks @raderick.. i got it working excatly as i wanted! :)
  • Leandro Bardelli
    Leandro Bardelli almost 7 years
    This is for MVC, not API
  • Leandro Bardelli
    Leandro Bardelli almost 7 years
    no problem, please take in consideration edit your answer in order to response the OP question and then get my upvote :)
  • Firegarden
    Firegarden almost 7 years
    Remember you can take advantage of anonymous types in any scenario where you are selecting data to be returned as JSON