Perform CRUD operation using anti-forgery token

21 Dec 202220 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.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'
            };
        }
    });
</script>

Now assign the custom adaptor to the grid as follows.

<script>
    function load(args) {
        this.dataSource.adaptor = customAdaptor;
    }
</script>
@using Syncfusion.EJ2
@Html.AntiForgeryToken()

<div>
    <ejs-grid id="Grid" load="load" toolbar="@(new List<string>() { "Add","Delete","Update", "Cancel" })" allowPaging="true">
        <e-data-manager json="@ViewBag.data" adaptor="RemoteSaveAdaptor" insertUrl="/Home/Insert" updateUrl="/Home/Update" removeUrl="/Home/Delete"></e-data-manager>
        <e-grid-editSettings allowDeleting="true" allowEditing="true" allowAdding="true" mode="Normal"></e-grid-editSettings>
        <e-grid-pagesettings pageCount="5"></e-grid-pagesettings>
        <e-grid-columns>
            <e-grid-column field="OrderID" headerText="Order ID" isPrimaryKey="true" validationRules="@(new { required=true})" textAlign="Right" width="120"></e-grid-column>
            <e-grid-column field="CustomerID" headerText="Customer Name" validationRules="@(new { required=true})" width="150"></e-grid-column>
            <e-grid-column field="Freight" headerText="Freight" validationRules="@(new { required=true})" textAlign="Right" editType="numericedit" format="C2" width="120"></e-grid-column>
            <e-grid-column field="ShipCity" headerText="Ship City" width="170"></e-grid-column>            
        </e-grid-columns>
    </ejs-grid>
</div>

<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.