16

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
}
4
  • 2
    You should not create json by your own, you can return an object from this method and make JSON as default format for returned data. Commented Mar 11, 2016 at 10:02
  • Could you make an example based on the code above? Commented Mar 11, 2016 at 10:12
  • JObect is also a great tool: newtonsoft.com/json/help/html/CreatingLINQtoJSON.htm Commented May 21, 2018 at 5:59
  • Possible duplicate of How to change default Web API 2 to JSON formatter? Commented Jun 19, 2018 at 12:56

2 Answers 2

37

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.

Sign up to request clarification or add additional context in comments.

4 Comments

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?
@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.
Thanks @raderick.. i got it working excatly as i wanted! :)
Remember you can take advantage of anonymous types in any scenario where you are selecting data to be returned as JSON
4

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;
}

2 Comments

This is for MVC, not API
no problem, please take in consideration edit your answer in order to response the OP question and then get my upvote :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.