ASP.MVC所需的防伪表单字段错误

3

我是MVC和Bootstrap的初学者。我想创建一个像这样的表单: enter image description here

我希望当用户点击“新建”按钮时,在Modal Bootstrap中打开创建视图;当用户点击“编辑”链接时,在Modal Bootstrap中打开编辑视图。我写了这段代码:

// <![CDATA[
(function ($) {
    $.bootstrapModalAjaxForm = function (options) {
        var defaults = {
            renderModalPartialViewUrl: null,
            renderModalPartialViewData: null,
            postUrl: '/',
            loginUrl: '/login',
            beforePostHandler: null,
            completeHandler: null,
            errorHandler: null
        };
        var options = $.extend(defaults, options);

        var validateForm = function (form) {

            var val = form.validate();
            val.form();
            return val.valid();
        };

        var enableBootstrapStyleValidation = function () {
            $.validator.setDefaults({
                highlight: function (element, errorClass, validClass) {
                    if (element.type === 'radio') {
                        this.findByName(element.name).addClass(errorClass).removeClass(validClass);
                    } else {
                        $(element).addClass(errorClass).removeClass(validClass);
                        $(element).closest('.form-group').removeClass('has-success').addClass('has-error');
                    }
                    $(element).trigger('highlited');
                },
                unhighlight: function (element, errorClass, validClass) {
                    if (element.type === 'radio') {
                        this.findByName(element.name).removeClass(errorClass).addClass(validClass);
                    } else {
                        $(element).removeClass(errorClass).addClass(validClass);
                        $(element).closest('.form-group').removeClass('has-error').addClass('has-success');
                    }
                    $(element).trigger('unhighlited');
                }
            });
        }

        var enablePostbackValidation = function () {
            $('form').each(function () {
                $(this).find('div.form-group').each(function () {
                    if ($(this).find('span.field-validation-error').length > 0) {
                        $(this).addClass('has-error');
                    }
                });
            });
        }

        var processAjaxForm = function (dialog) {
            $('form', dialog).submit(function (e) {
                e.preventDefault();

                if (!validateForm($(this))) {

                    return false;
                }


                if (options.beforePostHandler)
                    options.beforePostHandler();


                $.ajaxSetup({ cache: false });
                $.ajax({
                    url: options.postUrl,
                    type: "POST",
                    data: $(this).serialize(),
                    success: function (result) {
                        if (result.success) {
                            $('#dialogDiv').modal('hide');
                            if (options.completeHandler)
                                options.completeHandler();
                        } else {
                            $('#dialogContent').html(result);

                            $.validator.unobtrusive.parse("#dialogContent");
                            enablePostbackValidation();
                            processAjaxForm('#dialogContent');

                            if (options.errorHandler)
                                options.errorHandler();
                        }
                    }
                });
                return false;
            });
        };


        var mainContainer = "<div id='dialogDiv' class='modal fade'><div id='dialogContent'></div></div>";
        enableBootstrapStyleValidation(); 
        $.ajaxSetup({ cache: false });
        $.ajax({
            type: "POST",
            url: options.renderModalPartialViewUrl,
            data: options.renderModalPartialViewData,
            //contentType: "application/json; charset=utf-8",
          //  headers: { __RequestVerificationToken: $("input[name=__RequestVerificationToken]").val() },
            // dataType: "json",
            dataType: "html",
            complete: function (xhr, status) {
                var data = xhr.responseText;
                var data = xhr.responseText;
                if (xhr.status == 403) {
                    window.location = options.loginUrl; 
                }
                else if (status === 'error' || !data) {
                    if (options.errorHandler)
                        options.errorHandler();
                }
                else {
                    var dialogContainer = "#dialogDiv";
                    $(dialogContainer).remove();
                    $(mainContainer).appendTo('body');

                    $('#dialogContent').html(data); 
                    $.validator.unobtrusive.parse("#dialogContent");  
                    enablePostbackValidation();

                    $('#dialogDiv').modal({
                        backdrop: 'static', 
                        keyboard: true
                    }, 'show');

                    processAjaxForm('#dialogContent');
                }
            }
        });
    };
})(jQuery);
// ]]>

和控制器

public partial class CityController : Controller
    {
        private ArchiveEntities db = new ArchiveEntities();

        // GET: /City/
        public virtual ActionResult Index()
        {
            return View(db.CITIES.ToList());
        }

        // GET: /City/Details/5
        public virtual ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            CITy city = db.CITIES.Find(id);
            if (city == null)
            {
                return HttpNotFound();
            }
            return View(city);
        }

        // GET: /City/Create
        [ValidateAntiForgeryToken]
        public virtual ActionResult Create()
        {
            return View();
        }

        // POST: /City/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public virtual ActionResult Create([Bind(Include = "CITY_ID,CITY_NAME,CITY_ABBR,REMARK")] CITy city)
        {
            if (this.ModelState.IsValid)
            {
                //todo: SaveChanges;
                db.CITIES.Add(city);
                db.SaveChanges();
                return Json(new { success = true });
            }
            this.ModelState.AddModelError("", "Error");
            return PartialView("_ModalPartialView", city);

            //if (ModelState.IsValid)
            //{
            //    db.CITIES.Add(city);
            //    db.SaveChanges();
            //   // return View(MVC.City.RenderModalPartialView());
            //}

            //return View();
        }


        // GET: /City/Edit/5
        [ValidateAntiForgeryToken]
        public virtual ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            CITy city = db.CITIES.Find(id);
            if (city == null)
            {
                return HttpNotFound();
            }
           // return View(city);
            return PartialView(Views._Edit, city);
        }

        // POST: /City/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public virtual ActionResult Edit([Bind(Include = "CITY_ID,CITY_NAME,CITY_ABBR,REMARK")] CITy city)
        {
            if (ModelState.IsValid)
            {
                db.Entry(city).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(city);
        }

        // GET: /City/Delete/5
        public virtual ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            CITy city = db.CITIES.Find(id);
            if (city == null)
            {
                return HttpNotFound();
            }
            return View(city);
        }

        // POST: /City/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public virtual ActionResult DeleteConfirmed(int id)
        {
            CITy city = db.CITIES.Find(id);
            db.CITIES.Remove(city);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
        [HttpGet]
        public virtual ActionResult List()
        {
            return PartialView(Views._CityList, db.CITIES.ToList());
        }

        [HttpPost]
        // [AjaxOnly]
       // [OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
        public virtual ActionResult List2()
        {
            return PartialView(Views._CityList, db.CITIES.ToList());
        }

        public virtual ActionResult RenderModalPartialView()
        {

            return PartialView(viewName: "_ModalPartialView", model: new CITy() { CITY_ABBR = "", CITY_NAME = "" });
        }

        [HttpPost]
        //[AjaxOnly]
        public virtual ActionResult Index(CITy user) 
        {
            if (this.ModelState.IsValid)
            {
                //todo: SaveChanges;
                return Json(new { success = true });
            }

            this.ModelState.AddModelError("", "Error");
            return PartialView("_ModalPartialView", user);
        }
    }
}

索引视图

<div id="info">
    @Html.Action(MVC.City.List())
</div>
@section JavaScript
{
    <script type="text/javascript">

        function addToken(data) {
            data.__RequestVerificationToken = $("input[name=__RequestVerificationToken]").val();
            return data;
        }

        function EditPopup(id) {



            $.bootstrapModalAjaxForm({
                postUrl: '@postEditUrl',
                renderModalPartialViewUrl: '@renderModalPartialViewEditUrl',
                renderModalPartialViewData:addToken({ id: id }),
                loginUrl: '/login',
                beforePostHandler: function () {
                    alert('beforePost');
                },
                completeHandler: function () {

                    $.ajax({
                        type: "POST",
                        url: '@loadInfoUrl',
                        complete: function (xhr, status) {
                            var data = xhr.responseText;
                            if (xhr.status == 403) {
                                window.location = "/login";
                            }
                            else if (status === 'error' || !data || data == "nok") {
                                alert('error');
                            }
                            else {

                                $("#info").html(data);
                            }
                        }
                    });

                },
                errorHandler: function () {
                    alert("error");
                }
            });


        }
        $(function () {


            $('#btnCreate').click(function(e) {
                e.preventDefault(); //مي‌خواهيم لينك به صورت معمول عمل نكند

                $.bootstrapModalAjaxForm({
                    postUrl: '@postDataUrl',
                    renderModalPartialViewUrl: '@renderModalPartialViewUrl',
                    renderModalPartialViewData: {},
                    loginUrl: '/login',
                    beforePostHandler: function() {
                        alert('beforePost');
                    },
                    completeHandler: function() {

                        $.ajax({
                            type: "POST",
                            url: '@loadInfoUrl',
                            complete: function (xhr, status) {
                                var data = xhr.responseText;
                                if (xhr.status == 403) {
                                    window.location = "/login";
                                }
                                else if (status === 'error' || !data || data == "nok") {
                                    alert('error ajax');
                                }
                                else {

                                    $("#info").html(data);
                                }
                            }
                        });
                        // alert('completeHandler');


                    },
                    errorHandler: function() {
                        alert("error");
                    }
                });
            });


        });
    </script>
}

以及 _CityList

 @model IEnumerable<TestTwiter.Models.CITy>


    <table class="table">
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.CITY_NAME)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.CITY_ABBR)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.REMARK)
            </th>
            <th></th>
        </tr>

    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.CITY_NAME)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.CITY_ABBR)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.REMARK)
            </td>
            <td>
                <span onclick="EditPopup(@item.CITY_ID)">Edit</span>|||||
                <a href="JavaScript:void(0)" onclick="EditPopup(@item.CITY_ID)" >Edit</a>
                @*@Html.ActionLink("Edit", "Edit", new { id=item.CITY_ID }) |*@
                @Html.ActionLink("Details", "Details", new { id=item.CITY_ID }) |
                @Html.ActionLink("Delete", "Delete", new { id=item.CITY_ID })
            </td>
        </tr>
    }

    </table>

以及 _ModalPartialView

    @model TestTwiter.Models.CITy
    @{

    }
    @using (Html.BeginForm())
    {
        @Html.ValidationSummary(true, null, new { @class = "alert alert-warning" })
        @Html.AntiForgeryToken()
        <div>
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
                            ×
                        </button>
                        <h4 class="modal-title">
                            Title
                        </h4>
                    </div>
                    <div class="modal-body">
                        <fieldset class="form-horizontal">
                            <legend>User</legend>
                            <div class="form-group">
                                @Html.LabelFor(model => model.CITY_NAME, new { @class = "col col-lg-4 control-label" })
                                <div class="col col-lg-8 controls">
                                    @Html.EditorFor(model => model.CITY_NAME)
                                    @Html.ValidationMessageFor(model => model.CITY_NAME, null, new { @class = "help-block" })
                                </div>
                            </div>
                            <div class="form-group">
                                @Html.LabelFor(model => model.CITY_ABBR, new { @class = "col col-lg-4 control-label" })
                                <div class="col col-lg-8 controls">
                                    @Html.EditorFor(model => model.CITY_ABBR)
                                    @Html.ValidationMessageFor(model => model.CITY_ABBR, null, new { @class = "help-block" })
                                </div>
                            </div>
                            <div class="form-group">
                                @Html.LabelFor(model => model.REMARK, new { @class = "col col-lg-4 control-label" })
                                <div class="col col-lg-8 controls">
                                    @Html.EditorFor(model => model.REMARK)
                                    @Html.ValidationMessageFor(model => model.REMARK, null, new { @class = "help-block" })
                                </div>
                            </div>
                           </fieldset>
                    </div>
                    <div class="modal-footer">
                        <button class="btn btn-primary" type="submit">
                            Send
                        </button>
                        <button class="btn" data-dismiss="modal" aria-hidden="true">
                            Cancel
                        </button>
                    </div>
                </div>
            </div>
        </div>
    }
and _Edit

@model TestTwiter.Models.CITy

@using (Html.BeginForm())
{


    <div class="form-horizontal">
        <h4>CITy</h4>
        <hr />
        @Html.ValidationSummary(true)
        @Html.AntiForgeryToken()
        @Html.HiddenFor(model => model.CITY_ID)

        <div class="form-group">
            @Html.LabelFor(model => model.CITY_NAME, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.CITY_NAME)
                @Html.ValidationMessageFor(model => model.CITY_NAME)
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.CITY_ABBR, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.CITY_ABBR)
                @Html.ValidationMessageFor(model => model.CITY_ABBR)
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.REMARK, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.REMARK)
                @Html.ValidationMessageFor(model => model.REMARK)
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

当用户在“新链接”模态框中点击时,它能正常工作。但是当用户点击“编辑”按钮时,我会收到这个错误。

The required anti-forgery form field &quot;__RequestVerificationToken&quot; is not present

请帮我。谢谢大家

编辑-01:从所有 GET 请求中删除 [ValidateAntiForgeryToken] 标签。

public partial class CityController : Controller
    {
        private ArchiveEntities db = new ArchiveEntities();

        // GET: /City/
        public virtual ActionResult Index()
        {
            return View(db.CITIES.ToList());
        }

        // GET: /City/Details/5
        public virtual ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            CITy city = db.CITIES.Find(id);
            if (city == null)
            {
                return HttpNotFound();
            }
            return View(city);
        }

        // GET: /City/Create
        //[ValidateAntiForgeryToken]
        public virtual ActionResult Create()
        {
            return View();
        }

        // POST: /City/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public virtual ActionResult Create([Bind(Include = "CITY_ID,CITY_NAME,CITY_ABBR,REMARK")] CITy city)
        {
            if (this.ModelState.IsValid)
            {
                //todo: SaveChanges;
                db.CITIES.Add(city);
                db.SaveChanges();
                return Json(new { success = true });
            }
            this.ModelState.AddModelError("", "Error");
            return PartialView("_ModalPartialView", city);

            //if (ModelState.IsValid)
            //{
            //    db.CITIES.Add(city);
            //    db.SaveChanges();
            //   // return View(MVC.City.RenderModalPartialView());
            //}

            //return View();
        }


        // GET: /City/Edit/5



        // POST: /City/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        //[HttpPost]
        //[ValidateAntiForgeryToken]
        //public virtual ActionResult Edit([Bind(Include = "CITY_ID,CITY_NAME,CITY_ABBR,REMARK")] CITy city)
        //{
        //    if (ModelState.IsValid)
        //    {
        //        db.Entry(city).State = EntityState.Modified;
        //        db.SaveChanges();
        //        return RedirectToAction("Index");
        //    }
        //    return View(city);
        //}

        // GET: /City/Delete/5
        public virtual ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            CITy city = db.CITIES.Find(id);
            if (city == null)
            {
                return HttpNotFound();
            }
            return View(city);
        }

        // POST: /City/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public virtual ActionResult DeleteConfirmed(int id)
        {
            CITy city = db.CITIES.Find(id);
            db.CITIES.Remove(city);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
        [HttpGet]
        public virtual ActionResult List()
        {
            return PartialView(Views._CityList, db.CITIES.ToList());
        }

        [HttpPost]
        // [AjaxOnly]
       // [OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
        public virtual ActionResult List2()
        {
            return PartialView(Views._CityList, db.CITIES.ToList());
        }

        public virtual ActionResult Edit()
        {
            int id = 1;
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            CITy city = db.CITIES.Find(id);
            if (city == null)
            {
                return HttpNotFound();
            }
            // return View(city);
            return PartialView(Views._Edit, city);
        }

        public virtual ActionResult RenderModalPartialView()
        {

            return PartialView(viewName: "_ModalPartialView", model: new CITy() { CITY_ABBR = "", CITY_NAME = "" });
        }

        [HttpPost]
        //[AjaxOnly]
        public virtual ActionResult Index(CITy user) 
        {
            if (this.ModelState.IsValid)
            {
                //todo: SaveChanges;
                return Json(new { success = true });
            }

            this.ModelState.AddModelError("", "Error");
            return PartialView("_ModalPartialView", user);
        }
    }
1个回答

1
您在这里遇到的问题是您正在为不需要验证的控制器操作添加验证。让我们从查看您的控制器开始,您有:
// GET: /City/Edit/5
[ValidateAntiForgeryToken]
public virtual ActionResult Edit(int? id)

要求在Get请求上使用防伪标记。通常情况下,您只需要在POST请求中包含[ValidateAntiForgeryToken]属性-它们用于防止某人通过未经过您站点的途径向您发布数据。请查看此教程以获取概述。

现在,与此相关的任何地方,您都需要在View中使用HtmlHelper调用@Html.AntiForgeryToken()来配对[ValidateAntiForgeryToken]标记的BeginForm。在您的代码中,编辑链接既不在表单中,也没有这个功能。

因此,简而言之:从控制器的GET请求中删除[ValidateAntiForgeryToken]属性,它应该正常工作。


你是否已经从控制器的所有GET请求中删除了[ValidateAntiForgeryToken]?你是否检查过每个进行POST操作的地方,是否已经将提交包装在BeginForm中,并添加了一个调用@Html.AntiForgeryToken()的语句? - Wolfwyrd
是的,我从所有 GET 请求中删除了 [ValidateAntiForgeryToken]。 - Pouya
我编辑问题并添加新的控制器。 - Pouya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接