Web API CRUD Operations And Consume Service In ASP.NET MVC Application

Introduction

 
This article will give you an understanding of the what and the why of Web API and will demonstrate a CRUD operation with a simple example using Entity Framework and consuming the created service into ASP.NET MVC application.
 
The flow of the article
  1. What is Web API
  2. Why Web API
  3. Real time example of WEBAPI
  4. Steps to Create table, Web API Service, and MVC application to consume the service.

    • Create a table in SQL Server.
    • Create Data Access Layer in Visual Studio to access the data and perform DB operation.
    • Create a Web API project.
    • Create MVC Application to consume Web API Service. Project created in step II, III, and IV belonging to one same solution
    • Set Project Startup Order
  1. Output Screens
  2. Conclusion

Web API

  • Web API provides service that can be consumed by a broad range of clients like mobile, tablet, desktop, etc.
  • The response can be in any format, like XML, JSON (widely used), etc.
  • It supports MVC features, like controller, action, routing, etc.
  • Supports CRUD operation. CRUD stands for Create, Read, Update and Delete. It works on HTTP verbs like HttpPost to Create, HttpGet to Read, HttpPut to Update and HttpDelete to Delete.

Why Web API?

 
ASP.NET 
 
Without Web API, the server will have one application to handle the XML request and another application to handle the JSON request, i.e., for each request type, the server will have one application. But with Web API, the server can respond to any request type using a single application. Small end devices like mobile, tablet are capable of handling only the JSON data. So, the Web API has huge scope to give space in the real world. 
 

A real-time example of WebAPI

  • Weather forecasting
  • Movie, Bus, Flight booking
There can be one service provider who offers the service and many consumers to avail this service.
 
Step 1 - Create a table in SQL Server
 
We will create a table to perform CRUD operation with Web API. The table script is given below.
  1. CREATE TABLE [dbo].[Product](  
  2.     [ProductId] [intPRIMARY KEY IDENTITY(1,1) NOT NULL,  
  3.     [ProductName] [nvarchar](100) NULL,  
  4.     [Quantity] [intNULL,  
  5.     [Price] [intNULL)  
Step 2 - Create Class Library Project
  • New Project -> Visual C# -> Windows -> Class Library Project and name it as DataAccessLayer.
  • Right-click on DataAccessLayer project->Add->New Item->Data-> ADO.NET Entity Data Model and name it as ShowRoomEF.
  • Choose EF designer from database in next step.
  • Add the table created in step1 into Entity Framework.

    ASP.NET
  • Create a class called DAL.cs in this project to access the data from DB by Web API service. The code is given below.
DAL.cs
  1. public static class DAL  
  2. {  
  3.     static ShowroomEntities DbContext;  
  4.     static DAL()  
  5.     {  
  6.         DbContext = new ShowroomEntities();  
  7.     }  
  8.     public static List<Product> GetAllProducts()  
  9.     {  
  10.         return DbContext.Products.ToList();  
  11.     }  
  12.     public static Product GetProduct(int productId)  
  13.     {  
  14.         return DbContext.Products.Where(p => p.ProductId ==  productId).FirstOrDefault();  
  15.     }  
  16.     public static bool InsertProduct(Product productItem)  
  17.     {  
  18.         bool status;  
  19.         try  
  20.         {  
  21.             DbContext.Products.Add(productItem);  
  22.             DbContext.SaveChanges();  
  23.             status = true;  
  24.         }  
  25.         catch (Exception)  
  26.         {  
  27.             status = false;  
  28.         }  
  29.         return status;  
  30.     }  
  31.     public static bool UpdateProduct(Product productItem)  
  32.     {  
  33.         bool status;  
  34.         try  
  35.         {  
  36.             Product prodItem = DbContext.Products.Where(p => p.ProductId == productItem.ProductId).FirstOrDefault();  
  37.             if (prodItem != null)  
  38.             {  
  39.                 prodItem.ProductName = productItem.ProductName;  
  40.                 prodItem.Quantity = productItem.Quantity;  
  41.                 prodItem.Price = productItem.Price;  
  42.                 DbContext.SaveChanges();  
  43.             }  
  44.             status = true;  
  45.         }  
  46.         catch (Exception)  
  47.         {  
  48.             status = false;  
  49.         }  
  50.         return status;  
  51.     }  
  52.     public static bool DeleteProduct(int id)  
  53.     {  
  54.         bool status;  
  55.         try  
  56.         {  
  57.             Product prodItem = DbContext.Products.Where(p => p.ProductId == id).FirstOrDefault();  
  58.             if (prodItem != null)  
  59.             {  
  60.                 DbContext.Products.Remove(prodItem);  
  61.                 DbContext.SaveChanges();  
  62.             }  
  63.             status = true;  
  64.         }  
  65.         catch (Exception)  
  66.         {  
  67.             status = false;  
  68.         }  
  69.         return status;  
  70.     }  
  71. }  
Step 3 - Create Empty Web API Project
 
Navigate as given
  • Select New Project -> Visual C# -> Web -> ASP.NET Web Application and enter your application and solution name.

    ASP.NET

  • Select the empty template from options and check Web API checkbox and click OK.

    ASP.NET
  • The solution will be created as below.

    ASP.NET 
  • In App_Start -> WebApiConfig.cs file make sure routeTemplate as given below because by default, the route will not have {action}.
In WebApiConfig.cs
  1. public static void Register(HttpConfiguration config)  
  2.        {  
  3.            // Web API configuration and services  
  4.   
  5.            // Web API routes  
  6.            config.MapHttpAttributeRoutes();  
  7.   
  8.            config.Routes.MapHttpRoute(  
  9.                name: "DefaultApi",  
  10.                routeTemplate: "api/{controller}/{action}/{id}",  
  11.                defaults: new { id = RouteParameter.Optional }  
  12.            );  
  13.  } 
  • Add Reference to DataAccessLayer project.
  • Add the below DLL in references.

    • EntityFramework
    • SqlServer
    • Net.Http
    • Net.Http.Formatting

  • Install Entity Framework from ‘NuGet Package Manager’.
  • Create a Model class for the product as below.

    ASP.NET
Product.cs
  1. namespace WebApiService.Models  
  2. {  
  3.     public class Product  
  4.     {  
  5.         public int ProductId { get; set; }  
  6.         public string ProductName { get; set; }  
  7.         public Nullable<int> Quantity { get; set; }  
  8.         public Nullable<int> Price { get; set; }  
  9.     }  
  10. }  
Copy the connection string from DataAccessLayer -> web.config and paste it in WebApiService -> web.config.
  1. <connectionStrings>  
  2.     <add name="ShowroomEntities" connectionString="metadata=res://*/ShowRoomEF.csdl|res://*/ShowRoomEF.ssdl|res://*/ShowRoomEF.msl;provider=System.Data.SqlClient;provider connection string="data source=MYSYSTEM\SQLEXPRESS;initial catalog=Showroom;user id=sa;password=xxxxx;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />  
  3.   </connectionStrings>  
Add Showroom Controller and make class to inherit from ApiController.
  
ShowroomController.cs
 
Showroom Controller takes care of Inserting, Retrieving, Updating and Deleting the data in the database. Request comes to this controller from the consuming application.
  1. public class ShowroomController: ApiController {  
  2.     // GET: Showroom  
  3.     [HttpGet]  
  4.     public JsonResult < List < Models.Product >> GetAllProducts() {  
  5.             EntityMapper < DataAccessLayer.Product, Models.Product > mapObj = new EntityMapper < DataAccessLayer.Product, Models.Product > ();  
  6.             List < DataAccessLayer.Product > prodList = DAL.GetAllProducts();  
  7.             List < Models.Product > products = new List < Models.Product > ();  
  8.             var config = new MapperConfiguration(cfg => cfg.CreateMap < Product, Models.Product > ());  
  9.             var mapper = new Mapper(config);  
  10.             foreach(var item in prodList) {  
  11.                 products.Add(mapper.Map < Models.Product > (item));  
  12.             }  
  13.             return Json < List < Models.Product >> (products);  
  14.         }  
  15.         [HttpGet]  
  16.     public JsonResult < Models.Product > GetProduct(int id) {  
  17.             EntityMapper < DataAccessLayer.Product, Models.Product > mapObj = new EntityMapper < DataAccessLayer.Product, Models.Product > ();  
  18.             DataAccessLayer.Product dalProduct = DAL.GetProduct(id);  
  19.             Models.Product products = new Models.Product();  
  20.             var config = new MapperConfiguration(cfg => cfg.CreateMap < Product, Models.Product > ());  
  21.             var mapper = new Mapper(config);  
  22.             products = mapper.Map < Models.Product > (dalProduct);  
  23.             return Json < Models.Product > (products);  
  24.         }  
  25.         [HttpPost]  
  26.     public bool InsertProduct(Models.Product product) {  
  27.             bool status = false;  
  28.             if (ModelState.IsValid) {  
  29.                 EntityMapper < Models.Product, DataAccessLayer.Product > mapObj = new EntityMapper < Models.Product, DataAccessLayer.Product > ();  
  30.                 DataAccessLayer.Product productObj = new DataAccessLayer.Product();  
  31.                 var config = new MapperConfiguration(cfg => cfg.CreateMap < Models.Product, Product > ());  
  32.                 var mapper = new Mapper(config);  
  33.                 productObj = mapper.Map < Product > (product);  
  34.                 status = DAL.InsertProduct(productObj);  
  35.             }  
  36.             return status;  
  37.         }  
  38.         [HttpPut]  
  39.     public bool UpdateProduct(Models.Product product) {  
  40.             EntityMapper < Models.Product, DataAccessLayer.Product > mapObj = new EntityMapper < Models.Product, DataAccessLayer.Product > ();  
  41.             DataAccessLayer.Product productObj = new DataAccessLayer.Product();  
  42.             var config = new MapperConfiguration(cfg => cfg.CreateMap < Models.Product, Product > ());  
  43.             var mapper = new Mapper(config);  
  44.             productObj = mapper.Map < Product > (product);  
  45.             var status = DAL.UpdateProduct(productObj);  
  46.             return status;  
  47.         }  
  48.         [HttpDelete]  
  49.     public bool DeleteProduct(int id) {  
  50.         var status = DAL.DeleteProduct(id);  
  51.         return status;  
  52.     }  
  53. }  
Check your service
 
Execute your service created just now by running the below URL in the browser and change the port number accordingly.
 
http://localhost:52956/api/showroom/getallproducts 
 
Service Output
 
ASP.NET
Note
Attached WebApiServiceProvider.zip solution.
 
since solution size exceeds permitted one, have removed 'packages' folder content of 'WebApiServiceProvider' and kept in package_content_1.zip and package_content_2.zip.
 
Kindly don't forget to unzip package_content_1.zip and package_content_2.zip and keep their contents in 'WebApiServiceProvider\packages' folder. Also make changes to connection strings accordingly in both the solution.
 
Step 4 – Consuming Web Api Service In MVC Application
  • Create Empty MVC project as below.

    ASP.NET
  • Create Product model class as created in WebApiService project.
  • Create ServiceRepository.cs in Repository folder to consume the web api service and create ServiceUrl as key and as a value in web.config (port number changes according to the server).
    1. <add key="ServiceUrl" value="http://localhost:52956/"></add>  
  • Add the below DLL in the references.

    • Net
    • Net.Http
    • Net.Http.Formatting
ServiceRepository.cs
 
Service Repository is created to act as a reusable module for requesting, posting, updating and deleting data in WebAPI. This is used by any action method in the Controller which is created in next step and avoids duplication of this code.
  1. public class ServiceRepository  
  2. {  
  3.        public HttpClient Client { get; set; }  
  4.        public ServiceRepository()  
  5.        {  
  6.            Client = new HttpClient();  
  7.            Client.BaseAddress = new Uri(ConfigurationManager.AppSettings["ServiceUrl"].ToString());  
  8.        }  
  9.        public HttpResponseMessage GetResponse(string url)  
  10.        {  
  11.            return Client.GetAsync(url).Result;  
  12.        }  
  13.        public HttpResponseMessage PutResponse(string url,object model)  
  14.        {  
  15.            return Client.PutAsJsonAsync(url, model).Result;  
  16.        }  
  17.        public HttpResponseMessage PostResponse(string url, object model)  
  18.        {  
  19.            return Client.PostAsJsonAsync(url,model).Result;  
  20.        }  
  21.        public HttpResponseMessage DeleteResponse(string url)  
  22.        {  
  23.            return Client.DeleteAsync(url).Result;  
  24.        }  
Create a Controller to handle a request for different action method and navigate to the corresponding view.
 
ProductController.cs
 
Product Controller in MVC application is created to handle the request received from the user action and to serve the response accordingly. Code for product controller is given below.
  1. public class ProductController : Controller  
  2. {  
  3.     // GET: Product  
  4.     public ActionResult GetAllProducts()  
  5.     {  
  6.         try  
  7.         {  
  8.             ServiceRepository serviceObj = new ServiceRepository();  
  9.             HttpResponseMessage response = serviceObj.GetResponse("api/showroom/getallproducts");  
  10.             response.EnsureSuccessStatusCode();  
  11.             List<Models.Product> products = response.Content.ReadAsAsync<List<Models.Product>>().Result;  
  12.             ViewBag.Title = "All Products";  
  13.             return View(products);  
  14.         }  
  15.         catch (Exception)  
  16.         {  
  17.             throw;  
  18.         }  
  19.     }  
  20.     //[HttpGet]  
  21.     public ActionResult EditProduct(int id)  
  22.     {  
  23.         ServiceRepository serviceObj = new ServiceRepository();  
  24.         HttpResponseMessage response = serviceObj.GetResponse("api/showroom/GetProduct?id=" + id.ToString());  
  25.         response.EnsureSuccessStatusCode();  
  26.         Models.Product products = response.Content.ReadAsAsync<Models.Product>().Result;  
  27.         ViewBag.Title = "All Products";  
  28.         return View(products);  
  29.     }  
  30.     //[HttpPost]  
  31.     public ActionResult Update(Models.Product product)  
  32.     {  
  33.         ServiceRepository serviceObj = new ServiceRepository();  
  34.         HttpResponseMessage response = serviceObj.PutResponse("api/showroom/UpdateProduct", product);  
  35.         response.EnsureSuccessStatusCode();  
  36.         return RedirectToAction("GetAllProducts");  
  37.     }  
  38.     public ActionResult Details(int id)  
  39.     {  
  40.         ServiceRepository serviceObj = new ServiceRepository();  
  41.         HttpResponseMessage response = serviceObj.GetResponse("api/showroom/GetProduct?id=" + id.ToString());  
  42.         response.EnsureSuccessStatusCode();  
  43.         Models.Product products = response.Content.ReadAsAsync<Models.Product>().Result;  
  44.         ViewBag.Title = "All Products";  
  45.         return View(products);  
  46.     }  
  47.     [HttpGet]  
  48.     public ActionResult Create()  
  49.     {  
  50.         return View();  
  51.     }  
  52.     [HttpPost]  
  53.     public ActionResult Create(Models.Product product)  
  54.     {  
  55.         ServiceRepository serviceObj = new ServiceRepository();  
  56.         HttpResponseMessage response = serviceObj.PostResponse("api/showroom/InsertProduct", product);  
  57.         response.EnsureSuccessStatusCode();  
  58.         return RedirectToAction("GetAllProducts");  
  59.     }  
  60.     public ActionResult Delete(int id)  
  61.     {  
  62.         ServiceRepository serviceObj = new ServiceRepository();  
  63.         HttpResponseMessage response = serviceObj.DeleteResponse("api/showroom/DeleteProduct?id=" + id.ToString());  
  64.         response.EnsureSuccessStatusCode();  
  65.         return RedirectToAction("GetAllProducts");  
  66.     }  
Views are created in ConsumeWebApi MVC application to consume the service.
 
GetAllProducts.cshtml
 
.cshtml represents Views (UI) and this View displays all the products available which are received from API call in the corresponding method.
  1. @model IEnumerable<ConsumeWebApi.Models.Product>  
  2.   
  3. @{  
  4.     ViewBag.Title = "GetAllProducts";  
  5. }  
  6.   
  7. <h2>GetAllProducts</h2>  
  8.   
  9. <p>  
  10.     @Html.ActionLink("Create New""Create")  
  11. </p>  
  12. <table class="table">  
  13.     <tr>  
  14.         <th>  
  15.             @Html.DisplayNameFor(model => model.ProductName)  
  16.         </th>  
  17.         <th>  
  18.             @Html.DisplayNameFor(model => model.Quantity)  
  19.         </th>  
  20.         <th>  
  21.             @Html.DisplayNameFor(model => model.Price)  
  22.         </th>  
  23.         <th></th>  
  24.     </tr>  
  25.   
  26. @foreach (var item in Model) {  
  27.     <tr>  
  28.         <td>  
  29.             @Html.DisplayFor(modelItem => item.ProductName)  
  30.         </td>  
  31.         <td>  
  32.             @Html.DisplayFor(modelItem => item.Quantity)  
  33.         </td>  
  34.         <td>  
  35.             @Html.DisplayFor(modelItem => item.Price)  
  36.         </td>  
  37.         <td>  
  38.             @Html.ActionLink("Edit""EditProduct"new { id = item.ProductId, name= item.ProductName, quantity=item.Quantity, prod = item }) |  
  39.             @Html.ActionLink("Details""Details"new { id=item.ProductId }) |  
  40.             @Html.ActionLink("Delete""Delete"new { id=item.ProductId })  
  41.         </td>  
  42.     </tr>  
  43. }  
  44.   
  45. </table> 
Create.cshtml
 
This View allows the user to create a product and insert into the database through WebAPI call which is done in corresponding action method.
  1. @model ConsumeWebApi.Models.Product  
  2.   
  3. @{  
  4.     ViewBag.Title = "Create";  
  5. }  
  6.   
  7. <h2>Create</h2>  
  8.   
  9. @using (Html.BeginForm())   
  10. {  
  11.     @Html.AntiForgeryToken()  
  12.       
  13.     <div class="form-horizontal">  
  14.         <h4>Product</h4>  
  15.         <hr />  
  16.         @Html.ValidationSummary(true""new { @class = "text-danger" })  
  17.         <div class="form-group">  
  18.             @Html.LabelFor(model => model.ProductName, htmlAttributes: new { @class = "control-label col-md-2" })  
  19.             <div class="col-md-10">  
  20.                 @Html.EditorFor(model => model.ProductName, new { htmlAttributes = new { @class = "form-control" } })  
  21.                 @Html.ValidationMessageFor(model => model.ProductName, ""new { @class = "text-danger" })  
  22.             </div>  
  23.         </div>  
  24.   
  25.         <div class="form-group">  
  26.             @Html.LabelFor(model => model.Quantity, htmlAttributes: new { @class = "control-label col-md-2" })  
  27.             <div class="col-md-10">  
  28.                 @Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { @class = "form-control" } })  
  29.                 @Html.ValidationMessageFor(model => model.Quantity, ""new { @class = "text-danger" })  
  30.             </div>  
  31.         </div>  
  32.   
  33.         <div class="form-group">  
  34.             @Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" })  
  35.             <div class="col-md-10">  
  36.                 @Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })  
  37.                 @Html.ValidationMessageFor(model => model.Price, ""new { @class = "text-danger" })  
  38.             </div>  
  39.         </div>  
  40.   
  41.         <div class="form-group">  
  42.             <div class="col-md-offset-2 col-md-10">  
  43.                 <input type="submit" value="Create" class="btn btn-default" />  
  44.             </div>  
  45.         </div>  
  46.     </div>  
  47. }  
  48.   
  49. <div>  
  50.     @Html.ActionLink("Back to List""GetAllProducts")  
  51. </div>  
Details.cshtml
 
This View allows the user to see the particular product through WebAPI call which is done in the corresponding action method.
  1. @model ConsumeWebApi.Models.Product  
  2.   
  3. @{  
  4.     ViewBag.Title = "Detail";  
  5. }  
  6.   
  7. <h2>Detail</h2>  
  8.   
  9. <div>  
  10.     <h4>Product</h4>  
  11.     <hr />  
  12.     <dl class="dl-horizontal">  
  13.         <dt>  
  14.             @Html.DisplayNameFor(model => model.ProductName)  
  15.         </dt>  
  16.   
  17.         <dd>  
  18.             @Html.DisplayFor(model => model.ProductName)  
  19.         </dd>  
  20.   
  21.         <dt>  
  22.             @Html.DisplayNameFor(model => model.Quantity)  
  23.         </dt>  
  24.   
  25.         <dd>  
  26.             @Html.DisplayFor(model => model.Quantity)  
  27.         </dd>  
  28.   
  29.         <dt>  
  30.             @Html.DisplayNameFor(model => model.Price)  
  31.         </dt>  
  32.   
  33.         <dd>  
  34.             @Html.DisplayFor(model => model.Price)  
  35.         </dd>  
  36.   
  37.     </dl>  
  38. </div>  
  39. <p>  
  40.     @Html.ActionLink("Edit""EditProduct"new { id = Model.ProductId }) |  
  41.     @Html.ActionLink("Back to List""GetAllProducts")  
  42. </p>  
EditProduct.cshtml
 
This View allows the user to edit product and update database through WebAPI call which is done in the corresponding action method.
  1. @model ConsumeWebApi.Models.Product  
  2.   
  3. @{  
  4.     ViewBag.Title = "EditProduct";  
  5. }  
  6.   
  7. <h2>EditProduct</h2>  
  8.   
  9.   
  10. @using (Html.BeginForm("Update""Product", FormMethod.Post))  
  11. {  
  12.     @Html.AntiForgeryToken()  
  13.   
  14.     <div class="form-horizontal">  
  15.         <h4>Product</h4>  
  16.         <hr />  
  17.         @Html.ValidationSummary(true""new { @class = "text-danger" })  
  18.         @Html.HiddenFor(model => model.ProductId)  
  19.   
  20.         <div class="form-group">  
  21.             @Html.LabelFor(model => model.ProductName, htmlAttributes: new { @class = "control-label col-md-2" })  
  22.             <div class="col-md-10">  
  23.                 @Html.EditorFor(model => model.ProductName, new { htmlAttributes = new { @class = "form-control" } })  
  24.                 @Html.ValidationMessageFor(model => model.ProductName, ""new { @class = "text-danger" })  
  25.             </div>  
  26.         </div>  
  27.   
  28.         <div class="form-group">  
  29.             @Html.LabelFor(model => model.Quantity, htmlAttributes: new { @class = "control-label col-md-2" })  
  30.             <div class="col-md-10">  
  31.                 @Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { @class = "form-control" } })  
  32.                 @Html.ValidationMessageFor(model => model.Quantity, ""new { @class = "text-danger" })  
  33.             </div>  
  34.         </div>  
  35.   
  36.         <div class="form-group">  
  37.             @Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" })  
  38.             <div class="col-md-10">  
  39.                 @Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })  
  40.                 @Html.ValidationMessageFor(model => model.Price, ""new { @class = "text-danger" })  
  41.             </div>  
  42.         </div>  
  43.   
  44.   
  45.         <div class="form-group"><div class="col-md-offset-2 col-md-10">  
  46.                 <input type="submit" value="Save" class="btn btn-default" />  
  47.             </div>  
  48.         </div>  
  49.     </div>  
  50.   
  51. }  
  52.   
  53. <div>  
  54.     @Html.ActionLink("Back to List""GetAllProducts")  
  55. </div>  
Step 5 – Set Project Startup Order
  • This step is necessary and has to be set up because this solution needs WebApiService application to keep running and serve the request. ConsumeWebAPI application will create a request to WebApiService and receive a response back.
  • So, in order to make two projects to keep up and running, this step is performed.
  • Whereas if WebApiService is hosted in IIS, then only one project which consumes the service can be started, i.e., MVC or postman.

    ASP.NET
Output Screens
  1. Get All Products View.

    ASP.NET
  1. Create Product View.

    ASP.NET
  1. Edit Product View.

    ASP.NET
  1. Detailed View of a product.

    ASP.NET
  1. Product table data in Product table of SQL Database.

    ASP.NET

Conclusion

 
Web API can be self-hosted (service and consuming application in the same solution) as discussed in this example or it can be deployed on IIS server. JSON is the widely used request type in services as it is supported by a wide range of client devices. Enjoy creating your own service.


Similar Articles