Firebird Documentation IndexFirebird 3.0 Developer's GuideCreating Web Applications in Entity Framework with MVC → Adapting the Controller to jqGrid
Firebird Home Firebird Home Prev: Creating a User InterfaceFirebird Documentation IndexUp: Creating Web Applications in Entity Framework with MVCNext: Bundles

Adapting the Controller to jqGrid

Table of Contents

The Attribute ValidateAntiforgeryToken

Now, we are going to change the CustomerController controller so that it works with jqGrid. The code is quite lengthy, so track the comments to get a sense of the way the controller works.

public class CustomerController : Controller
{
  private DbModel db = new DbModel();

  // Display view
  public ActionResult Index()
  {
    return View();
  }

  // Receiving data in JSON for grid
  public ActionResult GetData(int? rows, int? page, string sidx, string sord,
string searchField, string searchString, string searchOper)
  {
    // get the page number, the number of data displayed
    int pageNo = page ?? 1;
    int limit = rows ?? 20;
    // calculate the offset
    int offset = (pageNo - 1) * limit;

    // building a query for suppliers
    var customersQuery =
        from customer in db.CUSTOMERS
        select new
    {
        CUSTOMER_ID = customer.CUSTOMER_ID,
        NAME = customer.NAME,
        ADDRESS = customer.ADDRESS,
        ZIPCODE = customer.ZIPCODE,
        PHONE = customer.PHONE
    };
    // adding a search condition to the query, if it is produced
    if (searchField != null)
    {
      switch (searchOper)
      {
        case "eq":
          customersQuery = customersQuery.Where(
            c => c.NAME == searchString);
          break;
        case "bw":
          customersQuery = customersQuery.Where(
            c => c.NAME.StartsWith(searchString));
          break;
        case "cn":
          customersQuery = customersQuery.Where(
            c => c.NAME.Contains(searchString));
          break;
      }
    }
    // get the total number of suppliers
    int totalRows = customersQuery.Count();
    // add sorting
    switch (sord) {
      case "asc":
        customersQuery = customersQuery.OrderBy(
          customer => customer.NAME);
        break;
      case "desc":
       customersQuery = customersQuery.OrderByDescending(
         customer => customer.NAME);
      break;
    }

    // get the list of suppliers
    var customers = customersQuery
          .Skip(offset)
          .Take(limit)
          .ToList();

    // calculate the total number of pages
    int totalPages = totalRows / limit + 1;
    // create the result for jqGrid
    var result = new
      {
        page = pageNo,
        total = totalPages,
        records = totalRows,
        rows = customers
      };
    // convert the result to JSON
    return Json(result, JsonRequestBehavior.AllowGet);
  }

  // Adding a new supplier
  [HttpPost]
  [ValidateAntiForgeryToken]
  public ActionResult Create(
[Bind(Include = "NAME,ADDRESS,ZIPCODE,PHONE")] CUSTOMER customer)
  {
    // check the correctness of the model
    if (ModelState.IsValid)
    {
      // get a new identifier using a generator
      customer.CUSTOMER_ID = db.NextValueFor("GEN_CUSTOMER_ID");
      // add the model to the list
      db.CUSTOMERS.Add(customer);
      // save model
      db.SaveChanges();
      // return success in JSON format
      return Json(true);
    }
    else {
      // join model errors in one string
      string messages = string.Join("; ", ModelState.Values
        .SelectMany(x => x.Errors)
        .Select(x => x.ErrorMessage));
      // return error in JSON format
      return Json(new { error = messages });
    }
  }

  // Editing supplier
  [HttpPost]
  [ValidateAntiForgeryToken]
  public ActionResult Edit(
[Bind(Include = "CUSTOMER_ID,NAME,ADDRESS,ZIPCODE,PHONE")] CUSTOMER customer)
  {
    // check the correctness of the model
    if (ModelState.IsValid)
    {
      // mark the model as modified
      db.Entry(customer).State = EntityState.Modified;
      // save model
      db.SaveChanges();
      // return success in JSON format
      return Json(true);
    }
    else {
      // join model errors in one string
      string messages = string.Join("; ", ModelState.Values
        .SelectMany(x => x.Errors)
        .Select(x => x.ErrorMessage));
      // return error in JSON format
      return Json(new { error = messages });
    }
  }

  // Deleting supplier
  [HttpPost]
  [ValidateAntiForgeryToken]
  public ActionResult Delete(int id)
  {
    // find supplier by id
    CUSTOMER customer = db.CUSTOMERS.Find(id);
    // delete supplier
    db.CUSTOMERS.Remove(customer);
    // save model
    db.SaveChanges();
    // return success in JSON format
    return Json(true);
  }

  protected override void Dispose(bool disposing)
  {
    if (disposing)
    {
      db.Dispose();
    }
    base.Dispose(disposing);
  }
}
      

The Index method is used to display the Views/Customer/Index.cshtml view. The view itself will be presented a bit later. This view is actually an html page template with markup and JavaScript for initiating jqGrid. The data itself will be obtained asynchronously in the JSON format, using the Ajax technology. The selected type of sorting, the page number and the search parameters will determine the format of an HTTP request that will be handled by the GetData action. The parameters of the HTTP request are displayed in the input parameters of the GetData method. We generate a LINQ query based on these parameters and send the retrieved result in the JSON format.

Note

Various libraries can assist with parsing the parameters of a query generated by jqGrid and make it easier to build the model. We have not used them in our examples so the code might be somewhat cumbersome. You can always improve it, of course.

The Create method is used to add a new customer record. The method has the [HttpPost] attribute specified for it to indicate that the parameters of the HTTP POST request () are to be displayed on the Customer model. Examine the following line:

[Bind(Include = "NAME,ADDRESS,ZIPCODE,PHONE")] CUSTOMER customer
      

Here Bind specifies which parameters of the HTTP request are to be displayed in the properties of the model.

The Attribute ValidateAntiforgeryToken

Note the ValidateAntiforgeryToken attribute. It is used to prevent forging requests between websites by verifying the tokens when the action method is called. The presence of this attribute requires that the HTTP request has an additional parameter named __RequestVerificationToken.

This parameter is automatically added to each form where the @Html.AntiForgeryToken() helper is specified. However, the jqGrid library uses dynamically generated Ajax requests rather than previously created web forms. To fix that, we need to change the shared view Views/Shared/_Layout.cshtml as follows:

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>@ViewBag.Title - ASP.NET application</title>
  @Styles.Render("~/Content/css")
  @Scripts.Render("~/bundles/modernizr")
  @Scripts.Render("~/bundles/jquery")
  @Scripts.Render("~/bundles/jquery-ui")
  <link href="~/Content/jquery.jqGrid/ui.jqgrid.css"
        rel="stylesheet" type="text/css" />
   <link href="~/Content/jquery.jqGrid/ui.jqgrid-bootstrap.css"
         rel="stylesheet" type="text/css" />
   <link href="~/Content/jquery.jqGrid/ui.jqgrid-bootstrap-ui.css"
         rel="stylesheet" type="text/css" />
   <script src="~/Scripts/jquery.jqGrid.min.js"
           type="text/javascript"></script>
    <script src="~/Scripts/i18n/grid.locale-en.js"
            type="text/javascript"></script>
</head>
<body>
  @Html.AntiForgeryToken()
  <script>
    
    function GetAntiForgeryToken() {
      var tokenField =
        $("input[type='hidden'][name$='RequestVerificationToken']");
      if (tokenField.length == 0) {
        return null;
      } else {
        return {
          name: tokenField[0].name,
          value: tokenField[0].value
        };
      }
    }

    // add prefilter to all ajax requests
    // it will add to any POST ajax request
    // AntiForgery token
    $.ajaxPrefilter(
      function (options, localOptions, jqXHR) {
        if (options.type !== "GET") {
          var token = GetAntiForgeryToken();
          if (token !== null) {
            if (options.data.indexOf(""X-Requested-With") === -1) {
              options.data = "X-Requested-With=XMLHttpRequest"
              + ((options.data === "") ? "" : "&" + options.data);
            }
            options.data = options.data + "&" + token.name + '='
                         + token.value;
          }
        }
      }
    );
    // initialize the general properties of the jqGrid module
    $.jgrid.defaults.width = 780;
    $.jgrid.defaults.responsive = true;
    $.jgrid.defaults.styleUI = 'Bootstrap';
  </script>

  <!-- Navigation menu -->
  <div class="navbar navbar-inverse navbar-fixed-top">
    <div class="container">
      <div class="navbar-header">
        <button type="button" class="navbar-toggle" data-toggle="collapse"
                data-target=".navbar-collapse">
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"7gt;</span>
        </button>
      </div>>
      <div class="navbar-collapse collapse">
        <ul class="nav navbar-nav">
          <li>@Html.ActionLink("Customers", "Index", "Customer")</li>
          <li>@Html.ActionLink("Goods", "Index", "Product")</li>
          <li>@Html.ActionLink("Invoices", "Index", "Invoice")</li>
        </ul>
      </div>
    </div>
  </div>

  <div class="container body-content">
    @RenderBody()
    <hr />
    <footer>
      <p>&copy; @DateTime.Now.Year - ASP.NET application</p>
    </footer>
  </div>

  @Scripts.Render("~/bundles/bootstrap")
  @RenderSection("scripts", required: false)
</body>
</html>
        

Prev: Creating a User InterfaceFirebird Documentation IndexUp: Creating Web Applications in Entity Framework with MVCNext: Bundles
Firebird Documentation IndexFirebird 3.0 Developer's GuideCreating Web Applications in Entity Framework with MVC → Adapting the Controller to jqGrid