0

I'm new to ASP.NET MVC and have an existing API which returns JSON. This API exists on another server and I need to make a server-to-server call to API and bind the resultant data to a Model so that it can be used within other parts of this web app I'm making.

I tried searching for this and it seems like it exists but I can't find the basic documentation for it or how to implement it.
I could make each component (make HTTP request, parse the JSON, set a model to use the data), but I'd hate to re-invent the wheel (and probably do it poorly) if this is something that is already in the library.

Example of the API call:

http://example.info/feeds/feed.aspx?alt=json-in-script

response:

{
    "version": "1.0",
    "encoding": "UTF-8",
    "feed": {
        "updated": {
            "$t": "2014-07-08T13:58:21-05:00"
        },
        "id": {
            "$t": "http://example.info/feeds/feed.aspx"
        },
        "title": {
            "type": "text",
            "$t": "Example Calendar of Events"
        },
        "link": [
            {
                "rel": "alternate",
                "type": "text/html",
                "href": "http://feed.example.edu/search/"
            },
            {
                "rel": "alternate",
                "type": "application/json",
                "title": "JSON",
                "href": "http://example.info/feeds/feed.aspx?alt=json"
            },
            {
                "rel": "alternate",
                "type": "text/calendar",
                "title": "iCal",
                "href": "http://example.info/feeds/feed.aspx?alt=ical"
            },
            {
                "rel": "self",
                "type": "application/atom+xml",
                "title": "ATOM Feed",
                "href": "http://example.info/feeds/feed.aspx"
            }
        ],
        "author": [
            {
                "name": {
                    "$t": "Example!!"
                },
                "email": {
                    "$t": "web@example.edu"
                }
            }
        ],
        "gd$where": [
            {
                "valueString": "Chicago, IL, US"
            }
        ],
        "gCal$timezone": {
            "value": "America/Chicago"
        },
        "entry": [
            {
                "category": [
                    {
                        "scheme": "http://schemas.google.com/g/2005#kind",
                        "term": "http://schemas.google.com/g/2005#event"
                    },
                    {
                        "term": "Current Students"
                    },
                    {
                        "term": "Faculty"
                    },
                    {
                        "term": "Staff"
                    }
                ],
                "published": {
                    "$t": "2012-03-06T20:57:24+00:00"
                },
                "updated": {
                    "$t": "2012-03-06T20:57:24+00:00"
                },
                "id": {
                    "$t": "http://example.info/feed/?eventid=74289"
                },
                "gCal$uid": {
                    "value": "e72724e9-34eb-41dd-a75a-78d1577cb98a.127924@feed.example.edu"
                },
                "title": {
                    "type": "text",
                    "$t": "Last Day of Sessions 1 & 4 Classes"
                },
                "content": {
                    "type": "html",
                    "$t": "<p>Session 1 &amp; 4 period ends today.</p>"
                },
                "summary": {
                    "type": "text",
                    "$t": "Session 1 & 4 period ends today."
                },
                "author": [
                    {
                        "name": {
                            "$t": "Office"
                        },
                        "email": {
                            "$t": "registrar@example.edu"
                        }
                    }
                ],
                "gd$who": [
                    {
                        "rel": "http://schemas.google.com/g/2005#event.organizer",
                        "valueString": "Registrar, Office of the"
                    },
                    {
                        "rel": "http://schemas.google.com/g/2005#event.attendee",
                        "valueString": "Current Students"
                    },
                    {
                        "rel": "http://schemas.google.com/g/2005#event.attendee",
                        "valueString": "Faculty"
                    },
                    {
                        "rel": "http://schemas.google.com/g/2005#event.attendee",
                        "valueString": "Staff"
                    }
                ],
                "gd$organization": [
                    {
                        "label": "Campus",
                        "primary": "true",
                        "gd$orgName": {
                            "$t": "Chicago"
                        }
                    }
                ],
                "gd": {
                    "value": "http://schemas.google.com/g/2005#event.opaque"
                },
                "link": [
                    {
                        "rel": "alternate",
                        "type": "text/html",
                        "href": "http://feed.example.edu/viewevent.aspx?eventid=74289&occurrenceid=127924"
                    }
                ],
                "gCal$sequence": {
                    "value": "0"
                },
                "gd$when": [
                    {
                        "startTime": "2014-07-30",
                        "endTime": "2014-07-31"
                    }
                ],
                "gd$where": [
                    {
                        "valueString": "Classes administered by the Chicago Campus"
                    }
                ]
            },
            ...
        ]
    }
}

Edit:

I just now found this article on Calling a Web API From a .NET Client, which is in-line with what I'm trying to ask with this question, but I need to know how to do this in an ASP.NET MVC context, not a console application.

Kyle Falconer
  • 8,302
  • 6
  • 48
  • 68

2 Answers2

3

To call an external API you can use the HttpClient. Personally, I would wrap the calls to the API in their own class akin to the repository pattern.

public class ApiCaller
{    
    /*
      this is the repository that can wrap calls to the API
      if you have many different types of object returned
      from the API it's worth considering making this generic
    */
    HttpClient client;

    public SomeClass Get()
    {
        SomeClass data;

        string url = "http://example.info/feeds/feed.aspx?alt=json-in-script";

        using (HttpResponseMessage response = client.GetAsync(url).Result)
        {
            if (response.IsSuccessStatusCode)
            {
                data = JsonConvert.DeserializeObject<SomeClass>(response.Content.ReadAsStringAsync().Result);
            }
        }
        return data;
    }
}

Then in the controller I would call the ApiCaller to get the object required at which point in this instance I'm just passing it to a view:

public class MyController : Controller
{
    ApiCaller caller;

    public MyController()
    {
        //maybe inject this dependency
        ApiCaller = new ApiCaller();
    }

    public ActionResult Index()
    {
        SomeClass model = ApiCaller.Get();

        //do something with the instance if required

        return View(model);
    }
}

The ApiCaller can then be extended if required to support posts, puts etc. If you have many different entities on the API that you wish to handle you can make an ApiCaller per entity or you could potentially use generics.

petelids
  • 12,305
  • 3
  • 47
  • 57
  • And how would I bind this to a Model? That's the whole point of my question. I know how to make HTTP requests, but it's the ASP.NET part which I'm missing. – Kyle Falconer Jul 30 '14 at 14:35
  • In my example your model would be the class `SomeClass`. I'm using the built in serializer to serialize the response into an object. Is that what you're after or are you looking to auto generate a model class? – petelids Jul 30 '14 at 14:38
  • what would the rest of the structure look like? Would this snippet of code that makes the actual request go in the controller? some global class? – Kyle Falconer Jul 30 '14 at 14:51
  • I would typically put it outside in a repository and treat it the same as a database call. You could then make that generic and make `SomeClass` a `T` instead which would obviously make it easier to call different end points that return different results. – petelids Jul 30 '14 at 14:55
  • This ended up being closest to what my final solution was, so I'll award the answer. The other part which was kinda glazed over (the building of the JSON/response model) I talk about in this other answer: http://stackoverflow.com/a/25063661/940217 – Kyle Falconer Aug 04 '14 at 13:38
0

You must change from ActionResult to JsonResult. Also you can create a derived class as I did or use native class JsonResult.

public JsonResult CheckTimeout()
{
    return Json(new JsonReturn { Success = true, ResponseData = new object() });
}

[Serializable]
public class JsonReturn : JsonResult
{
    public JsonReturn()
    {
        Success = true;
        Message = string.Empty;
        ResponseData = null;
    }

    public JsonReturn(object obj)
    {
        Success = true;
        Message = string.Empty;
        ResponseData = obj;
    }

        public bool Success { get; set; }
        public string Message { get; set; }
        public object ResponseData { get; set; }        
    }
}
gandarez
  • 2,609
  • 4
  • 34
  • 47