使用ajax发布对MVC控制器的满意度

时间:2014-11-12 10:31:27

标签: jquery ajax asp.net-mvc tinymce contenteditable

通常情况下,我只使用普通的@Html.BeginForm表单,并按照以下方式将其与ajax一起发布:

$("btnSubmit").on("click", function () {
    var $form = $("form#frmNewArticle");
    $form.submit();
});

$("form#frmNewArticle").submit(function () {
    $.post($(this).attr("action"), $(this).serialize(), function (data) {
        if (!data.IsOK) {
            // in the case of an error, just display info about it to the user
        }
        else {
            // if the post went well, go back to the article listing
            window.location.href = '@Url.Content("~/Articles")';
        }
        return;
    });

    return false;
});

我一直在我的MVC网站上取得了巨大的成功,但现在我想要一个富文本编辑器,所以我现在已经实现了tinymce并且我想使用它的内联模式,它使用了contenteditable html元素:

<h2>Article Title</h2>
<h3 class="editable"></h3>

<h2>Article Content</h2>
<div class="editable"></div>

<input type="button id="btnSubmit" value="Create" />

<script>
    tinymce.init({
        selector: "div.editable",
        theme: "modern",
        plugins: [
            ["advlist autolink link image lists charmap print preview hr anchor pagebreak spellchecker"],
            ["searchreplace wordcount visualblocks visualchars code fullscreen insertdatetime media nonbreaking"],
            ["save table contextmenu directionality emoticons template paste"]
        ],
        add_unload_trigger: false,
        schema: "html5",
        inline: true,
        toolbar: "undo redo | styleselect | bold italic underline | alignleft aligncenter alignright alignjustify | bullist numlist | outdent indent | link image     | print preview media",
        statusbar: false
    });
    tinymce.init({
        selector: "h3.editable",
        theme: "modern",
        add_unload_trigger: false,
        schema: "html5",
        inline: true,
        toolbar: "undo redo",
        statusbar: false
    });
</script>

我在这里看到其他问题,建议让可编辑的元素填充页面上的实际输入字段,但这对我来说似乎有点低效,但后来我不是这方面最了解的...

过去我已经指定了发布的确切数据(如下所示),但这对我来说也不合适......

$.ajax({
    type: 'POST',
    url: '/includes/contact.php',
    data: { name: $('#contact-name').val(),
            from: $('#contact-email').val(),
            subject: $('#contact-subject').val(),
            message: $('#contact-message').val()
    }, // end data
    success: function clearFields() {
        // clear form fields
    } // end success
}); // end ajax

有人可以告诉我,如果我只是在喋喋不休地谈论这是怎么做的,或者我是否正在使用这些方法中的任何一种?

如果我不是,那怎么意思呢?

提前致谢!

1 个答案:

答案 0 :(得分:0)

以下是适合您的TestCase。

div html内容不会序列化,因此在发布表单时,实现此案例的解决方法是获取内容可编辑部分的隐藏textarea字段的帮助。

在这种情况下,HeaderTitleHtml和ArticleHtml字段呈现为隐藏的TextAreas,在表单提交之前,我们使用各自的可编辑控件HTML设置这些值。

请参阅下面的按钮单击处理程序代码以了解:

$("#btnSubmit").on("click", function () {
    $("#HeaderTitleHtml").html($("h3.editable").html());
    $("#ArticleHtml").html($("div.editable").html());
    $("form#frmNewArticle").submit();
});
  

完整的源代码

型号: ArticleModel

namespace TestCases.MVC.Models
{
    public class ArticleModel
    {
        [AllowHtml]
        public string HeaderTitleHtml { get; set; }

        [AllowHtml]
        public string ArticleHtml { get; set; }
    }

}

控制器操作

public class ArticlesController : Controller
{
    public ActionResult ArticleContent()
    {
        return View();
    }

    [HttpPost]
    public ActionResult SaveArticle(ArticleModel model)
    {
        if (ModelState.IsValid) {

            //Perform some business logic here
            //Save Title and Article Html in database.

            return Json(new { IsOK = true });
        }

        return Json(new { IsOK = false });
    }
}

查看: ArticleContent.cshtml

@model TestCases.MVC.Models.ArticleModel
<style>
    .htmlTextHolder {
        display: none;
    }
</style>
@using (Html.BeginForm("SaveArticle", "Articles", FormMethod.Post, new { id = "frmNewArticle" })) {
    @Html.TextAreaFor(model => model.HeaderTitleHtml, new { @class = "htmlTextHolder" })
    @Html.TextAreaFor(model => model.ArticleHtml, new { @class = "htmlTextHolder" })
    <div>
        <h2>Article Title</h2>
        <h3 class="editable">Title Text goes here</h3>

        <h2>Article Content</h2>
        <div class="editable">Article Rich Text goes here</div>

        <p>
            <input type="button" id="btnSubmit" value="Create" />
        </p>

    </div>
}
@section scripts{
    <script src="//tinymce.cachefly.net/4.1/tinymce.min.js"></script>
    <script>
        tinymce.init({
            selector: "div.editable",
            theme: "modern",
            plugins: [
                ["advlist autolink link image lists charmap print preview hr anchor pagebreak spellchecker"],
                ["searchreplace wordcount visualblocks visualchars code fullscreen insertdatetime media nonbreaking"],
                ["save table contextmenu directionality emoticons template paste"]
            ],
            add_unload_trigger: false,
            schema: "html5",
            inline: true,
            toolbar: "undo redo | styleselect | bold italic underline | alignleft aligncenter alignright alignjustify | bullist numlist | outdent indent | link image     | print preview media",
            statusbar: false
        });

        tinymce.init({
            selector: "h3.editable",
            theme: "modern",
            add_unload_trigger: false,
            schema: "html5",
            inline: true,
            toolbar: "undo redo",
            statusbar: false
        });

        $("#btnSubmit").on("click", function () {
            $("#HeaderTitleHtml").html($("h3.editable").html());
            $("#ArticleHtml").html($("div.editable").html());
            $("form#frmNewArticle").submit();
        });

        $("form#frmNewArticle").submit(function () {
            $.post($(this).attr("action"), $(this).serialize(), function (data) {
                if (!data.IsOK) {
                    // in the case of an error, just display info about it to the user
                }
                else {
                    // if the post went well, go back to the article listing
                    window.location.href = '@Url.Content("~/Articles")';
                }
                return;
            });

            return false;
        });

    </script>
}

  

关于AllowHtml(vs)ValidateInput属性

要将丰富的文本编辑器(如tinymce)中的序列化数据和HTML内容发送到Controller Action,我们应该添加属性以允许HTML Content on Action方法或模型字段。

在模型中

public class ArticleModel 
{
    [AllowHtml]
    public string htmlContainer { get; set; }

    public string otherProperty { get; set; }
}

在控制器操作(不推荐)

  

ASP.NET具有自动帮助的内置请求验证   防止XSS和HTML注入攻击。如果你想   明确禁用此验证,您可以装饰您的操作   正在使用[ValidateInput(false)]属性发布到。

[HttpPost]
[ValidateInput(false)]   
public ActionResult SaveArticle(ArticleModel model)
{
    var JResult = new JsonResult();
    if (ModelState.IsValid)
    {
        ...
    }
    return JResult;
}
根据安全问题,

[ValidateInput(false)]不是最佳情况 请参阅:MVC Side effect of using [HttpPost, ValidateInput(false)]

最佳实践MSDN在此处说:http://msdn.microsoft.com/en-us/magazine/hh708755.aspx 只需在您想要的模型属性上使用[AllowHtml]即可。