【问题标题】:Posting contenteditable to MVC controller with ajax使用 ajax 将 contenteditable 发布到 MVC 控制器
【发布时间】:2023-03-13 02:28:01
【问题描述】:

通常我只使用普通的@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

有人可以告诉我,我是否只是对如何做到这一点持迂腐态度,或者我是否正在使用这两种方法中的任何一种?

如果我不是,那该怎么做?

提前致谢!

【问题讨论】:

  • 你可以在Controller Action使用[ValidateInput(false)]属性
  • @VenkataPanga 我正在努力将数据发送到控制器
  • 是要将 HTML 标记内容发布到控制器操作,我们应该在带有 [ValidateInput(false)] 的操作方法之前或在模型属性上应用属性装饰,例如 [AllowHtml]

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


【解决方案1】:

下面是适合你的测试用例。

div html 内容不会被序列化,因此在发布表单时,实现这种情况的解决方法是借助内容可编辑部分的隐藏文本区域字段。

在这种情况下,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 属性

要将序列化数据和 HTML 内容从 tinymce 等富文本编辑器发送到 Controller Action,我们应该添加属性以允许在 Action 方法或模型字段上提供 HTML 内容。

在模型中

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 只需在要获取 html 的模型属性上使用 [AllowHtml]

【讨论】:

  • 再一次,我明白这一点,但我不明白我在视图上的 ajax 帖子应该是什么样子
  • 或者我在这里遗漏了一个概念?
猜你喜欢
  • 2012-09-08
  • 1970-01-01
  • 1970-01-01
  • 2016-12-07
  • 2013-03-24
  • 1970-01-01
  • 2021-11-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多