We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date
close icon

ValidateAntiForgeryToken stop the grid update action

I have using the asp.net core mvc tag helper grid.  I set the mode to dialog which will pop up a dialog to modify my data.  When I click save, it not fire the server side update action.  If I remove the ValidateAntiForgeryToken in the server side update action, it work accordingly.


Below is my code

          [View]
        @Html.AntiForgeryToken()
        <ejs-grid id="Grid" allowPaging="true" allowSorting="true" allowFiltering="true" toolbar="@(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" })">
            <e-grid-editSettings allowAdding="true" allowDeleting="true" allowEditing="true" mode="Dialog" showDeleteConfirmDialog="true"></e-grid-editSettings>
            <e-grid-pagesettings pageSize="5" pageSizes="true"></e-grid-pagesettings>
            <e-grid-selectionsettings checkboxMode="ResetOnRowClick" type="Single"></e-grid-selectionsettings>
            <e-data-manager url="/Product/DataSoruce" adaptor="UrlAdaptor" insertUrl="/Product/Create" , updateUrl="/Product/Update" removeUrl="/Product/Delete"></e-data-manager>
            <e-grid-columns>
                <e-grid-column field="Id" headerText="Id" textAlign="Left" width="120" isPrimaryKey="true" visible="false"></e-grid-column>
                <e-grid-column field="Code" headerText="Code" textAlign="Left" width="120" validationRules="@(new { required = true})"></e-grid-column>
                <e-grid-column field="Description" headerText="Description" textAlign="Left" width="120" validationRules="@(new { required = true})"></e-grid-column>
            </e-grid-columns>
        </ejs-grid>


      [Controller]

       [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Update([FromBody]CRUDModel<ProductUpdateDeleteViewModel> model)
        {
            if(!ModelState.IsValid)
            {
                return View();
            }

            if(! await productService.UpdateAsync(model.Value))
            {
                return View();
            }
            //return RedirectToAction(nameof(Index));
            return Json(model.Value);
        }




9 Replies

TS Thavasianand Sankaranarayanan Syncfusion Team March 18, 2019 10:25 AM UTC

Hi Derick, 

Greetings from Syncfusion, 

We have validated your query from the provided information and we were tried to reproduce the reported defect from our end. But, unfortunately we are unsuccessful to reproduce the issue. Please refer the sample code example and sample for more information 
 
[index.cshtml] 

@Html.AntiForgeryToken() 
 
<ejs-grid id="Grid" allowPaging="true" load="onLoad"  toolbar="@( new List<object>() {"Add","Edit","Delete","Update","Cancel"})"> 
    <e-grid-editsettings allowAdding="true" allowDeleting="true" allowEditing="true" mode="Dialog"></e-grid-editsettings> 
    <e-data-manager url="/Index?handler=DataSource" adaptor="UrlAdaptor" insertUrl="/Index?handler=Insert" updateUrl="/Index?handler=Update" removeUrl="/Index?handler=Delete" ></e-data-manager> 
    <e-grid-pageSettings pageCount="5" pageSize="5"></e-grid-pageSettings> 
    <e-grid-columns> 
        . . . . 
    </e-grid-columns> 
</ejs-grid> 
 
<script> 
    function onLoad() {    
        this.dataSource.dataSource.headers = [{ 'XSRF-TOKEN': $("input:hidden[name='__RequestVerificationToken']").val() }]; 
    } 
</script> 
Screenshot:  
 

If you still face the same problem, then please provide some more information it will be helpful for us to provide a better solution as soon as possible 

  1. Share the video to demonstrate of your issue.
  2. Ensure the EJ2 Grid source, DLL versions.
  3. If possible try to reproduce the issue in the attached sample.
 
Please get back to us, if you have any concern. 

Regards, 
Thavasianand S. 



DL Derick Loo March 20, 2019 01:03 AM UTC

Hi Thavasianand S,
                Thanks for the guide.  Finally found the mistake.  Forgot to add the antiforgery service pipeline in the Startup.  Now it's work.

Regards,
Derick


TS Thavasianand Sankaranarayanan Syncfusion Team March 20, 2019 04:31 AM UTC

Hi Derick, 
 
We are happy that the problem has been solved. 
 
Please get back to us if you need any further assistance.  
                          
Regards, 
Thavasianand S.


DL Derick Loo May 27, 2019 03:23 AM UTC

The ValidateAntiForgeryToken not work again in the update action.  It not fire the update action in controller.  In the client side, it keep call onActionFailure function event there is no error.  I use custom dialog to display the details for update.  I have add the antiforgery service in startup.  
Below is the grid code

@Html.AntiForgeryToken()
<ejs-grid id="Grid" allowPaging="true" toolbar="@(new List<string>() {"Add", "Edit", "Update", "Delete" })" actionComplete="actionComplete" actionFailure="onActionFailure">
    <e-grid-editSettings allowAdding="true" allowDeleting="true" allowEditing="true" mode="Dialog" showDeleteConfirmDialog="true" template='#dialogTemplate'></e-grid-editSettings>
    <e-grid-pagesettings pageSize="8" pageSizes="true"></e-grid-pagesettings>
    <e-data-manager adaptor="UrlAdaptor" url="/Product/DataSoruce" insertUrl="/Product/Create" updateUrl="/Product/Update" removeUrl="/Product/Delete"></e-data-manager>
    <e-grid-columns>
        <e-grid-column field="Id" headerText="Id" textAlign="Left" width="120" isPrimaryKey="true" visible="false"></e-grid-column>
        <e-grid-column field="Code" headerText="Code" textAlign="Left" width="120"></e-grid-column>
        @*<e-grid-column field="Description" headerText="Description" textAlign="Left" width="120" validationRules="@(new { required = true})"></e-grid-column>*@
        <e-grid-column field="Description" headerText="Description" textAlign="Left" width="120"></e-grid-column>
    </e-grid-columns>
</ejs-grid>

<script id="dialogTemplate" type="text/x-template">
    <div id="dialogTemp"></div>
</script>

<script type="text/javascript">

        function onLoad() {
            this.dataSource.dataSource.headers = [{ 'XSRF-TOKEN': $("input:hidden[name='__RequestVerificationToken']").val() }];
        }

        function onActionFailure(args) {
            var errorMsg;
            if (args.error) {
                errorMsg = args.error[0].error.responseText;
            } else {
                errorMsg = args[0].error.responseText;
            }
            var grid = document.getElementById("Grid").ej2_instances[0];
            //this is ej2 old version to get control from dialog template, the dialog template is render inside the grid.
            //In the latest version of ej2, the dialog template is render outside the grid.
            //var validationEle = grid.element.querySelector(".e-edit-dialog .form-row div.e-float-input #ErrorMessages");

            if (document.getElementById(this.element.id + '_dialogEdit_wrapper') != null) {
                var validationEle = document.getElementById(this.element.id + '_dialogEdit_wrapper').querySelector('#ErrorMessage');
                var errormessageEle = document.getElementById(this.element.id + '_dialogEdit_wrapper').querySelector('#spanerrormessage');

                if (errormessageEle != null) {
                    errormessageEle.remove();
                }
                var spanEle = document.createElement("span");
                spanEle.textContent = '*' + errorMsg;
                spanEle.style.color = "red";
                spanEle.id = "spanerrormessage";
                validationEle.parentElement.appendChild(spanEle)
            }
            else {
                alert(errorMsg);
            }
    }

        function actionComplete(args) {
         if (args.requestType === 'beginEdit' || args.requestType === 'add') {
                let spinner = ej.popups.createSpinner({ target: args.dialog.element });
                ej.popups.showSpinner(args.dialog.element);

                 if (args.requestType === 'add') {
                     //  args.form.ej2_instances[0].addRules("ShipCountry", { required: true })
                     var ajax = new ej.base.Ajax({
                         url: "@Url.Action("CreatePartial", "Product")", //render the partial view
                         type: "POST",
                         contentType: "application/json",
                         data: JSON.stringify({ value: args.rowData })
                     });
                     ajax.send().then(function (data) {
                         appendElement(data, args.form); //Render the edit form with selected record
                         args.form.elements.namedItem('Code').focus();
                         ej.popups.hideSpinner(args.dialog.element);
                     }).catch(function (xhr) {
                         console.log(xhr);
                         ej.popups.hideSpinner(args.dialog.element);
                     });
                 }
                 if (args.requestType === 'beginEdit') {
                      var ajax = new ej.base.Ajax({
                         url: "@Url.Action("EditPartial", "Product")", //render the partial view
                         type: "POST",
                         contentType: "application/json",
                         data: JSON.stringify({ value: args.rowData })
                     });
                     ajax.send().then(function (data) {
                         appendElement(data, args.form); //Render the edit form with selected record
                         args.form.elements.namedItem('Code').focus();
                         ej.popups.hideSpinner(args.dialog.element);
                     }).catch(function (xhr) {
                         console.log(xhr);
                         ej.popups.hideSpinner(args.dialog.element);
                     });
                 }
            }
        }

        function appendElement(elementString, form) {
            form.querySelector("#dialogTemp").innerHTML = elementString;
            var script = document.createElement('script');
            script.type = "text/javascript";
            var serverScript = form.querySelector("#dialogTemp").querySelector('script');
            script.textContent = serverScript.innerHTML;
            document.head.appendChild(script);
            serverScript.remove();
        }
</script> 


TS Thavasianand Sankaranarayanan Syncfusion Team May 27, 2019 08:52 AM UTC

Hi Derick Loo, 

We have validated the provided code snippet and we have tried to reproduce the reported defect on our end. But, unfortunately we are unable to reproduce the issue. Please refer the below code example, sample and video for more information. 
[index.cshtml] 

<ejs-grid id="Grid" allowPaging="true" toolbar="@(new List<string>() {"Add", "Edit", "Update", "Delete" })" actionComplete="actionComplete"> 
    <e-grid-editSettings allowAdding="true" allowDeleting="true" allowEditing="true" mode="Dialog" template='#dialogtemplate'></e-grid-editSettings> 
    <e-data-manager url="/Home/UrlDataSource" adaptor="UrlAdaptor" insertUrl="/Home/Insert" updateUrl="/Home/Update" removeUrl="/Home/Remove"></e-data-manager> 
    <e-grid-columns> 
        .    .    .   . 
   </e-grid-columns> 
</ejs-grid> 

[HomeController.cs] 

public async Task<IActionResult> Update([FromBody]CRUDModel<Orders> model) 
        { 
            var data = order.Where(or => or.OrderID == model.Value.OrderID).FirstOrDefault(); 
            if(data != null) 
            { 
                .    .    .    . 
           } 
            return Json(model.Value); 
        } 



If you still face the same defect, then please provide some more information it will helpful for us to provide a better solution as soon as possible. 

  1. Ensure EJ2 Grid source, DLL version.
  2. Share video to demonstrate of your issue.
 
Please get back to us, if you need further assistance. 

Regards, 
Thavasianand S. 



DL Derick Loo May 28, 2019 06:57 AM UTC

Hi Thavasianand,
     The sample provided do not use the antiforgerytoken in the controller and view.  I have modify provided sample by add the antiforgery in the controller and view.  And add the antiforgery service in startup, the Edit function not been fired.  What mistake I have make?

Attachment: EJ2Grid_14082ea6.zip


TS Thavasianand Sankaranarayanan Syncfusion Team May 29, 2019 12:28 PM UTC

Hi Derick, 

We have validated query provided a sample code and we suggest you to use the customAdaptor in created event of EJ2 Grid. In the below code, we have achieved this requirement by extend the UrlAdaptor as a 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.  Please refer the below code example for more information. 

[index.cshtml] 

@Html.AntiForgeryToken() 
<ejs-grid id="Grid" allowPaging="true" toolbar="@(new List<string>() {"Add", "Edit", "Update", "Delete" })" created="created" actionComplete="actionComplete"> 
    <e-grid-editSettings allowAdding="true" allowDeleting="true" allowEditing="true" mode="Dialog" template='#dialogtemplate'></e-grid-editSettings>     
    <e-grid-columns> 
.    .    .    . 
    </e-grid-columns> 
</ejs-grid> 
 
<script id='dialogtemplate' type="text/x-template"> 
    <div id="dialogTemp"> 
    </div> 
</script> 
<script type="text/javascript"> 
   
    function created() { 
 
        class CustomAdaptor extends ej.data.UrlAdaptor { 
            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) { 
                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) { 
                new 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' 
                }; 
            } 
        } 
 
        var grid = document.querySelector('#Grid').ej2_instances[0]; 
        grid.dataSource = new ej.data.DataManager({ 
            url: "/Home/UrlDatasource/", 
            insertUrl: "/Home/Insert/", 
            updateUrl: "/Home/Update", 
            removeUrl:"/Home/Remove", 
            adaptor: new CustomAdaptor() 
        }); 
 
    } 
 
[HomeController.cs] 
 
       [HttpPost] 
        [ValidateAntiForgeryToken] 
        public async Task<IActionResult> Insert([FromBody]CRUDModel<Orders> value) 
        { 
            order.Insert(0, value.Value); 
            return Json(value.Value); 
        } 
        [HttpPost] 
        [ValidateAntiForgeryToken] 
        public async Task<IActionResult> Update([FromBody]CRUDModel<Orders> model, string action, string __RequestVerificationToken) 
        { 
            var data = order.Where(or => or.OrderID == model.Value.OrderID).FirstOrDefault(); 
            if(data != null) 
            { 
                data.OrderID = model.Value.OrderID; 
                data.CustomerID = model.Value.CustomerID; 
                data.EmployeeID = model.Value.EmployeeID; 
                data.OrderDate = model.Value.OrderDate; 
                data.ShipCity = model.Value.ShipCity; 
                data.Freight = model.Value.Freight; 
            } 
            return Json(model.Value); 
        } 
        [HttpPost] 
        [ValidateAntiForgeryToken] 
        public void Remove([FromBody]CRUDModel<Orders> Value) 
        { 
           var data = order.Where(or => or.OrderID.Equals(Value.Key)).FirstOrDefault(); 
           order.Remove(data); 
        } 
        public class Orders 
        { 
            public Orders() 
            { 
 
            } 
            public Orders(long OrderId, string CustomerId, int EmployeeId, double Freight, DateTime OrderDate, string ShipCity, string ShipCountry) 
            { 
                this.OrderID = OrderId; 
                this.CustomerID = CustomerId; 
                this.EmployeeID = EmployeeId; 
                this.Freight = Freight; 
                this.OrderDate = OrderDate; 
                this.ShipCity = ShipCity; 
                this.ShipCountry = ShipCountry; 
            } 
 



Please get back to us, if you need further assistance. 

Regards, 
Thavasianand S. 



DL Derick Loo May 30, 2019 09:45 AM UTC

Hi Thavasianand,
     I got no luck to make it work.  I have use the custom dialog for the add and update action.  So, I use the actioncomplete to prompt the partial dialog and actionfailure to get the custom error message from controller to display on the partial dialog.  When I run the project, it keep fired the actionfailure.  I have attached my view for your reference.

Thanks.

Attachment: index_c9f74de.zip


TS Thavasianand Sankaranarayanan Syncfusion Team May 31, 2019 01:45 PM UTC

Hi Derick Loo, 

Please share the error details you have getting on actionFailure event of EJ2 Grid while you run the project. It would be more helpful for us to provide better assistance from our end. 

Regards, 
Thavasianand S. 


Loader.
Live Chat Icon For mobile
Up arrow icon