@section
section"To make sure I'm keeping up with the times I want to build a web page that uses Javascript and asynchronous calls to the web server to create a responsive design solution for a simple problem."
This homework is all about creating a responsive, single-page application. An extreme case of this kind of application is the GMail client. We don't have those kinds of aspirations, but we can definitely get the main process down.
So the page that first loads (from the server) doesn't have any data. It presents the interface only. But it does load your Javascript, which requests data from your server via asynchronous web requests and then builds the page content as desired as the requests come back from your server. Users then interact with the page and more asynchronous calls are placed to send data to and receive data back from your server. The benefit is that, perhaps surprisingly, the time to load HTML, CSS and associated resources, and build and render a DOM, is actually significant. Not doing those things, while using Javascript to retrieve data and modify the DOM, often creates a more responsive page for the user. We want to learn about this as a viable option for building parts of your project next year.
Here's some good documentation from the Mozilla Developer Network. But note, that's plain Javascript. As usual, we'll use jQuery to make it easier.
A second purpose of this homework is to learn how to use an existing API as a resource. Ideally we would use a real REST API like those offered by Lyft (Docs), Twitter (Docs) or Trello (Docs). It is certainly possible to use these. But, examples like these require you to apply for a developer api key or use more advanced authentication methods and additionally be really responsible in how you use it. Yes, of course we'll be responsible, but it would be better to choose something a bit less risky, and easier. The one we'll use isn't a comprehensive REST API, but that's OK. It's safe, kind of silly, easy and you can have your api key in seconds.
We will use an API from Giphy, the world's precious repository of cat and internet meme gifs.
[Setup] Start by creating a simple MVC web application. You want to start with the minimal "Empty" example this time, but check the box to add folders and core references for MVC.
[Content/Coding] Create just a single controller and view that creates one page with a text input. This will be the only view and the only page for the entire HW. Get rid of the nav bar.
[Setup] Next up, go to Giphy and register as a developer. Create an application and they'll give you your API key which you will use to craft GET requests. This key is a secret; treat it like a password. Don't put it anywhere in your source code and certainly not in your repository anywhere. (I'll show you in class how to hide this secret from your repo and still use it in your code.)
Read their documentation and try out their API Explorer so you understand how to use their API. We'll use their Sticker API and the Translate
endpoint. Try out some searches with your key, with their API Explorer, Postman and a browser. I find that using Firefox Developers Edition is really nice for this because it parses the JSON and displays it in tree form with syntax highlighting.
Get to know the correct format and terms for a search as well as the JSON data that is returned.
For example, here is an object that is returned by searching for “lobster” with this request
GET https://api.giphy.com/v1/stickers/translate?api_key=XXXYourKeyHereXXX&s=lobster
{
"data":
{
"type": "gif",
"id": "7hqG8IJQRU1Qk",
"slug": "weird-lobster-transparent-7hqG8IJQRU1Qk",
"url": "https://giphy.com/stickers/weird-lobster-transparent-7hqG8IJQRU1Qk",
"bitly_gif_url": "https://gph.is/1aSHDAX",
"bitly_url": "https://gph.is/1aSHDAX",
"embed_url": "https://giphy.com/embed/7hqG8IJQRU1Qk",
"username": "scottgelber",
"source": "https://time-cop.tumblr.com/post/49629120885/noah-spidermen-macbook-prawn-2013-animated-gif",
"rating": "g",
"content_url": "",
"source_tld": "time-cop.tumblr.com",
"source_post_url": "https://time-cop.tumblr.com/post/49629120885/noah-spidermen-macbook-prawn-2013-animated-gif",
"is_sticker": 1,
"import_datetime": "2013-11-03 00:18:48",
"trending_datetime": "2017-06-26 17:34:10",
"user":
{
"avatar_url": "https://media.giphy.com/avatars/scottgelber/3opUDVNqoB0y.gif",
"banner_url": "",
"profile_url": "https://giphy.com/scottgelber/",
"username": "scottgelber",
"display_name": "Scott Gelber",
"guid": "Z2VsYmVyLnNjb3R0QGdtYWlsLmNvbQ",
"is_verified": true
},
"images":
{
"fixed_height_still":
{
"url": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/200_s.gif",
"width": "216",
"height": "200",
"size": "11676"
},
"original_still":
{
"url": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/giphy_s.gif",
"width": "400",
"height": "371",
"size": "36390"
},
"fixed_width":
{
"url": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/200w.gif",
"width": "200",
"height": "186",
"size": "269913",
"mp4": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/200w.mp4",
"mp4_size": "38405",
"webp": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/200w.webp",
"webp_size": "251982"
},
"fixed_height_small_still":
{
"url": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/100_s.gif",
"width": "108",
"height": "100",
"size": "4633"
},
"fixed_height_downsampled":
{
"url": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/200_d.gif",
"width": "216",
"height": "200",
"size": "50611",
"webp": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/200_d.webp",
"webp_size": "45910"
},
"preview":
{
"width": "228",
"height": "210",
"mp4": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/giphy-preview.mp4",
"mp4_size": "43832"
},
"fixed_height_small":
{
"url": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/100.gif",
"width": "108",
"height": "100",
"size": "99844",
"mp4": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/100.mp4",
"mp4_size": "15908",
"webp": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/100.webp",
"webp_size": "101130"
},
"downsized_still":
{
"url": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/giphy-downsized_s.gif",
"width": "400",
"height": "371",
"size": "36390"
},
"downsized":
{
"url": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/giphy-downsized.gif",
"width": "400",
"height": "371",
"size": "1021609"
},
"downsized_large":
{
"url": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/giphy.gif",
"width": "400",
"height": "371",
"size": "1021609"
},
"fixed_width_small_still":
{
"url": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/100w_s.gif",
"width": "100",
"height": "93",
"size": "4227"
},
"preview_webp":
{
"url": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/giphy-preview.webp",
"width": "155",
"height": "144",
"size": "49166"
},
"fixed_width_still":
{
"url": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/200w_s.gif",
"width": "200",
"height": "186",
"size": "10636"
},
"fixed_width_small":
{
"url": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/100w.gif",
"width": "100",
"height": "93",
"size": "88287",
"mp4": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/100w.mp4",
"mp4_size": "14638",
"webp": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/100w.webp",
"webp_size": "90880"
},
"downsized_small":
{
"width": "400",
"height": "370",
"mp4": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/giphy-downsized-small.mp4",
"mp4_size": "153039"
},
"fixed_width_downsampled":
{
"url": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/200w_d.gif",
"width": "200",
"height": "186",
"size": "45280",
"webp": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/200w_d.webp",
"webp_size": "41440"
},
"downsized_medium":
{
"url": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/giphy.gif",
"width": "400",
"height": "371",
"size": "1021609"
},
"original":
{
"url": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/giphy.gif",
"width": "400",
"height": "371",
"size": "1021609",
"frames": "41",
"mp4": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/giphy.mp4",
"mp4_size": "180633",
"webp": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/giphy.webp",
"webp_size": "895734",
"hash": "847a68e3bb9b70a191b84d87700388fe"
},
"fixed_height":
{
"url": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/200.gif",
"width": "216",
"height": "200",
"size": "301842",
"mp4": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/200.mp4",
"mp4_size": "42016",
"webp": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/200.webp",
"webp_size": "278668"
},
"looping":
{
"mp4": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/giphy-loop.mp4",
"mp4_size": "1448551"
},
"original_mp4":
{
"width": "480",
"height": "444",
"mp4": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/giphy.mp4",
"mp4_size": "180633"
},
"preview_gif":
{
"url": "https://media2.giphy.com/media/7hqG8IJQRU1Qk/giphy-preview.gif",
"width": "143",
"height": "133",
"size": "48866"
},
"480w_still":
{
"url": "https://media1.giphy.com/media/7hqG8IJQRU1Qk/480w_s.jpg",
"width": "480",
"height": "445"
}
},
"title": "weird computer STICKER by Scott Gelber",
"_score": 1111013.2,
"_topScoreQuotient": 0.9999963996957
},
"meta":
{
"status": 200,
"msg": "OK",
"response_id": "5bdc8b284b79706e59cad7cc"
}
}
You get a JSON object which contains a bunch of information about a single sticker that "matches" the translation of your word. Here's that sticker as a small gif: . I used the static version because seeing all these animated gifs drives me nuts. Also inside is id, title, rating, source, and URL's for many versions of the image.
To preview what we're doing, this JSON object is what you get at your server. You'll use C# to parse this, extract what's needed and build a JsonResult
to send to your client.
[Requirements] Now here's the plan.
JsonResult
object, which is then processed by your Javascript code to modify the DOM and display the sticker image.TranslateApi
controller and the Sticker
action method. We want to show that we can do custom routing rather than the default routing.[Content/Coding] Add a database to your project to keep a log of search requests. Make a table that will hold information about requests made to your server. When a request comes in, add an entry to the table with information about the request. You should log things like date/time, what the request was, the IP address of the requestor and the client's browser agent type.
Logging is a very common activity that is very useful when testing code. In production you'd probably only log requests that returned error codes, but we'd like to record everything.