Introduction
In .NET framework 4.5 asynchronous programming concept has been introduced. In this regard, .NET introduced two keyword async and await. It is much easier to implement than the multi-threading concept. The .NET Framework 4 introduced an asynchronous programming concept referred to as a Task and ASP.NET MVC 4 supports Task. In this article I will show you a simple CRUD operation using asynchronous programming by async, await and Task.
A simple overview on “async, await, Task” Keyword
async
- The async modifier indicates that the method, lambda expression, or anonymous method will work asynchronously.
- Method with async modifier also called async method.
- An async method provides a convenient way to do potentially long-running work without blocking the caller’s thread.
- The caller of an async method can resume its work without waiting for the async method to finish.
- Typically, a method modified by the async keyword contains at least one await expression or statement.
await
- Typically await keyword used to free a thread
- The await operator is applied to a task in an asynchronous method to suspend the execution of the method until the awaited task completes.
- The asynchronous method in which await is used must be modified by the async keyword. Such a method, defined by using the async modifier, and usually containing one or more await expressions, is referred to as an async method.
- The task to which the await operator is applied typically is the return value from a call to a method that
implements.
Task
- The main types are System.Threading.Tasks.Task
- Represents an asynchronous operation that can be waited on and cancelled
- System.Threading.Tasks.Task
, which is a task that can return a value.
MSDN References:
- https://msdn.microsoft.com/en-us/library/hh156513(v=vs.110).aspx
- https://msdn.microsoft.com/en-us/library/hh156528(v=vs.110).aspx
- https://msdn.microsoft.com/en-us/library/system.threading.tasks(v=vs.110).aspx
Here I implement async modifier to a CRUD operation on Employee Object. Let’s start.
Tools and Technology used
I used following tools and technology to develop the project –
- Visual Studio 2013
- Visual C#
- ASP.NET MVC 5
- Entity Framework 6
- Razor view engine
Step 1: Create an ASP.NET MVC 5 application using Visual Studio 2013. I kept the application name “MVCAsync”.
Help: How to create first application using asp.net MVC
Step 2: Configure connection string in web.config
Step 3: Create a model in model folder – Employee
Employee
public class Employee { public int Id { get; set; } public string Name { get; set; } public string NickName { get; set; } public string Designation { get; set; } public string Dept { get; set; } }
Step 4: Create a DbContext name EmployeeDBContext in Model folder.
public class EmployeeDBContext : DbContext { public EmployeeDBContext() : base("DefaultConnection") { } public DbSetEmployees { get; set; } }
Step 5: Create a controller name – EmployeeController. Select template “MVC5 Controller with views, using entity framework”. EmployeeController will create in Controller folder and related views will be created in Views/Employee folder. At the time of creating controller – mark use async controller action.
Step 6: Employee Controller is given below. A simple difference over normal method is –
- used async keyword in Action Method.
- Used Task instead of typical ActionResult
- And used await keyword in any operation.
public class EmployeeController : Controller { private EmployeeDBContext db = new EmployeeDBContext(); // GET: /Employee/ public async TaskIndex() { return View(await db.Employees.ToListAsync()); } // GET: /Employee/Details/5 public async Task Details(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Employee employee = await db.Employees.FindAsync(id); if (employee == null) { return HttpNotFound(); } return View(employee); } // GET: /Employee/Create public ActionResult Create() { return View(); } // POST: /Employee/Create // To protect from overposting attacks, please enable the specific properties you want to bind to, for // more details see http://go.microsoft.com/fwlink/?LinkId=317598. [HttpPost] [ValidateAntiForgeryToken] public async Task Create([Bind(Include="Id,Name,NickName,Designation,Dept")] Employee employee) { if (ModelState.IsValid) { db.Employees.Add(employee); await db.SaveChangesAsync(); return RedirectToAction("Index"); } return View(employee); } // GET: /Employee/Edit/5 public async Task Edit(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Employee employee = await db.Employees.FindAsync(id); if (employee == null) { return HttpNotFound(); } return View(employee); } // POST: /Employee/Edit/5 // To protect from overposting attacks, please enable the specific properties you want to bind to, for // more details see http://go.microsoft.com/fwlink/?LinkId=317598. [HttpPost] [ValidateAntiForgeryToken] public async Task Edit([Bind(Include="Id,Name,NickName,Designation,Dept")] Employee employee) { if (ModelState.IsValid) { db.Entry(employee).State = EntityState.Modified; await db.SaveChangesAsync(); return RedirectToAction("Index"); } return View(employee); } // GET: /Employee/Delete/5 public async Task Delete(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Employee employee = await db.Employees.FindAsync(id); if (employee == null) { return HttpNotFound(); } return View(employee); } // POST: /Employee/Delete/5 [HttpPost, ActionName("Delete")] [ValidateAntiForgeryToken] public async Task DeleteConfirmed(int id) { Employee employee = await db.Employees.FindAsync(id); db.Employees.Remove(employee); await db.SaveChangesAsync(); return RedirectToAction("Index"); } protected override void Dispose(bool disposing) { if (disposing) { db.Dispose(); } base.Dispose(disposing); } }
Step 7: Views – After selecting and executing template views are automatically created. Here is the views for CRUD operation of Employee.
Create.cshtml
@model MVCAsync.Models.EmployeeCreate @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/jqueryval") @using (Html.BeginForm()) { @Html.AntiForgeryToken()}Employee
@Html.ValidationSummary(true)@Html.LabelFor(model => model.Name, new { @class = "control-label col-md-2" })@Html.EditorFor(model => model.Name) @Html.ValidationMessageFor(model => model.Name)@Html.LabelFor(model => model.NickName, new { @class = "control-label col-md-2" })@Html.EditorFor(model => model.NickName) @Html.ValidationMessageFor(model => model.NickName)@Html.LabelFor(model => model.Designation, new { @class = "control-label col-md-2" })@Html.EditorFor(model => model.Designation) @Html.ValidationMessageFor(model => model.Designation)@Html.LabelFor(model => model.Dept, new { @class = "control-label col-md-2" })@Html.EditorFor(model => model.Dept) @Html.ValidationMessageFor(model => model.Dept)@Html.ActionLink("Back to List", "Index")
Delete.cshtml
@model MVCAsync.Models.EmployeeDelete Are you sure you want to delete this?
Employee
@using (Html.BeginForm()) { @Html.AntiForgeryToken()
- @Html.DisplayNameFor(model => model.Name)
- @Html.DisplayFor(model => model.Name)
- @Html.DisplayNameFor(model => model.NickName)
- @Html.DisplayFor(model => model.NickName)
- @Html.DisplayNameFor(model => model.Designation)
- @Html.DisplayFor(model => model.Designation)
- @Html.DisplayNameFor(model => model.Dept)
- @Html.DisplayFor(model => model.Dept)
| @Html.ActionLink("Back to List", "Index")}
Details.cshtml
@model MVCAsync.Models.EmployeeDetails Employee
- @Html.DisplayNameFor(model => model.Name)
- @Html.DisplayFor(model => model.Name)
- @Html.DisplayNameFor(model => model.NickName)
- @Html.DisplayFor(model => model.NickName)
- @Html.DisplayNameFor(model => model.Designation)
- @Html.DisplayFor(model => model.Designation)
- @Html.DisplayNameFor(model => model.Dept)
- @Html.DisplayFor(model => model.Dept)
@Html.ActionLink("Edit", "Edit", new { id = Model.Id }) | @Html.ActionLink("Back to List", "Index")
Edit.cshtml
@model MVCAsync.Models.EmployeeEdit @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/jqueryval") @using (Html.BeginForm()) { @Html.AntiForgeryToken()}Employee
@Html.ValidationSummary(true) @Html.HiddenFor(model => model.Id)@Html.LabelFor(model => model.Name, new { @class = "control-label col-md-2" })@Html.EditorFor(model => model.Name) @Html.ValidationMessageFor(model => model.Name)@Html.LabelFor(model => model.NickName, new { @class = "control-label col-md-2" })@Html.EditorFor(model => model.NickName) @Html.ValidationMessageFor(model => model.NickName)@Html.LabelFor(model => model.Designation, new { @class = "control-label col-md-2" })@Html.EditorFor(model => model.Designation) @Html.ValidationMessageFor(model => model.Designation)@Html.LabelFor(model => model.Dept, new { @class = "control-label col-md-2" })@Html.EditorFor(model => model.Dept) @Html.ValidationMessageFor(model => model.Dept)@Html.ActionLink("Back to List", "Index")
Index.cshtml
@model IEnumerableIndex @Html.ActionLink("Create New", "Create")
@foreach (var item in Model) { @Html.DisplayNameFor(model => model.Name) @Html.DisplayNameFor(model => model.NickName) @Html.DisplayNameFor(model => model.Designation) @Html.DisplayNameFor(model => model.Dept) } @Html.DisplayFor(modelItem => item.Name) @Html.DisplayFor(modelItem => item.NickName) @Html.DisplayFor(modelItem => item.Designation) @Html.DisplayFor(modelItem => item.Dept) @Html.ActionLink("Edit", "Edit", new { id=item.Id }) | @Html.ActionLink("Details", "Details", new { id=item.Id }) | @Html.ActionLink("Delete", "Delete", new { id=item.Id })
Step 8: Add a link to _Layout page to access Employee information in Views/Shared
Step 9: Run the following command in package manager console one after another
PM> Enable-Migrations -ContextTypeName EmployeeDBContext
PM> Add-Migration created
PM> Update-Database –Verbose
Now run application and apply CRUD operation on it. It’s simple!!
Output:
Well done mahedee…carry on…with best wishes……:)
Alaul
It’s helpful to adding a New Field to the Model and Table…:)
Nice and easily understandable article.