ASP.NET WEB API in practice

Originally posted by myself on 7/1/2016 at http://rchannel.azurewebsites.net/ChannelR/Details/25

RUN AN HTTP SERVICE ON MVC AND WPF; STEP IN THE BASIC ASP.NET WEB API WORLD.

PREREQUISITES

SCAFFOLDING

  • Create a empty web app and using the default template check the Web API check box.
  • Create an empty Web Api Controller named “ValuesController”
  • Add the following code to that controller:
public class ValuesController : ApiController
{
public IHttpActionResult Get()
{
return Ok (new []{"a","b"});
}
}

Explanation of code: 
we created an action for the get Result of the Values Controller.
in that action we have returned an array of “a” and “b” those datatype would be converted based on the client request.

Learn more about IHttpActionResult here:

  1. http://www.c-sharpcorner.com/blogs/a-new-way-to-send-response-using-ihttpactionresult1
  2. http://stackoverflow.com/questions/21758615/why-should-i-use-ihttpactionresult-instead-of-httpresponsemessage
  • Run the app and go to yourlocalhostcodehere/api/values.

Result from the Google Chrome Web Browser:

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<ArrayOfstring xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<string>a</string>
<string>b</string>
</ArrayOfstring>

CREATING AN MVC APP

  • Create a new MVC App and check the Web API check box on its creation.
  • Add a new class called “Coffee” to the models folder
  • Add these using statements to that class:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
  • Add some properties (shortcut prop tab+ tab)
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int Volume { get; set; }

[ForeignKey("Company")]
public int CompanyID { get; set; }
public Company Company { get; set; }
  • Notice that the Attributes [Key] is used to specify that Id is the primary key of your table, on the other hand [ForeignKey(“Company”)] is stating that CompanyID is the Foreign Key of the table’s column Company.
  • Add the Company Class in the same file as shown below:
public class Company
{
[Key]
public int Id { get; set; }
public string CompanyName { get; set; }
}
  • Build project
  • Add new MVC 5 controller with read/write actions using Entity Framework
  • Add Coffee class as your model and create a new datacontext (using the Entity framework code first approach)
  • Add another MVC 5 controller with read/write actions using Entity Framework (name it Companies)
  • Add Company class as your model and use the same datacontext which you previously created (using the Entity framework code first approach)
  • Click Run, navigate to yourlocalhostnamehere/companies/Create
  • Populate your database using your web browser.

Result after population (your data might be different):

ADDING WEB API TO THE MVC APP

  • Right Click the controller folder and add a new folder named API in it.
  • To the previously created folder Add an Web API 2 Controller with actions, using Entity Framework.
  • Add Coffee class as the model class and use the same datacontext which we previously created when developing the MVC App.
  • Check the “Use async controller actions” check box to have acync action methods be generated.
  • Create another controller similar to the one that we previously created but this time:
  1. The model class is Companies
  2. The Controller name is CompaniesController.

Result on Chrome:

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<ArrayOfCoffee xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/WebAPIDemo.Models">
<Coffee>
<Company i:nil="true"/>
<CompanyID>1</CompanyID>
<Id>1</Id>
<Name>Long Black</Name>
<Volume>100</Volume>
</Coffee>
<Coffee>
<Company i:nil="true"/>
<CompanyID>1</CompanyID>
<Id>2</Id>
<Name>Capucino</Name>
<Volume>200</Volume>
</Coffee>
</ArrayOfCoffee>
  • Notice that the company column is currently returning null, to return a value from that column:
  • Go to your API folder and double click on the CoffeesController
  • Change your GetCoffee Action method as shown below:
public IQueryable<Coffee> GetCoffees()
{
return db.Coffees.Include(a=> a.Company);
}

Run the app again and navigate to http://Yourlocalhost/api/coffees

Result on Google Chrome after modification:

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<ArrayOfCoffee xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/WebAPIDemo.Models">
<Coffee>
<Company>
<CompanyName>Starkbucks</CompanyName>
<Id>1</Id>
</Company>
<CompanyID>1</CompanyID>
<Id>1</Id>
<Name>Long Black</Name>
<Volume>100</Volume>
</Coffee>
<Coffee>
<Company>
<CompanyName>Starkbucks</CompanyName>
<Id>1</Id>
</Company>
<CompanyID>1</CompanyID>
<Id>2</Id>
<Name>Capucino</Name>
<Volume>200</Volume>
</Coffee>
</ArrayOfCoffee>
Notice that the company object’s properties CompanyName and Id ‘values are now being displayed.

MVC VS WEB API CONTROLLERS

  1. MVC controller is for people — (the output is html)
  2. Web API is for the robots and mobile applications — (the output is json, xml and so on.)

USING WEB API ON AN WPF APP

  • Create a new WPF app (New project)
  • Using the NuGet Package Manager for solution add the following libraries to your project:
  1. Microsoft http client libraries (To do HTTP commands to get data which may be in json format)
  2. Microsoft ASP.NET Web API client libraries (To convert data such as raw json data, into .Net objects)
  • From the toolbar ,drag and drop the followings to your MainWindow:

1 button 
1 textblock

  • Name the textblock “CoffeeTextBlock” as shown below:
<TextBlock x:Name="CoffeeTextBlock" HorizontalAlignment="Left" Margin="129,117,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Height="132" Width="238"/>
  • Double click the button that you previously drag and drop.
  • Create a new folder named “models”
  • In the model folder, Create a class named Coffee.cs and add the following in it:
public class Coffee
{

public int Id { get; set; }
public string Name { get; set; }
public int Volume { get; set; }
      
public int CompanyID { get; set; }
public Company Company { get; set; }
}
    public class Company
{

public int Id { get; set; }
public string CompanyName { get; set; }
}
  • Go to the MainWindow.xaml.cs and add the following using statements to it:
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Windows;
using WpfAppDemo.Models;
  • Go to your button click event that you previously generated and add the following code to it:
Notice that your localhost url might be different.
var client = new HttpClient();
var response = await client.GetAsync("http://localhost:5710/api/coffees");
var results= await response.Content.ReadAsAsync<IEnumerable<Coffee>>();

Display the content to the previously dragged and dropped textblock “CoffeeTextBlock” through the following c# code:

var sb = new StringBuilder();
foreach (var coffee in results)
{
var text = string.Format("Name: {0}, Volume: {1}, Company: {2}", coffee.Name, coffee.Volume, coffee.Company.CompanyName);
sb.AppendLine(text);
}
CoffeeTextBlock.Text = sb.ToString();

Run both the Web Api App that we previously created and the WPF app together.
Then click on the button on the Main Window from the WPF app.

Result from the wpf app on Button click.

Notice that the WPF app retrieved, converted and displayed data from the web api app that we created previously.

AJAX + WEB API = AWESOME

  • Open the Web API app we previously created
  • Go to View > Home > About.cshtml
  • Replace the code on About.cshtml with the following code:
@{
ViewBag.Title = "About";
}
<h2>@ViewBag.Title.</h2>
<h3>@ViewBag.Message</h3>
 
@*Loading image*@
<div id='loadingmessage' >
<img src='http://digitalsynopsis.com/wp-content/uploads/2015/10/gif-icons-menu-transition-animations-eatstreet-loading.gif' />
</div>
@*Outputing data into the following div*@
<div id="coffeeData"></div>
@*Adding arbitrary javascript code*@
@section script
{
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script>
$('#loadingmessage').show(); // show the loading message.
//We need to get the data and display it
$.ajax({
//From where we want to take information
url: "http://localhost:5710/api/coffees",
//This is the type of http command that we are making (get/post/delete/put)
type: "Get",
        //Telling the system "if the data comes correctly then go to success method else go to error method"
success: function(data)
{
for(var i =0; i< data.length; i++)
                //Appending (adding/displaying to div with id "coffeeData") the content to the database in a formated way.
$('#coffeeData').append("<p>Name: " + data[i].Name + " " + data[i].Volume + "</p>");
$('#loadingmessage').hide(); // hide the loading message
},
        error: function (msg)
{
alert(msg);
}
     });
</script>
}
Notice that your jQuery file reference might be different than the one provided in the above code.
  • Go to your _Layout.cshtml file and include the following code in it:
@RenderSection("script")

Result on Google Chrome:

Notice that the database content loads soon after the web page loaded; this is helpful when you only want to load a specific content instead of loading the whole page again.