Udemy

First .NET Core Console Application using Command Prompt

Monday, November 27, 2017 0 Comments A+ a-

Introduction

In this post, we will create our very first console application in .NET Core, we will see how we can build .NET Core based applications without using any IDE or Visual Studio. We will be using Command Line to create, build and run the application. If we don’t need all the fancy features that Visual Studio and Visual Studio Code offers, then we can build a .NET Core application with just a note pad, the only thing we would need is the .NET Core SDK installed on the machine, and all other actions that we do with Visual Studio all can be invoked using the CLI which we will see how it can be done.


Checking .NET Core Installation

Before creating the .NET Core project, it is obvious thing that we should have .NET Core installed on our machine which can be checked by opening a Command Prompt Window or Powershell window and typing in it the dotnet command, if the .NET Core is not already installed on the machine we will get a error as it will not be able to recognize the command:

Installing .NET Core SDK on Windows

As .NET Core is  all about cross platform, so the SDK is available for different platforms which includes Windows 32-bit and 64-bit, MacOS and Linux, if we go to the official download link we can see multiple options available from which can choose as per our need or convenience.


The following is the list taken from official .NET Core download link :


.NET Core List.PNG


We will be creating the application using Windows so let’s download the sdk installer executable for Windows, i downloaded the Installer of Windows (x64) as on my machine i have 64-bit Windows installed.


.NET SDK x64.png
After downloading the installer, proceed to install the SDK :





This installer will install all the necessary components need to develop .NET Core application and running it which includes .NET Core RunTime, SDK and other things as well. The installation will take 2 - 3 minutes to do the installation, and if all the things go right in installation you will see the following window acknowledging the successful installation :



As we were able to install the SDK successfully, now open the command prompt again and type dontnet command again, i am using powershell for this and executing the command gives you back some output that means .NET Core is being setup correctly:




.NET Core CLI provides different commands to create new project, build, clean and all other commands that we normally invoke using Visual Studio, there is a complete list of commands documented on the official documentation page and all the commands can be seen at this link.

Creating Console Application

Now let’s create the simplest famous Hello World console application using command prompt in .NET Core. If all the previous steps have been completed correctly, open the Command Prompt and create a new directory which will contain the source code for the application.


Write the following command on cmd to create the directory:


mkdir First DotNetCoreApp




Now open the directory using the following command:


cd First DotNetCoreApp




Fromt the above image we can verify that we have opened the correct directory.


Adding Project Template

.NET Core comes with it’s own CLI tools enables to create new project using commands in Command Prompt or Powershell without even opening up the IDE either Visual Studio or VS Code.


We will type dotnet new on command line and press enter which will list down all the templates that can be created using this command.


After running the command, we will see few things listed which includes the different flags which are available to do different things which are also available within Visual Studio but the support is added via Command Line too which is great.




If we go little down, we can see all the templates listed which are available via CLI tools:




Now let’s run the command for creating a new Console Application, so write dotnet new and press enter key and this will create new Console Application project in our working directory:




Our project has been created successfully, but to double check and make sure the command worked fine, we can list the directory content and we should be able to see csproj, Program.cs and other files for the application.




Now let’s run the application by executing the dotnet run command in CMD:




One thing to remember here is that if you are creating the project using .NET Core 1.0 SDK, then before the dotnet run command you would need to execute the dotnet restore command which will restore all the NuGet package dependencies of the project, but for .NET Core 2.0 we don’t need to execute this command as calling the dotnet run makes sure to restore the NuGet package dependencies before running the code.


In actual the restore command was called when we execute the command dotnet new and NuGet packages were restored that time, but it is also called on run as well, which can be verified from this GitHub announcement .

Resources

Udemy

Implement Equality for Value Types in C#

Saturday, July 29, 2017 0 Comments A+ a-

Introduction

This post is to focus on implementing Equality in Value Types i.e. overriding Equality behavior for our own implemented Value Types which is basically defining that how to decide two objects of a type are equal or not. 

Background

As we are now aware of the fact that the technique for checking equality for Value Types and Reference Types is different, so it would be better if we discuss both of them separately, that’s why we will be focusing on each of them in separate posts to have clear understanding on how we can override the Equality for both of these.

This post will particularly focus on the Value Types and for Reference Types we will see in some future post.

Why we need it?

The first question that might come in mind is “Why we should override the Equality for Value Type”, we will see with a simple example and it will help you understand that fact that overriding the Equality behavior for Value Types is always a good idea indeed. We will define a struct later down the road and will implement the Equality of it.

Steps to Implement Equality for Value Type

For overriding the Equality for a Value Type, there are some necessary steps that should be performed which are mentioned below.

We will need to:
  • override the virtual Equals method of Object
  • implement IEquatable<T> interface and provide the implementation of Equals() method of it
  • provide the overloaded implementation for == and != operator method
  • override the GetHashCode method of Object class

Possible Reasons for implementing Equality

So before we start discussing how we can implement Equality for a Value Type, let’s think a little on what are the possible reasons that would make us think that we should define our own Equality behavior for a Value Type instead of using the default one that framework already provides.
So why would you want to override it, the following are the main reasons for that:
  • We want to be able use == operator for comparing the objects of our Value Type. If you remember we discussed previously that == operator does not work for value types and to make it work we need to do some implementation (i.e. overload == operator) in our particular Value Type
  • We have also seen previously that the framework provided implementation uses Reflection for checking the values of each field of that type which is obviously affect the performance as Reflection is slow which results in poor performance of code.
  • We also need sometimes different behavior for comparison of a particular type, though this is not usually required but can be needed in some cases, as the default behavior for Value Types considers two objects to be equal if all of their fields also have the same content which is absolutely fine most of the time.

It is recommended approach to implement Equality for your own defined Value Types that would be used further in your code base. Other developers using your defined Value Type would not get surprised or frustrated when trying to compare two objects of it by using == operator and came to know that they can’t do it.

We can skip overriding the equality for those types that we know we will be using internally in the code base and won’t be exposed to complete code base for usage and we know what we wouldn’t be needing to compare the objects frequently, so implementing equality for those types is not that much needed and would be a waste of time as a result.

Example

We will create an example struct named Employee to illustrate about implementing Equality for a Value Type. This is how our Employee struct looks like now:

    public struct Employee
    {
        public string Name { get; }

        public Gender Gender { get; set; }

        public Department Department { get; set; }

        public Employee(string name, Gender gender, Department department)
        {
            Name = name;
            Gender = gender;
            Department = department;
        }

        public override string ToString()
        {
            return Name;
        }

    }

    public enum Department
    {
        HumanRecource,
        QualityAssurance,
        SoftwareDevelopment,
        ProjectManagement,
        ITOperations
    }

    public enum Gender
    {
        Male,
        Female
    }



We have a very simple Employee type as example which has a String property which will contain the name of employee and one enumeration property to hold the gender of employee and another enumeration for Department which will be used to track the Department of the employee. We will define our own implementation later to dictate that how to decide if two employee instances are equal or not.

There are multiple things that we need to take care and implement in our Employee type for implementing Equality. The first thing that we need to do is override the Object.Equals() method so that instead of default implementation getting invoked which is obviously slow because of Reflection involved, by providing implementation for this method it will enhance the performance of the Type, so overriding Equals method will eliminate the equality check using Reflection and will make it efficient and we will be able to see significant performance improvement.

But wait, Object.Equals() method takes parameter of type Object which means that boxing will happen and we know it also hurts the performance of our code, as boxing and unboxing has its own cost involved, so here we would want to avoid that one as well some way.

For avoiding both Reflection and boxing we will need to implement the IEquatable<Employee> interface for our type Employee. Now we will have efficient implementation of Equals() method in comparison with the framework provided one and another plus point of doing this is that now we have a much better implementation which is also type safe.

We will need to provide the overloaded implementation for == and != operators as it is normally considered a good practice to do all of the following things when overriding Equality:
  • Object.Equals method overriding
  • Implementing IEquatable<T> interface for that type
  • Implementing == and != overloaded methods
  • Object.GetHashCode method overriding
This is important to do because it will make sure that checking for equality for two objects of that type will give the same result, otherwise it can be confusing for the calling code who will be utilizing our type and can cause problems in future.

For Example, if we just implement the overloads for == and != operator and we don’t provide the override for Object.Equals method then what will happen is that the result of Equals method can be different from the result of == operator which will be troublesome for the code that will be utilizing our types.

There is also another method in Object class called GetHashCode, whenever we override the Object.Equals method for a type then another thing that must be done is overriding the GetHashCode method as well.

Step1 - Implementing IEquatable<T> Interface

Now let’s jump in to the Visual Studio and let’s start implementing the IEquatable<Employee> interface for out Person type. We will need to inherit our struct from IEquatable<Employee> and using the code refactoring feature of Visual Studio:

It will add the Equals method without any implementation for the IEquatable<Employee> which would look like:

        public bool Equals(Employee other)
        {
            throw new NotImplementedException();
        }


Now we just need to provide the logic which would be used to identify that the two objects of Employee are equal or not which for this particular example we will do by checking the name and department of the employee is same, or we can also add the Gender if we like as this is just for getting understanding how we can implement it so it doesn’t matter much.

After implementing the Equals method, here is how the method now looks like:


        public bool Equals(Employee other)
        {
            var IsEqual = this.Name == other.Name && this.Department == other.Department;

            return IsEqual;
        }


So the two objects of Employee will be considered Equal if they both contain in Name field and Department field same value. Our one field is of type String which does the value equality for == operator and the other is Enum which is a primitive type in C# so we know that in case of primitive type also == operator checks for value Equality, so the both operations will check for value equality which is what we are trying to do here.

Step 2 - Overriding Object.Equals Method

As we are done with the IEquatable<Employee> part, let’s now override the Equals method so that it also returns the same result that we would get when checking for equality via IEquatable<Employee>, the implementation for which would be:

        public override bool Equals(object obj)
        {
            var IsEqual = false;

            if(obj is Employee)
            {
                IsEqual = Equals((Employee)obj);
            }

            return IsEqual;
        }


What we are doing here is that first we need to make sure that the object that is passed in as parameter is of type Employee which totally makes sense as Object.Equals is not type safe and it is possible to pass an object of type Person instead of Employee and the compiler will not give any compile time error but the code would fail at run-time in that case, but adding that if block would save us from breaking the code at run-time and the method will simply return false which is the correct result as object of type Person and Employee can never be equal.

The thing to note here is that this Object.Equals override will be less efficient than Equals method implementation of IEquatable<T> because the former one has cost of Boxing when it will get called and then we are unboxing it back to Employee which IEquatable<Employee> implementation saves us from these.

What we can do is try to always call using the IEquatable<T> method, if we are concerned about performance and memory cost.

Step 3 - Overloading == and != Operator

Now let’s also implement the == and != operator for Employee which would make sure that checking for Equality using these will return consistent result what we were getting using Object.Equals or IEquatable<Employee> Equals method. So let’s add the implementation for == operator first which is:

        public static bool operator ==(Employee employee,Employee otherEmployee)
        {
            var IsEqual = employee.Equals(otherEmployee);

            return IsEqual;
        }


The method is pretty simple, it is also reusing the Equals method implementation that we did for IEquatable<Employee>, if we build the code it would not build and will give error saying that it hasn’t found the implementation of  != operator, in C# if we overload == operator for a type it is mandatory to provide the implementation for inverse of it i.e. != operator implementation as well, otherwise we will get the following compile time error:

Error CS0216: The operator 'Employee.operator ==(Employee, Employee)' requires a matching operator '!=' to also be defined

 If we have overloaded any one of the operator either == or != we would need to implement the other one as well, so let’s implement the other one as well:

        public static bool operator !=(Employee employee, Employee otherEmployee)
        {
            var IsNotEqual = !employee.Equals(otherEmployee);

            return IsNotEqual;
        }

We can see that it is just inverting the result returned the Equals method of IEquatable<Employee> and passing it back to the caller. Now if we again build our Solution we will be able to build it successfully without any errors.

 Step 4 - Implementing GetHashCode

It is a practice and considered mandatory that if we override the Equals method for a type then we must also provide the overridden implementation for GetHashCode().
If we peek in to the implementation of Object we will see that there is a virtual method present in it named GetHashCode, its purpose is to return the 32-bit hash of the value which is contained in the object itself.



you might be wondering what is the purpose of this code, the GetHashCode method is used by types that internally use HashTables to store the objects which are normally Collections so they consume this method and get the hash value of the object to be used in the hash table as HashTables utilize the hash codes of the objects. In Framework Class Libraries the Dictionary<TKey,TValue> also uses HashTable internally.
Hash Codes is a complete topic on which a full article can be written to cover its aspects and we will not not be focusing in details on it. How Hash Tables work is that if two objects return true when called Equals method on them, then the Hash Codes for both objects should also be returned same when we call GetHashCode method on both which in our case would mean that the following line should return true as well.
So what it actually means is that If employee.Equals(OtherEmployee) results in true then employee.GetHashCode() == otherEmployee.GetHasCode() should also return true as result. If the GetHashCode method is not implemented how it is required then the using Dictionary on our type wouldn’t work properly and can cause problems.

Now let’s add the implementation for our Employee type GetHashCode method which would be:
        public override int GetHashCode()
        {
            return Name.GetHashCode() ^ Department.GetHashCode();
        }


So it is quite simple to understand that what we are doing above, we are just taking the HashCode for our String field Name and Department Enumeration and combining them using XOR as both the framework provided types so there is already implementation presentation for generating the Hash Code for these types, so we are just reusing the Hash Codes that are already available and provided by framework.

Now let’s add some code in the Main method to verify what we have implemented is working as expected, add the following code in the Main and run it:


        static void Main(string[] args)
        {


            Employee ehsan = new Employee("Ehsan Sajjad", Gender.Male, Department.SoftwareDevelopment);
            Employee ehsan2 = new Employee("Ehsan Sajjad", Gender.Female, Department.SoftwareDevelopment);

            Employee bilal = new Employee("Bilal Asghar", Gender.Male, Department.QualityAssurance);

            object ehsanObj = ehsan;

            Console.WriteLine(ehsan.Equals(ehsan2));
            Console.WriteLine(ehsanObj.Equals(ehsan2));
            Console.WriteLine(ehsan == ehsan2);

            Console.WriteLine(ehsan.Equals(bilal));
            Console.WriteLine(ehsanObj.Equals(bilal));
            Console.WriteLine(ehsan == bilal);

            Console.ReadKey();

      }


The following is the result which was printed on the Console:


We can observe the for ehsan and ehsan2 objects all the three conditions have evaluated to return true which of course means that both are equal which was expected as this is how we defined to check for equality in our type, though we defined Gender field different in both objects but it has evaluated that both are equal as we are not considering Gender field when deciding that if two are equal or not.

Summary

Following are the points that we learned in this post:
  • We learned how to provide Custom implementation for Equality checking of Value Types
  • Implementing Equality for Value Types is normally good to do as it would improve performance by eliminating boxing/unboxing and reflection cost which can make our code inefficient.
  • There are multiple things to take care of when overriding equality for Value Types which includes:
    • Implementing IEquatable<T> interface of that Value Type which will have type safe Equals method for checking two object of a type T
    • Overriding the Object.Equals method which in turn calls the Equals method which we implemented for IEquatable<T>
    • Implementing the == and != operator overloads which also call the Equals method on IEquatable<T>
    • Implementing GetHashCode of Object for our value type T
  • This is the recommended approach for implementing Equality for Value Types and this is not recommended way in case of Reference Types.
Udemy

AJAX CRUD in Grid using JQuery DataTables in ASP.NET MVC 5

Sunday, June 11, 2017 0 Comments A+ a-


Introduction

I frequently come across questions on online forums like StackOverflow in which the questioners are able to create CRUD operations for their entity which is a normal form post, but they struggle implementing the CRUD via ajax so that page does not reloads completely for better User Experience.

In this post, I will be addressing this problem and we will learn that how can implement CRUD using JQuery DataTables in one page without any full page reloads.

Background

I had been writing in last few posts about the usage of JQuery DataTables and it can be leveraged to build a GridView like functionality in asp.net mvc, we saw how we can install it using NuGet Package Manager and implement a simple gird using the plugin which provides us the essential features like Sorting, Searching and Pagination, then we saw how we can implement the paging, filtering and Ordering, then we proceeded to see how advanced search can be added for more better user experience.

If someone wants to have refresher or interested to read the previous posts related, they can be found here:

In this post we will learn how we can add create, update and delete operations support in the grid that we already implemented using JQuery DataTables. The end result will look something like:


 Database Creation using Script

First of all we will run the script for database and tables creation that would be essential for this post. Following is the script for that:

CREATE DATABASE [AdvancedSearchGridExampleMVC]
GO
CREATE TABLE [dbo].[FacilitySites] ([FacilitySiteID] UNIQUEIDENTIFIER NOT NULL,
                                    [FacilityName]   NVARCHAR (MAX)   NULL,
                                    [IsActive]       BIT              NOT NULL,
                                    [CreatedBy]      UNIQUEIDENTIFIER NOT NULL,
                                    [CreatedAt]      DATETIME         NOT NULL,
                                    [ModifiedBy]     UNIQUEIDENTIFIER NULL,
                                    [ModifiedAt]     DATETIME         NULL,
                                    [IsDeleted]      BIT              NOT NULL
                                   );
GO

CREATE TABLE [dbo].[Assets] (
                             [AssetID]                   UNIQUEIDENTIFIER NOT NULL,
                             [Barcode]                   NVARCHAR (MAX)   NULL,
                             [SerialNumber]              NVARCHAR (MAX)   NULL,
                             [PMGuide]                   NVARCHAR (MAX)   NULL,
                             [AstID]                     NVARCHAR (MAX)   NOT NULL,
                             [ChildAsset]                NVARCHAR (MAX)   NULL,
                             [GeneralAssetDescription]   NVARCHAR (MAX)   NULL,
                             [SecondaryAssetDescription] NVARCHAR (MAX)   NULL,
                             [Quantity]                  INT              NOT NULL,
                             [Manufacturer]              NVARCHAR (MAX)   NULL,
                             [ModelNumber]               NVARCHAR (MAX)   NULL,
                             [Building]                  NVARCHAR (MAX)   NULL,
                             [Floor]                     NVARCHAR (MAX)   NULL,
                             [Corridor]                  NVARCHAR (MAX)   NULL,
                             [RoomNo]                    NVARCHAR (MAX)   NULL,
                             [MERNo]                     NVARCHAR (MAX)   NULL,
                             [EquipSystem]               NVARCHAR (MAX)   NULL,
                             [Comments]                  NVARCHAR (MAX)   NULL,
                             [Issued]                    BIT              NOT NULL,
                             [FacilitySiteID]            UNIQUEIDENTIFIER NOT NULL
                            );

GO

CREATE NONCLUSTERED INDEX [IX_FacilitySiteID]
   ON [dbo].[Assets]([FacilitySiteID] ASC);

GO
ALTER TABLE [dbo].[Assets]
    ADD CONSTRAINT [PK_dbo.Assets] PRIMARY KEY CLUSTERED ([AssetID] ASC);

GO

ALTER TABLE [dbo].[Assets]
   ADD CONSTRAINT [FK_dbo.Assets_dbo.FacilitySites_FacilitySiteID] FOREIGN KEY ([FacilitySiteID]) _
REFERENCES [dbo].[FacilitySites] ([FacilitySiteID]) ON DELETE CASCADE;

GO


You can find the script in attached source code in file name dbScript.sql which also contains sample data to get started quickly, running it will create the DB and will add some sample data in the tables as well.

Create/Insert Operation

For the insertion part, first of all we need to create a partial view in Views >> Asset by right clicking the Asset folder and navigate to Add >> MVC 5 Partial Page (Razor) like the below screen shot:


Open the container view in which asset rows are being rendered which _AssetsPartial.cshtml located in Views >> Asset directory and add the html for the Add Asset button which will open up a popup for inserting a new asset row in database:

<button type="button" class="btn btn-default btn-md" data-toggle="modal" data-url="@Url.Action("Create","Asset")" id="btnCreateAsset">
  <span class="glyphicon glyphicon-new-window" aria-hidden="true"></span> Add Asset
</button>

Now, open the Index View of Asset which is  Views >> Asset >> index.csthtml and in scripts section add the following jQuery code for the button click event which we just created above, it will call the create get action and will display the partial view in bootstrap modal to user, the code for which is:

$("#btnCreateAsset").on("click", function () {

       var url = $(this).data("url");

       $.get(url, function (data) {
               $('#createAssetContainer').html(data);

               $('#createAssetModal').modal('show');
       });

});

We also need to add bootstrap modal with container div in which we will be loading create partial view of Asset, so we will add the following html at the end of Index.cshtml view:

<div class="modal fade" id="createAssetModal" tabindex="-1" role="dialog" aria-labelledby="CreateAssetModal" aria-hidden="true" data-backdrop="static">
    <div id="createAssetContainer">
    </div>
</div>

Implementing Add GET Action 

Add action method for Asset Creation get request in the Asset controller file located at Controllers >> AssetController.cs which would be called by the above jQuery code, inside the action method we are populating the ViewModel and passing the instance back to PartialView as normally we do in mvc based application:

public ActionResult Create()
{
    var model = new AssetViewModel();
    model.FacilitySitesSelectList = GetFacilitiySitesSelectList();
    return View("_CreatePartial", model);
}

Add Partial View Creation:

Add a new Partial view in project in Asset Views for Create form, for that right click the Asset folder under Views in the Solution Explorer

Enter the name of partial view to be _CreatePartial in textbox or whatever name you think would be better in your case.



Implementing Add Partial View

Now we will write the partial view that we created in previous step _CreatePatial, add the following code in that View:

@model GridAjaxCRUDMVC.Models.AssetViewModel
@{
    Layout = null;
}

<div class="modal-dialog">
    <div class="modal-content">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
            <h4 class="modal-title">Add Asset</h4>
        </div>
        @using (Ajax.BeginForm("Create", "Asset", null, new AjaxOptions { HttpMethod = "Post", OnSuccess = "CreateAssetSuccess" }, new {  @class = "form-horizontal", role = "form" }))
        {
            <div class="modal-body">
                <div class="form-horizontal">
                    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
                    @Html.HiddenFor(model => model.AssetID, new { Value = Guid.NewGuid() })
                    <div class="form-group">
                        @Html.LabelFor(model => model.Barcode, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            @Html.EditorFor(model => model.Barcode, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.Barcode, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        @Html.LabelFor(model => model.SerialNumber, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            @Html.EditorFor(model => model.SerialNumber, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.SerialNumber, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        @Html.LabelFor(model => model.FacilitySiteID, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            @Html.DropDownListFor(model => model.FacilitySiteID, Model.FacilitySitesSelectList, "Select One", new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.FacilitySiteID, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        @Html.LabelFor(model => model.PMGuide, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            @Html.EditorFor(model => model.PMGuide, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.PMGuide, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        @Html.LabelFor(model => model.AstID, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            @Html.EditorFor(model => model.AstID, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.AstID, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        @Html.LabelFor(model => model.ChildAsset, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            @Html.EditorFor(model => model.ChildAsset, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.ChildAsset, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        @Html.LabelFor(model => model.GeneralAssetDescription, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            @Html.EditorFor(model => model.GeneralAssetDescription, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.GeneralAssetDescription, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        @Html.LabelFor(model => model.SecondaryAssetDescription, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            @Html.EditorFor(model => model.SecondaryAssetDescription, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.SecondaryAssetDescription, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        @Html.LabelFor(model => model.Quantity, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            @Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.Quantity, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        @Html.LabelFor(model => model.Manufacturer, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            @Html.EditorFor(model => model.Manufacturer, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.Manufacturer, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        @Html.LabelFor(model => model.ModelNumber, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            @Html.EditorFor(model => model.ModelNumber, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.ModelNumber, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        @Html.LabelFor(model => model.Building, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            @Html.EditorFor(model => model.Building, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.Building, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        @Html.LabelFor(model => model.Floor, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            @Html.EditorFor(model => model.Floor, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.Floor, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        @Html.LabelFor(model => model.Corridor, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            @Html.EditorFor(model => model.Corridor, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.Corridor, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        @Html.LabelFor(model => model.RoomNo, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            @Html.EditorFor(model => model.RoomNo, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.RoomNo, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        @Html.LabelFor(model => model.MERNo, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            @Html.EditorFor(model => model.MERNo, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.MERNo, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        @Html.LabelFor(model => model.EquipSystem, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            @Html.EditorFor(model => model.EquipSystem, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.EquipSystem, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        @Html.LabelFor(model => model.Comments, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            @Html.EditorFor(model => model.Comments, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.Comments, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        @Html.LabelFor(model => model.Issued, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            <div class="checkbox">
                                @Html.EditorFor(model => model.Issued)
                                @Html.ValidationMessageFor(model => model.Issued, "", new { @class = "text-danger" })
                            </div>
                        </div>
                    </div>


                </div>
            </div>
            <div class="modal-footer">
                <div class="form-group">
                    <div class="col-md-offset-2 col-md-10">
                        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                        <input type="submit" class="btn btn-primary" value="Save" />
                    </div>
                </div>
            </div>
        }
    </div>
</div>

Implementing Add/Create Post Action 

The important thing to note in the view code is the Ajax.BeginForm helper portion as the class Ajax should be enough to understand that it will post the model back to controller action via Ajax, which means that whole will not refresh i.e. no full postback will happen in terms on asp.net web forms.

The post action is simply mapping ViewModel object to the Model and then saving it in the repository:
[HttpPost]
public async Task<ActionResult> Create(AssetViewModel assetVM)
{
   if (!ModelState.IsValid)
        return View("_CreatePartial", assetVM);

   Asset asset = MaptoModel(assetVM);

   DbContext.Assets.Add(asset);
   var task = DbContext.SaveChangesAsync();
   await task;

   if (task.Exception != null)
   {
       ModelState.AddModelError("", "Unable to add the Asset");
       return View("_CreatePartial", assetVM);
   }

   return Content("success");
}

We are trying to save the newly entered asset in the database and tracking if it is saved successfully or not and if it saves successfully we are returning a string message “success” back to client side and in the success call back of Ajax Form we will be checking if operation was successful or not to do UI changes according to that.

Implementing Ajax Callback Function

We can see that in BeginForm helper method parameters we are specifying JavaScript function to be called when the Ajax Form successfully returns back from server i.e. OnSuccess = "CreateAssetSuccess"

Now let’s go to the index.cshtml view of Asset and define the success callback implementation:

function CreateAssetSuccess(data) {

    if (data != "success") {
       $('#createAssetContainer').html(data);
        return;
    }
    $('#createAssetModal').modal('hide');
    $('#createAssetContainer').html("");
    assetListVM.refresh();

}

What we are doing here is if the operation is not successful we are updating the client side html to notify the user about the failure of creation and if the insert goes successful we are closing the modal popup and refreshing the Grid to display the up to date information.

Edit/Update Operation:

Until now we should be able to run the application and successfully add new assets in the database via Ajax using the bootstrap modal which we created above, now let’s move to the update part of the Asset.
We will be adding another column in the datatable columns collection which will contain hyper link that will navigate to Edit View, but as we are using Ajax and bootstrap modal, we will be doing updates as well same way, so no redirect will be involved. Let’s get started.
Open the Index.csthml file and add a new column in the columns collection in jQuery datatable initialization, after updating the columns array our code would look like:

"columns": [
              { "title": "Bar Code", "data": "BarCode", "searchable": true },
              { "title": "Manufacturer", "data": "Manufacturer", "searchable": true },
              { "title": "Model", "data": "ModelNumber", "searchable": true },
              { "title": "Building", "data": "Building", "searchable": true },
              { "title": "Room No", "data": "RoomNo" },
              { "title": "Quantity", "data": "Quantity" },
              {
                  "title": "Actions",
                  "data": "AssetID",
                  "searchable": false,
                  "sortable": false,
                  "render": function (data, type, full, meta) {
                      return '<a href="@Url.Action("Edit","Asset")?id=' + data + '" class="editAsset">Edit</a>';
                     }
              }
           ]

We are setting the header of new column to display Actions as title and we would need to disable the searching and sorting for this column, as it is for edit operation and it does not makes sense to enable sorting and searching on this column. Next we are defining the render method of the column and we are generating anchor link html which could call the Edit action of Asset controller and will pass the current asset id to pull the information of it and display in the Edit View.

Defining Edit/Update GET Action:

After doing the datatable js changes, now we need to create a get action method which will pull the asset record from the database and will display it for editing to the user in a popup.
Let’s implement the Edit get action of it:

public ActionResult Edit(Guid id)
{
    var asset = DbContext.Assets.FirstOrDefault(x => x.AssetID == id);

    AssetViewModel assetViewModel = MapToViewModel(asset);

    if (Request.IsAjaxRequest())
        return PartialView("_EditPartial",assetViewModel);

    return View(assetViewModel);
}


The action simply retrieves the row from the database and after converting it to ViewModel passes it to back to partial view to rendered or returned back to the client side for processing, as no post backs would happen it will generate the html and will send the html back in response of ajax call which client side will handle and decide where to put that html.

Handling Action Links Events on Client Side using JQuery:

From the column render function you can see that there is class applied on anchor link called EditAsset, it is defined because jQuery event handler will be applied to the anchor link and Ajax call will be sent to server, let’s define the event handler for that in Index View:

$('#assets-data-table').on("click", ".editAsset", function (event) {

        event.preventDefault();

        var url = $(this).attr("href");

        $.get(url, function (data) {
            $('#editAssetContainer').html(data);

            $('#editAssetModal').modal('show');
        });

 });

Addition of Bootstrap Modal

Now add the bootstrap modal html in the Index View which will be placeholder for loading the Edit View, define it just after create  bootstrap modal html:

<div class="modal fade" id="editAssetModal" tabindex="-1" role="dialog" aria-labelledby="EditAssetModal" aria-hidden="true" data-backdrop="static">
    <div id="editAssetContainer">
    </div>
</div>

Edit/Update Partial View Creation:

Create another new partial view following the same steps which we did for adding _CreatePartial.cshtml which was for Create Asset, So add a new Partial View in the Asset folder in Views with name _EditPartial.cshtml and add the following code in it:

@model TA_UM.ViewModels.AssetViewModel
    @{ 
        Layout = null;
    }
<div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
                <h4 class="modal-title">Edit Asset</h4>
            </div>
@using (Ajax.BeginForm("Edit", "Asset", null, new AjaxOptions { HttpMethod="Post", OnSuccess = "UpdateAssetSuccess" }, new { @class = "form-horizontal", role = "form" }))
            {
                <div class="modal-body">
                    <div class="form-horizontal">
                        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
                        @Html.HiddenFor(model => model.AssetID)

                        <div class="form-group">
                            @Html.LabelFor(model => model.Barcode, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @Html.EditorFor(model => model.Barcode, new { htmlAttributes = new { @class = "form-control" } })
                                @Html.ValidationMessageFor(model => model.Barcode, "", new { @class = "text-danger" })
                            </div>
                        </div>
<div class="form-group">
                            @Html.LabelFor(model => model.SerialNumber, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @Html.EditorFor(model => model.SerialNumber, new { htmlAttributes = new { @class = "form-control" } })
                                @Html.ValidationMessageFor(model => model.SerialNumber, "", new { @class = "text-danger" })
                            </div>
                        </div>
<div class="form-group">
                            @Html.LabelFor(model => model.FacilitySiteID, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @Html.DropDownListFor(model => model.FacilitySiteID,Model.FacilitySitesSelectList, "Select One", new { htmlAttributes = new { @class = "form-control" } })
                                @Html.ValidationMessageFor(model => model.FacilitySiteID, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group">
                            @Html.LabelFor(model => model.PMGuide, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @Html.EditorFor(model => model.PMGuide, new { htmlAttributes = new { @class = "form-control" } })
                                @Html.ValidationMessageFor(model => model.PMGuide, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group">
                            @Html.LabelFor(model => model.AstID, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @Html.EditorFor(model => model.AstID, new { htmlAttributes = new { @class = "form-control" } })
                                @Html.ValidationMessageFor(model => model.AstID, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group">
                            @Html.LabelFor(model => model.ChildAsset, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @Html.EditorFor(model => model.ChildAsset, new { htmlAttributes = new { @class = "form-control" } })
                                @Html.ValidationMessageFor(model => model.ChildAsset, "", new { @class = "text-danger" })
                            </div>
                        </div>
<div class="form-group">
                            @Html.LabelFor(model => model.GeneralAssetDescription, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @Html.EditorFor(model => model.GeneralAssetDescription, new { htmlAttributes = new { @class = "form-control" } })
                                @Html.ValidationMessageFor(model => model.GeneralAssetDescription, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group">
                            @Html.LabelFor(model => model.SecondaryAssetDescription, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @Html.EditorFor(model => model.SecondaryAssetDescription, new { htmlAttributes = new { @class = "form-control" } })
                                @Html.ValidationMessageFor(model => model.SecondaryAssetDescription, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group">
                            @Html.LabelFor(model => model.Quantity, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { @class = "form-control" } })
                                @Html.ValidationMessageFor(model => model.Quantity, "", new { @class = "text-danger" })
                            </div>
                        </div>
<div class="form-group">
                            @Html.LabelFor(model => model.Manufacturer, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @Html.EditorFor(model => model.Manufacturer, new { htmlAttributes = new { @class = "form-control" } })
                                @Html.ValidationMessageFor(model => model.Manufacturer, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group">
                            @Html.LabelFor(model => model.ModelNumber, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @Html.EditorFor(model => model.ModelNumber, new { htmlAttributes = new { @class = "form-control" } })
                                @Html.ValidationMessageFor(model => model.ModelNumber, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group">
                            @Html.LabelFor(model => model.Building, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @Html.EditorFor(model => model.Building, new { htmlAttributes = new { @class = "form-control" } })
                                @Html.ValidationMessageFor(model => model.Building, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group">
                            @Html.LabelFor(model => model.Floor, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @Html.EditorFor(model => model.Floor, new { htmlAttributes = new { @class = "form-control" } })
                                @Html.ValidationMessageFor(model => model.Floor, "", new { @class = "text-danger" })
                            </div>
                        </div>
<div class="form-group">
                            @Html.LabelFor(model => model.Corridor, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @Html.EditorFor(model => model.Corridor, new { htmlAttributes = new { @class = "form-control" } })
                                @Html.ValidationMessageFor(model => model.Corridor, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group">
                            @Html.LabelFor(model => model.RoomNo, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @Html.EditorFor(model => model.RoomNo, new { htmlAttributes = new { @class = "form-control" } })
                                @Html.ValidationMessageFor(model => model.RoomNo, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group">
                            @Html.LabelFor(model => model.MERNo, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @Html.EditorFor(model => model.MERNo, new { htmlAttributes = new { @class = "form-control" } })
                                @Html.ValidationMessageFor(model => model.MERNo, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group">
                            @Html.LabelFor(model => model.EquipSystem, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @Html.EditorFor(model => model.EquipSystem, new { htmlAttributes = new { @class = "form-control" } })
                                @Html.ValidationMessageFor(model => model.EquipSystem, "", new { @class = "text-danger" })
                            </div>
                        </div>
<div class="form-group">
                            @Html.LabelFor(model => model.Comments, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @Html.EditorFor(model => model.Comments, new { htmlAttributes = new { @class = "form-control" } })
                                @Html.ValidationMessageFor(model => model.Comments, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group">
                            @Html.LabelFor(model => model.Issued, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                <div class="checkbox">
                                    @Html.EditorFor(model => model.Issued)
                                    @Html.ValidationMessageFor(model => model.Issued, "", new { @class = "text-danger" })
                                </div>
                            </div>
                        </div>


                    </div>
                </div>
<div class="modal-footer">
                        <div class="form-group">
                            <div class="col-md-offset-2 col-md-10">
                                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                                <input type="submit" class="btn btn-primary" value="Save changes"/>
                            </div>
                        </div>
                    </div>
            }
        </div>
    </div>

The Edit View is also pretty same as we had for Insert except it would be posting to different action which would be responsible for handling the updates of a particular Asset row.

Implementing Edit/Update Post Action:

 Now let’s implement the post action of Edit:

        [HttpPost]
        public async Task<ActionResult> Edit(AssetViewModel assetVM)
        {

            assetVM.FacilitySitesSelectList = GetFacilitiySitesSelectList(assetVM.FacilitySiteID);
            if (!ModelState.IsValid)
            {
                Response.StatusCode = (int)HttpStatusCode.BadRequest;
                return View(Request.IsAjaxRequest() ? "_EditPartial" : "Edit", assetVM);
            }

            Asset asset = MaptoModel(assetVM);

            DbContext.Assets.Attach(asset);
            DbContext.Entry(asset).State = EntityState.Modified;
            var task = DbContext.SaveChangesAsync();
            await task;

            if (task.Exception != null)
            {
                ModelState.AddModelError("", "Unable to update the Asset");
                Response.StatusCode = (int)HttpStatusCode.BadRequest;
                return View(Request.IsAjaxRequest() ? "_EditPartial" : "Edit", assetVM);
            }

            if(Request.IsAjaxRequest())
            {
                return Content("success");
            }

            return RedirectToAction("Index");

        }


Handling Update Ajax Success CallBack

In Index.cshtml implement the OnSuccess callback function which will be called when the asset gets updated successfully, in the call back function modal would be closed and the form will be cleared so that if user opens for editing again the fresh html would be fetched and updated information will be displayed in View and of course datatable will also be refreshed to display the latest updates:

        /**** Edit Asset Ajax Form CallBack ********/

        function UpdateAssetSuccess(data) {

            if (data != "success") {
                $('#editAssetContainer').html(data);
                return;
            }
            $('#editAssetModal').modal('hide');
            $('#editAssetContainer').html("");
            assetListVM.refresh();

        }

The same approach will be followed for the details and delete action, let’s see the delete portion, first of all  open the Index view and let’s add the details and delete action hyperlinks in the render function where we defined the edit link above:

"render": function (data, type, full, meta) {
             return '<a href="@Url.Action("Edit","Asset")?id=' + data + '" class="editAsset">Edit</a> | <a href="@Url.Action("Details","Asset")?id=' + data + '">Details</a> | <a href="@Url.Action("Delete","Asset")?id=' + data + '">Delete</a>';
          }


Now the action column will contain three hyperlinks for Edit, Details and Delete of Asset.

Retrieve and Delete Operation:

At this stage we should be able to see the insert and update functionality working correctly, now we will move to the deletion part to see how we implement the Deletion part for Assets. For doing that, we will need to add class to the hyperlinks which we are generated in the render function for the column in which links will be appearing, let’s do that first, we need to define the render property for the last column in columns array of the DataTables initialization code, and we will define the how the column value should be rendered:

"render": function (data, type, full, meta) {
            return '<a href="@Url.Action("Edit","Asset")?id=' + data + '" class="editAsset">Edit</a> | <a href="@Url.Action("Details","Asset")?id=' + data + '" class="detailsAsset">Details</a> | <a href="@Url.Action("Delete","Asset")?id=' + data + '" class="deleteAsset">Delete</a>';
          }

We have added the detailsAsset and deleteAsset classes to the respective anchor tags so that we can bind the events using jQuery and do some logic to display details or delete particular asset.

After doing the above step, now we will be writing the events to handle the click of these two hyperlinks. We will have to write the following code to achieve it :

$('#assets-data-table').on("click", ".detailsAsset", function (event) {

                event.preventDefault();

                var url = $(this).attr("href");

                $.get(url, function (data) {
                    $('#detailsAssetContainer').html(data);

                    $('#detailsAssetModal').modal('show');
                });

Now as the handler for details tag is placed, let’s move to the view part and write the needed razor code in the respective view. So, Create a new partial view named _detailsPartial which will be responsible for displaying the details of the particular asset selected. For that again Right click the Asset folder in Views directory in Solution Explorer and do the same steps as previously and create the partial with the name mentioned above and add the following code in it.
@model GridAdvancedSearchMVC.Models.AssetViewModel

<div class="modal-dialog">
    <div class="modal-content">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
            <h4 class="modal-title">Asset Details</h4>
            <hr/>
        </div>

        <div class="modal-body">
            <dl class="dl-horizontal">
                <dt>
                    @Html.DisplayNameFor(model => model.Barcode)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.Barcode)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.SerialNumber)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.SerialNumber)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.FacilitySite)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.FacilitySite)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.PMGuide)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.PMGuide)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.AstID)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.AstID)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.ChildAsset)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.ChildAsset)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.GeneralAssetDescription)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.GeneralAssetDescription)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.SecondaryAssetDescription)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.SecondaryAssetDescription)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.Quantity)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.Quantity)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.Manufacturer)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.Manufacturer)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.ModelNumber)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.ModelNumber)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.Building)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.Building)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.Floor)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.Floor)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.Corridor)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.Corridor)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.RoomNo)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.RoomNo)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.MERNo)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.MERNo)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.EquipSystem)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.EquipSystem)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.Comments)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.Comments)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.Issued)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.Issued)
                </dd>

            </dl>

        </div>

    </div>
</div>

Details Get Action Implementation:

Now it’s the time to define the controller action code which will retrieve the asset information from the data source and will pass it back to view to be displayed to the user. Here is the code for controller action:

        public async Task<ActionResult> Details(Guid id)
        {
            var asset = await DbContext.Assets.FirstOrDefaultAsync(x => x.AssetID == id);
            var assetVM = MapToViewModel(asset);

            if(Request.IsAjaxRequest())
                return PartialView("_detailsPartial", assetVM);

            return View(assetVM);
        }

Implementing Delete Operation:

We will add the GET action method for delete which will get the particular asset from the repository and will display the details in popup, where user would be able to delete it or cancel it. Here is the code for the action method:
        public ActionResult Delete(Guid id)
        {
            var asset = DbContext.Assets.FirstOrDefault(x => x.AssetID == id);

            AssetViewModel assetViewModel = MapToViewModel(asset);

            if (Request.IsAjaxRequest())
                return PartialView("_DeletePartial", assetViewModel);
            return View(assetViewModel);
        }

Delete Partial View Addition

We will now add another partial view in the solution for delete part, so navigate to the Views >> Asset folder in the Solution Explorer and from the context menu which appears by right clicking the Asset folder, add a new View using the Option Add >> MVC 5 Partial Page (Razor) and name the partial view to _DeletePartial and add the following code to it:
@model GridAdvancedSearchMVC.Models.AssetViewModel


<div class="modal-dialog">
    <div class="modal-content">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
            <h4 class="modal-title">Delete Asset</h4>
            <h3>Are you sure you want to delete this?</h3>

        </div>

        <div class="modal-body">
            <dl class="dl-horizontal">
                <dt>
                    @Html.DisplayNameFor(model => model.Barcode)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.Barcode)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.SerialNumber)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.SerialNumber)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.FacilitySite)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.FacilitySite)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.PMGuide)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.PMGuide)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.AstID)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.AstID)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.ChildAsset)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.ChildAsset)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.GeneralAssetDescription)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.GeneralAssetDescription)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.SecondaryAssetDescription)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.SecondaryAssetDescription)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.Quantity)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.Quantity)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.Manufacturer)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.Manufacturer)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.ModelNumber)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.ModelNumber)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.Building)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.Building)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.Floor)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.Floor)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.Corridor)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.Corridor)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.RoomNo)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.RoomNo)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.MERNo)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.MERNo)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.EquipSystem)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.EquipSystem)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.Comments)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.Comments)
                </dd>

                <dt>
                    @Html.DisplayNameFor(model => model.Issued)
                </dt>

                <dd>
                    @Html.DisplayFor(model => model.Issued)
                </dd>

            </dl>

            @using (Ajax.BeginForm("Delete", "Asset", null, new AjaxOptions { HttpMethod = "Post", OnSuccess = "DeleteAssetSuccess" }, new { @class = "form-horizontal", role = "form" }))
            {

                <div class="form-actions no-color">
                    @Html.HiddenFor(x => x.AssetID)
                    <input type="submit" value="Delete" class="btn btn-default" /> |
                    @Html.ActionLink("Back to List", "Index",null,new { data_dismiss = "modal" })
                </div>
            }
        </div>
    </div>
</div>

Now we need to again a container div for delete popup as well which will be holding the html returned by the partial view _DeletePartial as we did for other three operations, so add the following html in the Index.cshtml view of Asset :

<div class="modal fade" id="deleteAssetModal" tabindex="-1" role="dialog" aria-labelledby="DeleteAssetModal" aria-hidden="true" data-backdrop="static">
    <div id="deleteAssetContainer">
    </div>
</div>

Handling Delete Link Event with JQuery:

We also need to implement the delete button click event which will be responsible for calling the action method asynchronously and will add the response html to the popup container and the popup container will be displayed to user, the code for which would be:
$('#assets-data-table').on("click", ".deleteAsset", function (event) {

                event.preventDefault();

                var url = $(this).attr("href");

                $.get(url, function (data) {
                    $('#deleteAssetContainer').html(data);

                    $('#deleteAssetModal').modal('show');
                });

            });

Handling DELETE Ajax POST Success Callback:

If you notice here as well we are using Ajax.BeginForm helper method to post the GUID of Asset row that needs to be deleted, and we have specified a JavaScript success callback, but we haven’t yet defined the function in the Index view, so let’s do that as well, here is the function definition:
function DeleteAssetSuccess(data) {

                if (data != "success") {
                    $('#deleteAssetContainer').html(data);
                    return;
                }
                $('#deleteAssetModal').modal('hide');
                $('#deleteAssetContainer').html("");
                assetListVM.refresh();

            }

This is also quite same as we did for other actions, we are making sure that if deletion was successful or not, we update the UI accordingly, that’s what the above code is doing, it closes the popup, clears the html of the container div and refreshes the datatable ViewModel to reflect the latest changes in the grid.

Implementing Delete POST Action:

Lastly, we need to define the POST action for delete which will be responsible for deleting the row from the database table and will return the status of the action back to view in either case i.e. success or failure, let’s do that, here is the code for Delete post action:

        [HttpPost, ActionName("Delete")]
        public async Task<ActionResult> DeleteAsset(Guid AssetID)
        {
            var asset = new Asset { AssetID = AssetID };
            DbContext.Assets.Attach(asset);
            DbContext.Assets.Remove(asset);

            var task = DbContext.SaveChangesAsync();
            await task;

            if (task.Exception != null)
            {
                ModelState.AddModelError("", "Unable to Delete the Asset");
                Response.StatusCode = (int)HttpStatusCode.BadRequest;
                AssetViewModel assetVM = MapToViewModel(asset);
                return View(Request.IsAjaxRequest() ? "_DeletePartial" : "Delete", assetVM);
            }

            if (Request.IsAjaxRequest())
            {
                return Content("success");
            }

            return RedirectToAction("Index");

        }

Now run the application and you should be able to add update and delete rows via Ajax without navigating between the pages.