You are on page 1of 31

ISM 6225

Distributed
Information Systems
P ROTOT YPICA L AC T I V E WE BS ITE
R EST - APIS, JS ON , DATA BA SE, CHA RTS
Agenda
• Build an active web application
◦ Show common elements of interacting with other applications

• Acknowledgment
◦ Anupam Bhattacherjee (MS BAIS, F17 – F18)

2
Application overview
• The prototypical application
◦ Consumes a REST API from the IEX Trading exchange
◦ Saves the data in a database
◦ Charts the quotes in the view

• Reference application
◦ https://github.com/ISM6225/2018_Fall_Assignment4_ActiveCloudSite

3
Exchanging data
• A common business technology need is to deliver data to end users
◦ And consume data from other providers

• A persistent problem is to retain meaning across systems


◦ How do you transfer a STOCK object from one computer to another

• A data format and delivery mechanism that is readily available is to


transfer strings over the web
• In this example, we consume data from a relatively new stock
exchange
◦ IEX Trading
◦ Received approval to list stocks in 2017

4
Exchanging data
• A common business technology need is to deliver data to end users
◦ And consume data from other providers

• A persistent problem is to retain meaning across systems


◦ How do you transfer a STOCK object from one computer to another

• A data format and delivery mechanism that is readily available is to


transfer strings over the web
◦ Commonly used to transfer data
◦ Described as REST
◦ Representational State Transfer
◦ https://en.wikipedia.org/wiki/Representational_state_transfer
◦ https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

5
Exchanging data
• In this example, we will consume data from a relatively new stock
exchange
◦ IEX Trading
◦ Received approval to list stocks in 2017
◦ Provides a fairly simple API to get stock quotes

• Start with the MVC_EF_Start project


◦ Recommend to fork it
◦ Rename to IEX_Application or similar if possible

6
Reading IEX REST API
• Most programming languages provide a framework to read web data
◦ Usually called HttpClient
◦ We will discuss Http in more detail in the OSI module
◦ https://docs.microsoft.com/en-
us/dotnet/api/system.net.http.httpclient?view=netframework-4.7.2

• Create a new Controller


◦ Name it as IEXTradingController (or similar)

• Start by creating and initializing the HttpClient


◦ Use Ctrl+. To import necessary references

7
Reading IEX REST API
public class IEXTradingController : Controller
{
HttpClient httpClient;

public IEXTradingController()
{
httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new
System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("applicatio
n/json"));
}

}

8
Using the HttpClient
• In the Index action method

string symbol = "AAL"; // American Airlines group


//string symbol = "AAPL"; // Apple Computer

string BASE_URL = "https://api.iextrading.com/1.0/";


string IEXTrading_API_PATH = BASE_URL + "stock/" +
symbol + "/batch?types=chart&range=1y";

HttpResponseMessage response =
httpClient.GetAsync(IEXTrading_API_PATH).GetAwaiter().
GetResult();

9
HttpResponseMessage
• Framework object to
read the Http response
from the server
◦ Use a breakpoint to
view the response from
the IEXTrading API
◦ There is information we
need
◦ And some additional
protocol overhead
◦ We can use appropriate
reader methods to retrieve
the content we need

10
Reading the Http response
string charts = "";

if (response.IsSuccessStatusCode)
{
charts = response
.Content
.ReadAsStringAsync()
.GetAwaiter()
.GetResult();
}

• Use breakpoints to check out the charts string


◦ Has the information we need, as a Json object
◦ But needs to be parsed

11
Parsing the charts Json string
• The C# approach is to first parse Json objects as regular objects
◦ Make sure your Models file has the following classes
◦ ChartRoot
◦ Equity
◦ Company
◦ These class definitions correspond to the Json objects returned by the API
◦ We will shortly see how to create these class definitions

• If the object definitions are present


◦ Parse the Json string into C# objects as follows

12
Parsing the charts Json string
if (!charts.Equals(""))
{
ChartRoot root =
JsonConvert.DeserializeObject<ChartRoot>(charts,
new
JsonSerializerSettings { NullValueHandling =
NullValueHandling.Ignore });
Equities = root.chart.ToList();
}

13
Closing loose ends
• The IEXTrading API does not populate the symbol field
◦ So, we need to populate it

foreach (Equity Equity in Equities)


{
Equity.symbol = symbol;
}

14
Creating C# object definitions
from Json string
• The Visual Studio editor can help you create object definitions
◦ Also, some web sites can do the same
◦ E.g. http://json2csharp.com/

1. Create a break point just after reading the HttpResponseMessage


content
1. charts string in our example
2. Right click the charts string and use the Text Visualizer to copy the string to
the clipboard
3. Stop the application
4. Place cursor at an empty space on the file
1. Edit → Paste Special → Paste Json as classes

15
Implementation in reference
application
• The reference application has this method as
◦ Infrastructure/IEXTradingHandler/IEXHandler.cs/GetChart

• Also, a similar method to get the available symbols in the API


◦ Infrastructure/IEXTradingHandler/IEXHandler.cs/GetSymbols

16
Saving the data to the
database
• We have seen how to save data to the database
◦ The reference application uses the same methods
◦ And some supporting objects to simplify the UI

• Application performs three operations


◦ Accessed from the home page (/Home/index)
◦ Retrieves all symbols in the API
◦ /Home/Symbols
◦ Retrieves the stock chart for a selected symbol
◦ /Home/Chart
◦ Clears the database
◦ /Home/Refresh

17
Retrieving symbols
public IActionResult Symbols()
{
IEXHandler webHandler = new IEXHandler();
List<Company> companies = webHandler.GetSymbols();

//Save companies in TempData for later


TempData["Companies"] = JsonConvert.SerializeObject(companies);

return View(companies);
}

18
Saving symbols to the
database
• To keep things simple, retrieved symbols are saved to a temp object
◦ A representative sample is shown to users
◦ A button is provided to save all symbols

• Symbols.cshtml view

@model IEnumerable<IEXTrading.Models.Company>

@foreach (var item in Model)


{
<tr>
<td>
@Html.DisplayFor(modelItem => item.symbol)

<a id="dbopt" asp-controller="Home" asp-action="PopulateSymbols">


<img src="~/images/button_save-data.png" />
</a>

19
Saving symbols to the
database
• TempData is available for the round trip
◦ Controller response → View → User response
◦ Hence a convenient simple mechanism to save data for later use
◦ In the application, used to save all available symbols
◦ Should have worked without serialization, but does not seem to

• Recall
◦ Companies saved to TempData as
TempData["Companies"] = JsonConvert.SerializeObject(companies);

• We can retrieve the companies in the action method as


List<Company> companies = JsonConvert
.DeserializeObject<List<Company>>(
TempData["Companies"].ToString()
);

20
Saving companies
foreach (Company company in companies)
{
//Database will give PK constraint violation error when trying to insert record with existing PK.
//So add company only if it doesnt exist, check existence using symbol (PK)

if (dbContext.Companies.Where(c => c.symbol.Equals(company.symbol)).Count() == 0)


{
dbContext.Companies.Add(company);
}
}

dbContext.SaveChanges();
ViewBag.dbSuccessComp = 1;
return View("Symbols", companies);

21
Displaying quotes for selected
company
• Retrieving quotes is similar to retrieving symbols
◦ Get Json object with quotes for the selected symbol
◦ /Home/Chart

• Once the quotes are retrieved


◦ We display them using chart.js
◦ Simple, but intuitive charting mechanism
◦ https://www.chartjs.org/
◦ Download chart.js from the site above
◦ Save it in wwwroot/js
◦ Simplest way to make it accessible where needed
◦ Include it in the html layout

22
Chart.js in the layout
• In _Layout.cshtml

<head>
<link rel="stylesheet" href="~/css/site.css" />
<script type="text/javascript" src="~/js/Chart.min.js"></script>

<script type="text/javascript" src="~/lib/chartjs-plugin-annotation-master/chartjs-plugin-annotation.min.js"></script>

<script type="text/javascript" src="~/js/site.js"></script>

</head>

23
Using chart.js
• Chart.js works with comma separated values
◦ The controller therefore needs to pass the appropriate values to the chart
script
◦ In chart.cshtml
<script>
getChart("@Model.Dates", "@Model.Prices", "@Model.Volumes", @Model.AvgPrice, @Model.AvgVolume);

</script>
◦ Preferred at the end of the page
◦ Ensures that the elements are rendered before the script is called

24
Passing values to chart.js
• Linq and utility methods in the string class are helpful to get the values
quickly
◦ Pass these values to the view as part of the view model

string dates = string.Join(",", equities.Select(e => e.date));

string prices = string.Join(",", equities.Select(e => e.high));

string volumes = string.Join(",", equities.Select(e => e.volume / 1000000)); //Divide vol by million

float avgprice = equities.Average(e => e.high);


double avgvol = equities.Average(e => e.volume) / 1000000; //Divide volume by million

25
Displaying the chart
• When using chart.js
◦ The page requires 3 elements

1. A canvas element where the chart will be rendered


2. The data, as csv, that will be charted
3. A call to the JavaScript method
1. Which will use chart.js to render the data as the specified chart

26
Chart.cshtml
• Look at chart.cshtml

1. @model IEXTrading.Models.ViewModel.CompaniesEquities
◦ The data is passed as part of the view model
◦ This model aggregates some entities and other needed values for the page

2. The canvas element


1. Id helps the chart script locate the element on the page

<div>
<canvas id="myChart" height="500" width="800"></canvas>
</div>
3. The script, calling the method which will display the chart
<script>
getChart("@Model.Dates", "@Model.Prices", "@Model.Volumes",
@Model.AvgPrice, @Model.AvgVolume);
</script>

27
Using chart.js
• Let’s start with a simple chart
◦ Add the following method to site.js
◦ Also, change call in chart.cshtml from getChart to getChart1

function getChart1(dates, prices, vols, avgprice, avgvol) {


var ctx = document.getElementById("myChart").getContext('2d');

var myChart = new Chart(ctx, {


type: 'bar',
data: {
labels: dates.split(","),
datasets: [{
data: prices.split(",")
}]
}
});
}

28
Refining the chart
• We can progressively update the chart method
◦ Add the second data series
◦ To display volume
◦ Add colors
◦ Add series labels
◦ Add annotations

29
Next steps
• Deploy to Azure
◦ https://azure.microsoft.com/en-us/free/students/
◦ Should primarily just require a change of the database connection string

30
Summary
• Background
• Code first components
• Entity framework example
• Loose ends
◦ Constraints - Fluent API and Data Annotations
◦ Connection strings - Database selection
◦ Migrations
◦ LINQ

• Entity Framework in MVC

31

You might also like