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

时间:2014-01-16 10:13:28

标签: asp.net-mvc twitter-bootstrap asp.net-mvc-4

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

我想要当用户单击新建按钮时打开创建视图在模态引导程序中以及当用户单击编辑链接时在模态引导程序中打开编辑视图。我写这个代码

// <![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>

当用户点击New Link Modal表单Work Good时,但当用户点击编辑按钮时出现此错误

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

请帮帮我。谢谢大家

EDIT-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 个答案:

答案 0 :(得分:1)

您在此处遇到的问题是您正在向不需要它的控制器操作添加验证。让我们首先看一下你的控制器,你有:

// GET: /City/Edit/5
[ValidateAntiForgeryToken]
public virtual ActionResult Edit(int? id)

在Get请求中需要防伪令牌。您通常只会在POST请求中包含[ValidateAntiForgeryToken]属性 - 它们用于阻止某人向您发布数据,而无需通过您的网站。 Check this tutorial了解概述。

现在再加上这个,你需要在[View]中使用HtmlHelper调用@ Html.AntiForgeryToken()获得相应的BeginForm [ValidateAntiForgeryToken]令牌。在您的代码中,编辑链接是1)不在表单中,2)没有这个。

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