MVC3 - 将换行符传递给ModelState.AddModelError

11
当后端出现错误时,MVC控制器通过 ModelState.AddModelError("", "message"); 返回消息。
我想让 'message' 在显示时换成两行,因此我想在它们之间添加 "\r\n""<br />"
我正在使用Razor通过 @Html.ValidationSummary(); 显示消息,但是View的HTML输出将其显示为&lt;br/&gt;
如何最好地传递换行符并在HTML输出级别将其解释为真正的
标签?
================================ Controller代码:
ModelState.AddModelError("", "Line one <br /> Line two.");
return Request.IsAjaxRequest() ? (ActionResult) PartialView("ViewName", model) 
            : View(model);

查看代码:

@using (Ajax.BeginForm("Index", "Home", new AjaxOptions { UpdateTargetId = "tv" })) 
{
    @if (Html.ValidationSummary() != null)
        @Html.Raw(Server.HtmlDecode(Html.ValidationSummary(true).ToString()))   

    ....
}

请提供更多信息,您想要做什么? - dknaack
ValidationSummary助手会自动对消息进行HTML编码。如果您想实现其他功能,您需要编写自定义助手。 - Darin Dimitrov
4个回答

16

ValidationSummary助手会对错误消息进行HTML编码,这是有意设计的。这意味着您不能使用HTML标签,因为它们将被编码。因此,您可以编写一个自定义助手程序来不进行编码:

public static class ValidationExtensions
{
    public static IHtmlString MyValidationSummary(this HtmlHelper htmlHelper)
    {
        var formContextForClientValidation = htmlHelper.ViewContext.ClientValidationEnabled ? htmlHelper.ViewContext.FormContext : null;
        if (htmlHelper.ViewData.ModelState.IsValid)
        {
            if (formContextForClientValidation == null)
            {
                return null;
            }
            if (htmlHelper.ViewContext.UnobtrusiveJavaScriptEnabled)
            {
                return null;
            }
        }

        var stringBuilder = new StringBuilder();
        var ulBuilder = new TagBuilder("ul");

        ModelState modelState;
        if (htmlHelper.ViewData.ModelState.TryGetValue(htmlHelper.ViewData.TemplateInfo.HtmlFieldPrefix, out modelState))
        {
            foreach (ModelError error in modelState.Errors)
            {
                string userErrorMessageOrDefault = error.ErrorMessage;
                if (!string.IsNullOrEmpty(userErrorMessageOrDefault))
                {
                    var liBuilder = new TagBuilder("li");
                    liBuilder.InnerHtml = userErrorMessageOrDefault;
                    stringBuilder.AppendLine(liBuilder.ToString(TagRenderMode.Normal));
                }
            }
        }

        if (stringBuilder.Length == 0)
        {
            stringBuilder.AppendLine("<li style=\"display:none\"></li>");
        }
        ulBuilder.InnerHtml = stringBuilder.ToString();

        TagBuilder divBuilder = new TagBuilder("div");
        divBuilder.AddCssClass(htmlHelper.ViewData.ModelState.IsValid ? HtmlHelper.ValidationSummaryValidCssClassName : HtmlHelper.ValidationSummaryCssClassName);
        divBuilder.InnerHtml = ulBuilder.ToString(TagRenderMode.Normal);
        if (formContextForClientValidation != null)
        {
            if (!htmlHelper.ViewContext.UnobtrusiveJavaScriptEnabled)
            {
                divBuilder.GenerateId("validationSummary");
                formContextForClientValidation.ValidationSummaryId = divBuilder.Attributes["id"];
                formContextForClientValidation.ReplaceValidationSummary = false;
            }
        }
        return new HtmlString(divBuilder.ToString(TagRenderMode.Normal));
    }
}

然后:

@Html.MyValidationSummary()

这是我们自定义帮助器中不进行HTML编码的以下行:

liBuilder.InnerHtml = userErrorMessageOrDefault;

在原始的帮助程序中,它看起来像这样:

liBuilder.SetInnerText(userErrorMessageOrDefault);

如果每次你的答案帮助了我,我就能得到一美元,那么现在我可能已经不用工作了,Darin。 - Chris
美好!谢谢Darin。 - Serj Sagan
谢谢你的回答,Darin!非常完美! - Dave Agaba

12

尝试使用Html.RawServer.HtmlDecode将验证摘要包装起来,像这样:

@Html.Raw(Server.HtmlDecode(Html.ValidationSummary().ToString()))

我修改了我的答案。我测试了修改后的代码,当错误信息中有<br />时,它返回了带有换行符的错误消息。 - counsellorben
也许我在 Ajax.BeginForm 中有验证。那会有什么区别吗? - SF Developer
@Filu,对于ValidationSummary,你没有太多的选择。正如我在评论中所说,默认情况下它会对消息进行HTML编码,这是设计上的考虑。因此,你需要编写一个自定义的帮助程序来解决这个问题。 - Darin Dimitrov
2
对我来说没问题!@Html.Raw(Server.HtmlDecode(Html.ValidationSummary(true, "", new { @class = "text-danger" }).ToString())) - Ray Linder
@DarinDimitrov,您的自定义帮助程序很棒,谢谢 - 但Coundsellorben和Ray是正确的:这个解决方案也可以工作。对于只在项目中使用一两次的人来说,这是一个好的快速选项。谢谢。 - MemeDeveloper
显示剩余3条评论

4

控制器:

ModelState.AddModelError("MyError", "Line 1" + Environment.NewLine + "Line 2");

Razor:

<span style="white-space: pre-line">@Html.ValidationSummary()</span>

2
在这里提出的插入 Environment.NewLine 的方法对我没有起作用。 - Mario Levesque
@levteck 你有什么想法,为什么它对我有效而对你无效? - ADH
2
@MarioLevesque 对我有用。请确保像示例那样进行span元素的样式处理。 - Lukas

1

虽然我的答案有些晚了,但这是我在谷歌搜索时得到的最佳结果,希望我的解决方案能帮助到某些人。

我绕过了问题,为每个错误消息行添加了单独的一行。显示效果非常好。

控制器代码:

    public ActionResult Edit(EditModel model)
    {
            try
            {
                //... do update
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains(Environment.NewLine))
                {
                    var messages = ex.Message.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (var message in messages)
                    {
                        this.ModelState.AddModelError(string.Empty, message);
                    }
                }
                else
                {
                    this.ModelState.AddModelError(string.Empty, ex.Message);
                }
            }
        //...

        return this.View(model);
    }

如果您使用AddModelError中的第一个参数键来引用输入,则此方法无效。 - marianotigre

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