0

I have this view that brings in all data from an entity:

@model MyApplication.Application.TableModel<Entities.FPDrinkingWater>
@{
Layout = null;

var insertionMode = InsertionMode.Replace;
var fail = "displayFailure";
var target = "UnverifiedDrinkingWatersContent";
var ajax = "UnverifiedDrinkingWaterLogLoader";
var verify = Html.UserHasClaim("FP/DrinkingWater/VerifyDrinkingWater");
var action = "VerifyDrinkingWater";
string form = action + "Form";
}

<br />

@if (Model != null && Model.Alert != null && Model.Alert.Message != null)
{
@Html.Alert(Model.Alert)
}

@MyHelper.Loader(ajax)

<div class="form-group">
<table id="UnverifiedDrinkingWaterTable" class="table table-hover">
    <thead>
        <tr>
            <th>@Html.LabelFor(m => m.Data.FirstOrDefault().SID)</th>
            <th>@Html.LabelFor(m => m.Data.FirstOrDefault().Location)</th>
            <th>@Html.LabelFor(m => m.Data.FirstOrDefault().Replicate)</th>
            <th>@Html.LabelFor(m => m.Data.FirstOrDefault().CollectionDate) 
   </th>
            <th>@Html.LabelFor(m => m.Data.FirstOrDefault().CollectionTime) 
   </th>
            <th>@Html.LabelFor(m => m.Data.FirstOrDefault().Collectors)</th>
            <th>@Html.LabelFor(m => m.Data.FirstOrDefault().Clorinated)</th>
            <th>@Html.LabelFor(m => m.Data.FirstOrDefault().Comments)</th>
            <th>@Html.LabelFor(m => m.Data.FirstOrDefault().Verified)</th>
        </tr>
    </thead>
    <tbody>

        @for (int i = 0; i < Model.Data.Count(); i++)
        {
            using (Ajax.BeginForm(actionName: action, routeValues: null,

    htmlAttributes: new { id = form, @class = "form-horizontal" }, 
ajaxOptions: 
new AjaxOptions
            {
                InsertionMode = InsertionMode.Replace,
                UpdateTargetId = target,
                OnSuccess = "success",
                LoadingElementId = ajax
            }))
            {
                @Html.AntiForgeryToken()

                <tr>
                    <td>@Html.DisplayFor(m => m.Data[i].SID)</td>
                    <td>@Html.DisplayFor(m => m.Data[i].Location)</td>
                    <td>@Html.DisplayFor(m => m.Data[i].Replicate)</td>
                    <td>@Html.DisplayFor(m => m.Data[i].CollectionDate)</td>
                    <td>@Html.DisplayFor(m => m.Data[i].CollectionTime)</td>
                    <td>@Html.DisplayFor(m => m.Data[i].Collectors)</td>
                    <td>@Html.DisplayFor(m => m.Data[i].Clorinated)</td>
                    <td>@Html.DisplayFor(m => m.Data[i].Comments)</td>
                    <td>@Html.CheckBoxFor(v => v.Data[i].Verified, new { 
data_url = Url.Action("VerifyDrinkingWater", "DrinkingWater"), id = 
"checkboxid" }) </td>
                </tr>
           }
        }

    </tbody>
</table>
</div>

<hr />

        @if (Model.Data.Count > 0)
        {
            <script>
                $(document).ready(function () {
                    makeDataTable('UnverifiedDrinkingWaterTable');
                });

                (function () {
                    $('#checkboxid').change(function () {
                        var data = {};
                        data[$(this).attr('name')] = $(this).is('checked');

                        $.ajax({
                            url: $(this).data('url'),
                            type: 'POST',
                            data: data,
                            success: function (result) {
                            }

                        });
                    });

                    });

            </script>
        }

What my goal is that I want to update 3 fields on the record displayed in the table by checking the "Verified" checkbox. I followed This Link to enable a click event on the checkboxfor. However, I receive an error claiming that The required anti-forgery form field __RequestVerificationToken is not present.. This is the only error I receive.

So my question is, how can I combine the AntiForgeryToken creation by the Ajax call AND pass the checked status of the checkbox at the same time and then pass it to the controller? Right now it's not even touching the controller and just giving me the AntiForgeryToken Error.

Braden
  • 135
  • 1
  • 11
  • Did you bother to read the links I gave you in your [previous question](https://stackoverflow.com/questions/51796201/asp-net-mvc-5-post-checkboxfor-to-controller-with-onclick-using-ajax). You have multiple errors in your code (including invalid html - a `
    ` cannot be a child of ``, it makes no sense to have `@Ajax.BeginForm()` and then use `$.ajax()`, its a terrible UI to submit a form when you click on a checkbox, you have duplicate `id` attributes which is also invalid html etc etc)
    –  Aug 13 '18 at 22:41
  • I'm sorry for my ignorance with this issue. I understand there are a lot of things wrong in this view. I'm doing my best to learn as I go. – Braden Aug 13 '18 at 22:57
  • Is a better format to select all of the checkboxes that are to be verified and then pass the collection to the controller where it loops over each one in a `foreach` testing if the verified field is true or false and then updating accordingly? – Braden Aug 13 '18 at 22:59
  • Yes. And to generate the html for binding to a collection, refer [this answer](https://stackoverflow.com/questions/30094047/post-an-html-table-to-ado-net-datatable/30094943#30094943) - you will need a hidden input for the ID property, plus a `@Html.CheckBoxFor(m => m.Data[i].Verified)` –  Aug 13 '18 at 23:06
  • Thank you for the advice and patience. I will look at all of the links you've posted. – Braden Aug 14 '18 at 00:41

1 Answers1

0

just get the token using

var token = $('input[name="__RequestVerificationToken"]').val();

and put it in data like this

var data = { 
__RequestVerificationToken: token 
}

please note that you render the AntiForgeryToken multiple times, so modify your code to have the ability to get the right AntiForgeryToke of each form

  • Sweet, that's a simple fix than what I searched for earlier. Now I have a new problem that when it reaches the controller everything is null....but more importantly it reaches the controller! Thanks! – Braden Aug 13 '18 at 22:48