Perform CRUD operation using anti-forgery token

21 Dec 202217 minutes to read

Anti-forgery token is used between the client and server to prevent cross-site request forgery (CSRF) attack. For more information on preventing CSRF attack, refer to the link.

While performing grid save operation, you can send anti-forgery token along with the save request using the below custom adaptor.

This custom adaptor will read the anti-forgery token from the hidden element and send it along with the request. Also content type is set to application/x-www-form-urlencoded; charset=UTF-8 since the ValidateAntiForgeryToken will look for the token in the form encoded data.

<script>

    window.customAdaptor = new ej.data.UrlAdaptor();

    customAdaptor = ej.base.extend(customAdaptor, {

        processResponse: function (data, ds, query, xhr, request, changes) {
            request.data = JSON.stringify(data);
            return ej.data.UrlAdaptor.prototype.processResponse.call(this,data, ds, query, xhr, request, changes);
        },
        insert: function (dm, data, tableName) {
            return {
                url: dm.dataSource.insertUrl || dm.dataSource.crudUrl || dm.dataSource.url,
                data: $.param({
                    //Added the anti-forgery token.
                    __RequestVerificationToken: document.getElementsByName("__RequestVerificationToken")[0].value,
                    value: data,
                    table: tableName,
                    action: 'insert'
                }),
                contentType: 'application/x-www-form-urlencoded; charset=UTF-8'
            }
        },
        update: function (dm, keyField, value, tableName) {
            return {
                url: dm.dataSource.updateUrl || dm.dataSource.crudUrl || dm.dataSource.url,
                data: $.param({
                    //Added the anti-forgery token.
                    __RequestVerificationToken: document.getElementsByName("__RequestVerificationToken")[0].value,
                    value: value,
                    table: tableName,
                    action: 'insert'
                }),
                contentType: 'application/x-www-form-urlencoded; charset=UTF-8'
            };
        },
    });
</script>

Now assign the custom adaptor to the grid as follows.

<script>
    function load(args) {
        this.dataSource.adaptor = customAdaptor;
    }
</script>
@Html.EJS().Grid("RemoteSaveAdaptor").DataSource(dataManager => { dataManager.Json(ViewBag.dataSource.ToArray()).InsertUrl("/Home/Insert").RemoveUrl("/Home/Delete").UpdateUrl("/Home/Update").Adaptor("RemoteSaveAdaptor");

}).EditSettings(e => { e.AllowAdding(true).AllowEditing(true).AllowDeleting(true); }).Columns(col =>
{
    col.Field("OrderID").HeaderText("Order ID").Width("120").IsPrimaryKey(true).TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Add();
    col.Field("CustomerID").HeaderText("Customer ID").Width("150").Add();
    col.Field("Freight").HeaderText("Freight").Width("130").TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Format("C2").Add();
    col.Field("OrderDate").HeaderText("Order Date").Width("120").TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Format("yMd").Add();

}).Toolbar(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" }).Render()

<script type="text/javascript">
    window.customAdaptor = new ej.data.RemoteSaveAdaptor();

    customAdaptor = ej.base.extend(customAdaptor, {
        insert(dm, data, tableName) {
            this.updateType = 'add';
            return {
                url: dm.dataSource.insertUrl || dm.dataSource.crudUrl || dm.dataSource.url,
                data: $.param({
                    //Added the anti-forgery token.
                    __RequestVerificationToken: document.getElementsByName("__RequestVerificationToken")[0].value,
                    value: data,
                    table: tableName,
                    action: 'insert'
                }),
                contentType: 'application/x-www-form-urlencoded; charset=UTF-8'
            };
        },
        update(dm, keyField, value, tableName) {
            debugger;
            this.updateType = 'update';
            this.updateKey = keyField;
            return {
                type: 'POST',
                url: dm.dataSource.updateUrl || dm.dataSource.crudUrl || dm.dataSource.url,
                data: $.param({
                    //Added the anti-forgery token.
                    __RequestVerificationToken: document.getElementsByName("__RequestVerificationToken")[0].value,
                    value: value,
                    action: 'update',
                    keyColumn: keyField,
                    key: value[keyField],
                    table: tableName
                }),
                contentType: 'application/x-www-form-urlencoded; charset=UTF-8'
            };
        },
        remove(dm, keyField, value, tableName) {
            ej.data.JsonAdaptor.prototype.remove(dm, keyField, value);
            return {
                type: 'POST',
                url: dm.dataSource.removeUrl || dm.dataSource.crudUrl || dm.dataSource.url,
                data: $.param({
                    //Added the anti-forgery token.
                    __RequestVerificationToken: document.getElementsByName("__RequestVerificationToken")[0].value,
                    key: value,
                    keyColumn: keyField,
                    table: tableName,
                    action: 'remove'

                }),
                contentType: 'application/x-www-form-urlencoded; charset=UTF-8'
            };
        }

    });

    function load(args) {
        this.dataSource.adaptor = customAdaptor;
    }
</script>
public class HomeController : Controller
{
    public static List<Orders> order = new List<Orders>();
    
    public ActionResult Index()
    {
        if (order.Count == 0)
            BindDataSource();
        ViewBag.data = order.ToArray();
        return View();
    }

    public void BindDataSource()
    {
        int code = 10000;
        for (int i = 1; i < 10; i++)
        {
            order.Add(new Orders(code + 1, "VINET", i + 0, 2.3 * i, new DateTime(1991, 05, 15), "Berlin"));
            order.Add(new Orders(code + 2, "ANATR", i + 2, 3.3 * i, new DateTime(1990, 04, 04), "Madrid"));
            order.Add(new Orders(code + 3, "ANTON", i + 1, 4.3 * i, new DateTime(1957, 11, 30), "Cholchester"));
            order.Add(new Orders(code + 4, "BLONP", i + 3, 5.3 * i, new DateTime(1930, 10, 22), "Marseille"));
            order.Add(new Orders(code + 5, "BOLID", i + 4, 6.3 * i, new DateTime(1953, 02, 18), "Tsawassen"));
            code += 5;
        }
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Update(Orders value, string action)
    {
        var data = order.Where(or => or.OrderID == value.OrderID).FirstOrDefault();
        if (data != null)
        {
            data.OrderID = value.OrderID;
            data.CustomerID = value.CustomerID;
            data.EmployeeID = value.EmployeeID;
            data.Freight = value.Freight;
            data.OrderDate = value.OrderDate;
            data.ShipCity = value.ShipCity;
        }
        return Json(value);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Insert(Orders value, string action)
    {
        order.Insert(0, value);
        return Json(value);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public void Remove(int key)
    {
        var data = order.Where(or => or.OrderID == key).FirstOrDefault();
        if (data != null)
        {
            order.Remove(data);
        }
    }

    public class Orders
    {
        public Orders()
        {

        }
        public Orders(long OrderId, string CustomerId, int EmployeeId, double Freight, DateTime OrderDate, string ShipCity)
        {
            this.OrderID = OrderId;
            this.CustomerID = CustomerId;
            this.EmployeeID = EmployeeId;
            this.Freight = Freight;
            this.OrderDate = OrderDate;
            this.ShipCity = ShipCity;
        }
        public long OrderID { get; set; }
        public string CustomerID { get; set; }
        public int EmployeeID { get; set; }
        public double Freight { get; set; }
        public DateTime OrderDate { get; set; }
        public string ShipCity { get; set; }
    }
}

NOTE

You can find the full sample at our GitHub repository.