Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return Json from Generic List in Web API

I build my list like this:

public static List<SearchFormula> SearchData(string searchString)
{
    var searchResults = new List<SearchFormula>();

    SqlDataReader drResults = FormulaUtility.SearchFormulas(searchString);

    if ((drResults != null) && (drResults.HasRows))
    {                
        while (drResults.Read())
        {
            searchResults.Add(new SearchFormula() 
            {  
                // id  use the GetValue function
                Title = drResults.GetString(1),
                Description = drResults.GetString(2), 
                Url = drResults.GetString(3)
                // total use the GetValue Function
                });
            }
        }
    return searchResults;
}

Using this Object:

public class SearchFormula
{
    public string Title { get; set; }

    public string Description { get; set; }

    public string Url { get; set; }
}

I began using the IHttpActionResult, returning the OK(results); function. I believe this is what started me down the confusing road. I had successfully sent an ArrayList but this did not serialize the way I thought it would.

I tried changing it to ActionResult and attempted to return Json(result) Result being the actual list.

I would like to continue to use the IhttpActionResult and send the serialized data with the OK() method. I also seem to be having a conflict between the built-in json serializer and NewtonSoft json serializer.

What should I use. What is the simplest way of just serializing a generic list and passing the result into the IHttpActionResult OK() method?

I tried the JavaScriptSerializer but it returns XML not Json...

public class SearchController : ApiController
{
    public IHttpActionResult Get(string searchTerm)
    {            
        var jsonSerialiser = new JavaScriptSerializer();
        var jsonResult = jsonSerialiser.Serialize(SearchUtility.SearchData(searchTerm));

        if (jsonResult != null)
        {
            return Ok(jsonResult);
        }
        return NotFound();

    }
}

Here is the Json.Net Example:

public class SearchController : ApiController
{
    public IHttpActionResult Get(string searchTerm)
    {   
        var jsonResult = JsonConvert.SerializeObject(SearchUtility.SearchData(searchTerm));

        if (jsonResult != null)
        {
            return Ok(jsonResult);
        }
        return NotFound();        
    }
}

I have tried the MemoryStream... blah blah blah... nothing seems like a clean, straightforward approach and there is no subject matter for this specific solution.

Let me start with this...

How can I serialize a Generic list to Json?

How can I send that result through the IHttpActionResult?

*Update*

This is what I am getting for the serialization from Json.Net. BUT something is wrong with the format... Even Fiddler can not determine that it is Json. My Header looks like this (in Fiddler):

Accept: application/json, text/javascript, /; q=0.01

"[{\"title\":\"Lacidofil®\",\"description\":\"Lacidofil® features Institut Rosell’s Lactobacillus helveticus and Lactobacillus rhamnosus. Both of these strains have been extensively studied in human clinical trials, possess an...\",\"url\":\"/products/product-detail.aspx?pid=103\"},{\"title\":\"MedCaps GI™\",\"description\":\"MedCaps GI™ features ingredients that are designed to nutritionally support the integrity and optimal function of the gastrointestinal lining. Fortified with nutrients such as l-glutam...\",\"url\":\"/products/product-detail.aspx?pid=114\"},{\"title\":\"OrganiX™ PhytoFood™\",\"description\":\"OrganiX PhytoFood is a convenient powdered formulation providing key nutrients to support a healthy lifestyle. This comprehensive formula incorporates an innovative blend of organi...\",\"url\":\"/products/product-detail.aspx?pid=271\"},{\"title\":\"Probio Defense™\",\"description\":\"Probio Defense™ is an optimal combination of probiotic bacteria that supports the immune system.\r\nThis product contains:\r\n\r\nLactobacillus helveticus Rosell-52 (3 billion)\r\nLactobacillu...\",\"url\":\"/products/product-detail.aspx?pid=102\"},{\"title\":\"ProbioMax Daily DF™\",\"description\":\"ProbioMax Daily DF™ is a vegetarian, dairy- and gluten-free, four-strain probiotic totaling 30 billion CFU† per capsule. Each vegetarian capsule is sealed in nitrogen-purged alu...\",\"url\":\"/products/product-detail.aspx?pid=181\"},{\"title\":\"ProbioMax DF™\",\"description\":\"ProbioMax DF™ is a vegetarian, dairy- and gluten-free, four-strain probiotic totaling 100 billion CFU† per capsule. Each vegetarian capsule is sealed in nitrogen-purged aluminum...\",\"url\":\"/products/product-detail.aspx?pid=184\"},{\"title\":\"ProbioMax Plus DF™\",\"description\":\"The multitude of healthful benefits attained by the individual supplementation of probiotic strains of bacteria, the non-pathogenic yeast, Saccharomyces boulardii, immunoglobulins,...\",\"url\":\"/products/product-detail.aspx?pid=185\"},{\"title\":\"Saccharomycin DF™\",\"description\":\"Saccharomycin DF™ is a lactose-free, stomach acid–resistant, stable, European patent-pending formula containing DNA-verified Saccharomyces boulardii. This probiotic yeast support...\",\"url\":\"/products/product-detail.aspx?pid=197\"}]"

like image 275
Brett Spencer Avatar asked Dec 16 '13 21:12

Brett Spencer


People also ask

How do I return a JSON response in API?

To return JSON from the server, you must include the JSON data in the body of the HTTP response message and provide a "Content-Type: application/json" response header. The Content-Type response header allows the client to interpret the data in the response body correctly.

Does Web API return JSON by default?

After developing the WebAPI we need to host the service for client. There are different types of client with different type requirement. Means some client need result in XML format and same time some client need it JSON format. By default Web API returns result in XML format.


2 Answers

I take this approach which seems a lot simpler and does not involve changing the json serializer for the data that you have.

If you return the objects as a list the default media type formatter will handle the serialization based on the content type specified from the client (providing it is json or xml).

For demo purposes add the below methods which return hard coded objects.

    // GET api/search
    public List<SearchFormula> Get(string searchTerm)
    {
        var searchItems = SearchData(searchTerm);
        return searchItems;
    }

    public static List<SearchFormula> SearchData(string searchString)
    {
        var searchResults = new List<SearchFormula>();

        searchResults.Add(new SearchFormula { Description = "desc1", Title = "title1", Url = "http://url.com" });
        searchResults.Add(new SearchFormula { Description = "desc2", Title = "title2", Url = "http://url.com" });

        return searchResults;

    }

Then in fiddler specify the client accepts application/json as pictured below and the content is returned as json.

enter image description here

For further info on serialization see here:

http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization

like image 68
hutchonoid Avatar answered Oct 06 '22 11:10

hutchonoid


I usually serialize to JSON using this extension method:

    public static class Extensions
{
    public static string SerializeToJson<T>(this T obj, DateTimeSerializationFormat format = DateTimeSerializationFormat.DotNet) where T : class
    {
        string result;
        var serializer = new DataContractJsonSerializer(typeof(T));
        using (var stream = new MemoryStream())
        {
            serializer.WriteObject(stream, obj);
            result = Encoding.UTF8.GetString(stream.ToArray());
        }

        if (formaat != DateTimeSerializationFormat.DotNet)
        {
            const string dotNetDateTimePattern = @"""\\/Date\((-?\d+)([\+-]\d{4})?\)\\/""";

            if (format ==DateTimeSerializationFormat.Iso8601 || format ==DateTimeSerializationFormat.Ruby))
            {
                var matchEvaluator = new MatchEvaluator(ConvertJsonDateToIso8601DateString);
                var regex = new Regex(dotNetDateTimePattern);
                resultaat = regex.Replace(resultaat, matchEvaluator);
                if (format == DateTimeSerializationFormat.Ruby && resultaat.Length > 10) // Ruby time
                {
                    result = Regex.Replace(result, @"([\+-]\d{1,2}\:\d{2})", " $0"); // Add an space before the timeZone, for example bv "+01:00" becomes " +01:00"
                }
            }

        }
        return result;
    }

    public enum DateTimeSerializationFormat
    {
        /// <summary>
        /// Example: "\/Date(1198908717056)\/" (aantal miliseconden na 1-1-1970)
        /// </summary>
        DotNet,
        /// <summary>
        /// Example: "1997-07-16T19:20:30.45+01:00"
        /// </summary>
        Iso8601,
        /// <summary>
        /// Example: "1997-07-16T19:20:30.45 +01:00"
        /// </summary>
        Ruby,
        ///// <summary>
        ///// Example: new Date(1198908717056) or other formats like new (date (1997,7,16)
        ///// </summary>
        //JavascriptDateObject
    }

Don't forget to add the using and reference to:

System.Runtime.Serialization.Json;
like image 41
Alex Siepman Avatar answered Oct 06 '22 13:10

Alex Siepman