Exchange Json Data with Web API

Web API is the ultimate .NET Framework which allows you to exchange data with a service through HTTP requests. You can send data to it or get back different types of data but the most common usage is the Json format. This post will show you how to send GET, POST, PUT or DELETE HTTP requests to your Web API infrastructure, in order to retrieve, add, update or delete a resource respectively. We are going to use the HttpClient class to make our HTTP client requests. Our solution, will apart by a basic API controller which is going to support all HTTP methods and a simple WebForm page which is going to play the User Interface role.
exchJsonwebapi_01

Let’s do it. In Visual Studio create a new ASP.NET MVC 4 Web Application named WebAPIExchangeJsonData choosing the Web API template. Add a Product class file inside the Models folder and paste the following code. This class will be our model class.

namespace WebAPIExchangeJsonData.Models
{
    public class Product
    {
        public int Id;
        public string Name;
        public decimal Price;
    }
}

Next we are going to create the Web API infrastructure, so create a new Empty API controller named ProductController inside the Controllers folder. Paste the following code.

public class ProductController : ApiController
    {
        //Initialize some Products
        public static List<Product> products = InitProducts();

        public IEnumerable<Product> Get()
        {
            return products;
        }

        public Product Get(int id)
        {
            return products.Where(c => c.Id == id).FirstOrDefault();
        }

        public void Post(Product product)
        {
            products.Add(product);
        }

        public void Put(Product newProduct)
        {
            Product product = products.Where(c => c.Id == newProduct.Id).FirstOrDefault();
            products.Remove(product);
            products.Add(newProduct);
        }

        public void Delete(int id)
        {
            Product pDel = products.Where(p => p.Id == id).FirstOrDefault();
            products.Remove(pDel);
        }

        private static List<Product> InitProducts()
        {
            List<Product> products = new List<Product>();
            products.Add(new Product
            {
                Id = 1,
                Name = "Product P1",
                Price = 15m
            });
            products.Add(new Product
            {
                Id = 2,
                Name = "Product P2",
                Price = 45m
            });
            return products;
        }
    }

This is a simple API controller that can serve all HTTP methods. It has a static list of Product items, which are initialized with two products. It’s time to start creating our User Interface. Right click in your project and create a Web Form page named Default.aspx. Change it’s contents to the following in order to create the Image you saw at the beginning of this post. Before running the page, make sure you switch to Design mode and double click all buttons, otherwise you are going to receive an error saying that click events aren’t defined yet.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebAPIExchangeJsonData.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body style="background-color: darkslategrey;">
    <form id="form1" runat="server">
    <div style="width:830px; background-color:lightsteelblue; margin:0 auto;padding-left:8px;float:left;margin-left:190px;">
        <div style="float:left">
    <h3>All Products</h3>
        <div style="background-color:royalblue; width:390px">
            <span style="color:white">Get All Available Products:</span>&nbsp;&nbsp;&nbsp; <asp:Button ID="btnGetAllProducts"
                 runat="server" Text="Get Products" OnClick="btnGetAllProducts_Click" />
            <br />
            <asp:Label ID="lblAllProducts" ForeColor="White" runat="server" Text=""></asp:Label>
        </div>

        <h3>Product By ID</h3>
        <div style="background-color:#800000; width:390px">
            <span style="color:white">Get Product By ID:</span> <asp:TextBox ID="txtProductId" runat="server"></asp:TextBox>
            &nbsp;&nbsp;
            <asp:Button ID="btnGetProductByID"
                 runat="server" Text="Get Product" OnClick="btnGetProductByID_Click"/>
            <br />
            <asp:Label ID="lblProduct" ForeColor="White" runat="server" Text=""></asp:Label>
        </div>
        <h3>New Product</h3>
        <div style="background-color:#009999; width:390px">
            <span style="color:white">Post New Product:</span><br />
            Product ID:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <asp:TextBox ID="txtNewProductId" runat="server"></asp:TextBox><br />
            Product Name:&nbsp; <asp:TextBox ID="txtNewProductName" runat="server"></asp:TextBox><br />
            Product Price:&nbsp;&nbsp; <asp:TextBox ID="txtNewProductPrice" runat="server"></asp:TextBox>&nbsp;
            <asp:Button ID="btnPostProduct"
                 runat="server" Text="Post Product" OnClick="btnPostProduct_Click"/>
            <br />
            <br /><br />
            <asp:Label ID="lblProductPosted" ForeColor="White" runat="server" Text=""></asp:Label>
        </div>
            </div>
        <div style="float:left;margin-left:35px;">
        <h3>Delete Product</h3>
        <div style="background-color:brown; width:390px">
            <span style="color:white">Product ID:</span> <asp:TextBox ID="txtDeleteProductID" runat="server"></asp:TextBox>
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            <asp:Button ID="btnDeleteProduct" runat="server" Text="Delete Product" OnClick="btnDeleteProduct_Click"/>
            <br /><br />
            <asp:Label ID="lblDeleteProduct" ForeColor="White" runat="server" Text=""></asp:Label>
        </div>
        <h3>Update Product</h3>
        <div style="background-color:#009999; width:390px">
            <span style="color:white">Update Product:</span><br />
            Product ID:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <asp:TextBox ID="txtUpdateProduct" runat="server"></asp:TextBox><br />
            New Name:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <asp:TextBox ID="txtUpdateName" runat="server"></asp:TextBox><br />
            New Price:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <asp:TextBox ID="txtUpdatePrice" runat="server"></asp:TextBox>&nbsp;&nbsp;
            <asp:Button ID="btnUpdateProduct"
                 runat="server" Text="Update Product" OnClick="btnUpdateProduct_Click" Width="106px"/>
            <br /><asp:Label ID="lblProductUpdated" ForeColor="White" runat="server" Text=""></asp:Label>
            <br /><br />
            
        </div>
        <br />
            </div>
        
    </div>
        <span style="color:red;background-color:silver;margin-left:800px;float:left;clear:both;">Created by Chris S.</span>
    </form>
</body>
</html>

The Default.aspx.cs file should look like this:

namespace WebAPIExchangeJsonData
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void btnGetAllProducts_Click(object sender, EventArgs e)
        {

        }

        protected void btnGetProductByID_Click(object sender, EventArgs e)
        {

        }

        protected void btnPostProduct_Click(object sender, EventArgs e)
        {

        }

        protected void btnDeleteProduct_Click(object sender, EventArgs e)
        {

        }

        protected void btnUpdateProduct_Click(object sender, EventArgs e)
        {

        }
    }
}

Now you can build your solution and run it. Navigate to the Default.aspx page and make sure everything is fine. At this moment, clicking the buttons will cause a post back to the server but nothing really happens since we haven’t write any code to “talk” to Web API. Before continuing, test that your Product Controller works fine by navigating to

http://localhost:your_port/api/product

You should get the following result:

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<ArrayOfProduct xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/WebAPIExchangeJsonData.Models">
<Product>
   <Id>1</Id>
   <Name>Product P1</Name>
   <Price>15</Price>
</Product>
   <Product>
   <Id>2</Id>
   <Name>Product P2</Name>
   <Price>45</Price>
</Product>
</ArrayOfProduct>

Now the good stuff. Let’s bind first the click event for the Get Products button. Change it’s click event handler to the following.

protected void btnGetAllProducts_Click(object sender, EventArgs e)
        {
            lblAllProducts.Text = "";

            List<Product> products = null;
            HttpResponseMessage getResponse = client.GetAsync(address).Result;
            var task = getResponse.Content.ReadAsAsync<List<Product>>().ContinueWith((t) =>
            {
                products = t.Result;
            });
            task.Wait();

            foreach (Product product in products)
            {
                lblAllProducts.Text += "Product ID: " + product.Id + " "
                    + product.Name + " Price: " + product.Price + "<br/>";
            }
        }

When you paste the above code your compiler will complaint that some variables aren’t declared or some classes are unknown. First add the following using statements and add a System.ServiceModel reference to your project.

using System.Net.Http;
using WebAPIExchangeJsonData.Models;

namespace WebAPIExchangeJsonData
{
    public partial class Default : System.Web.UI.Page
    {

        HttpClient client = new HttpClient();
        static readonly Uri _baseAddress = new Uri("http://localhost:your_port_number_here/");
        Uri address = new Uri(_baseAddress, "/api/product");
        // Rest of code omitted...

Back to our code now. I have declared an HttpClient instance and a Uri object in order to make the HTTP requests. In the btnGetAllProducts_Click event, we call the client.GetAsync(address) method which returns a Task and has a property Result that returns an HttpRequestMessage. You can read the contents of that message with the getResponse.Content.ReadAsAsync() method that also returns a Task with a property Result. You will notice that you need to wait for the Task to end before assigning it’s results to the respective Label Text property. The good part is that you could have continued making other operations that aren’t related to your Web API call. If you want change the HomeController’s Index action to the following, in order to navigate to your page automatically when you start your application.

public class HomeController : Controller
    {
        public RedirectResult  Index()
        {
            return Redirect("/default.aspx");
        }
    }

You are ready to go. Build and run your application. Click the Get Products button. Your Web API GET call should successfully return two Json objects and their values should be added to the UI respective label.
exchJsonwebapi_02

The btnGetProductByID_Click event handler will be almost the same, but this time you need to pass the Product’s ID you want to retrieve plus that this time, you ReadAsAsync a single Product object rather than a list of them. I have highlighted the important lines.

protected void btnGetProductByID_Click(object sender, EventArgs e)
        {
            lblProduct.Text = "";
            int pID = Int32.Parse(txtProductId.Text);

            Product product = null;
            HttpResponseMessage getResponseWithId = client.GetAsync(new Uri(_baseAddress, "/api/product/" + pID)).Result;
            var taskWithId = getResponseWithId.Content.ReadAsAsync<Product>().ContinueWith((t) =>
            {
                product = t.Result;
            });
            taskWithId.Wait();
            lblProduct.Text += "Product ID: " + product.Id + " "
                    + product.Name + " Price: " + product.Price + "<br/>";
        }

exchJsonwebapi_03

Time to POST a new Product now. After we do that, we will be able to retrieve it eight clicking the Get Products button or the Get Product, passing the newly created Product’s Id as a parameter.

protected void btnPostProduct_Click(object sender, EventArgs e)
        {
            lblProductPosted.Text = "";
            int pID = Int32.Parse(txtNewProductId.Text);
            string pName = txtNewProductName.Text;
            decimal pPrice = decimal.Parse(txtNewProductPrice.Text);

            Product newProduct = new Product
            {
                Id = pID,
                Name = pName,
                Price = pPrice
            };

            HttpResponseMessage response = client.PostAsJsonAsync(address.ToString(), newProduct).Result;

            // Check that response was successful or throw exception
            response.EnsureSuccessStatusCode();
            response.Content.ReadAsAsync<HttpResponseMessage>().Wait();
            lblProductPosted.Text = "New Product Added!";

            btnGetAllProducts_Click(sender, e);
        }

You use the PostAsJsonAsync HttpClient’s method in order to POST Json data to a Web API POST action and you pass the Product object you want to create. You will notice that I call the btnGetAllProducts_Click in order to update the respective Label and ensure that the product was created.
exchJsonwebapi_04

Let’s try to Delete or Update a product now.

protected void btnDeleteProduct_Click(object sender, EventArgs e)
        {
            int pDelID = Int32.Parse(txtDeleteProductID.Text);

            HttpResponseMessage response = client.DeleteAsync(address.ToString() + "/" + pDelID).Result;
            response.EnsureSuccessStatusCode();
            response.Content.ReadAsAsync<HttpResponseMessage>().Wait();

            lblDeleteProduct.Text = "Product Deleted...";
            btnGetAllProducts_Click(sender, e);
        }

        protected void btnUpdateProduct_Click(object sender, EventArgs e)
        {
            int pUpdateId = Int32.Parse(txtUpdateProduct.Text);
            string pUpdateName = txtUpdateName.Text;
            decimal pUpdatePrice = decimal.Parse(txtUpdatePrice.Text);

            Product newProduct = new Product
            {
                Id = pUpdateId,
                Name = pUpdateName,
                Price = pUpdatePrice
            };

            //HttpResponseMessage response = client.PutAsync(address.ToString() + "/" + pUpdateId + "/" + pUpdateName + "/" + pUpdatePrice).Result;
            HttpResponseMessage response = client.PutAsync<Product>(address.ToString(), newProduct, new JsonMediaTypeFormatter()).Result;
            response.EnsureSuccessStatusCode();
            response.Content.ReadAsAsync<HttpResponseMessage>().Wait();

            lblProductUpdated.Text = "Product Updated...";
            btnGetAllProducts_Click(sender, e);
        }

I thing I don’t have to explain the above code, it’s quite self explanatory. I have added a using statement for the System.Net.Http.Formatting namespace too. Let’s see it all in action now (you may have to click the GIF image below).
exchJsonwebapi_inaction
Download the WebAPIExchangeJsonData from here. I hope you enjoyed the post.

In case you find my blog’s content interesting, register your email to receive notifications of new posts and follow chsakell’s Blog on its Facebook or Twitter accounts.

Facebook Twitter
.NET Web Application Development by Chris S.
facebook twitter-small


Categories: ASP.NET

Tags: , , ,

1 reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: