【问题标题】:Generating HTML from non-MVC class从非 MVC 类生成 HTML
【发布时间】:2016-03-22 11:42:56
【问题描述】:

我有一个方法可以获取给定字符串的本地化并返回它。此方法由HtmlHelper 的扩展方法调用,以便可以从 Razor 视图访问。但是,有时我们也会在控制器和其他非 Razor 的地方使用它,这就是我们有“内部”方法的原因。

现在,出于调试目的,我想将返回的本地化(或可能不是)字符串包装成一些 HTML(类似于<span class="localized">Returned text</span>)。但是,如果我写

return string.Format("<span class=\"localized\">{0}</span>", text);

然后呈现的页面包含&lt; 和&gt; 字符,就好像它们是HTML 编码的一样,所以输出是假的。

当然,我不能调用 HtmlHelper.Raw(string s),部分原因是我不知道如何从 MVC 控制器外部创建 HtmlHelper,然后因为它返回一个不可分配的 IHtmlString到string。

如果我调用HttpUtility.HtmlEncode(string s),文本会被两次编码,呈现的页面显示&amp;lt;span class&amp;eq;&amp;quot;...。

我应该怎么做才能在视图中有一个呈现为 HTML 的字符串?


编辑

这是来自 Helper 静态类的代码(所有扩展方法都有效,除了它们的行为错误):

public static string localize(string textId)
{
    string ret = "";

    // Query to obtain the localized string, 
    //   or to obtain a fallback in case there are issues 
    //   (missing localization, wrong id...)
    // In the end, ret is filled with the output string

#if !OFFICIAL
    ret = string.Format("<span class=\"localized\" title=\"{1}\">{0}</span>", ret, expression);
#endif

    return ret;
}

public static string localize(this HtmlHelper htmlhelper, string expression)
{
    return trad(textId);
}

【问题讨论】:

  • 你的 string.Format 方法是从哪里调用的?
  • IHtmlString.ToString() 返回string
  • @Lee,来自inner方法内部,可以被HtmlHelper扩展方法调用,也可以从其他地方调用。
  • @StephenMuecke,你是对的,但我无法浏览项目的所有视图并将@Html.localize("textId") 更改为@Html.localize("textId").ToString()...
  • 问题是由于将本地化置于 HTML 级别的不幸决定造成的,现在您正试图通过编程解决问题。恕我直言,唯一真正的解决方案是重新设计解决方案的这一部分,例如通过创建一个 LocalizationHelper 然后从 HTML 中使用它,而不是相反。

标签: c# asp.net-mvc razor


【解决方案1】:

鉴于您发表了您想要制作的评论

@Html.localize("textId")

输出一个 HTML 元素,解决方案似乎很明显:返回类型为 string,这在设计上是不可能的。所以改变你的方法不返回string。

您已经发现原则上可以使用返回IHtmlString 的HtmlHelper.Raw,但IHtmlString 不能分配给string。如果您将返回类型更改为IHtmlString,问题就解决了。

【讨论】:

  • 没错,但还有一点。我的一些本地化字符串有占位符,因为它们应该传递给string.Format()。 string.Format() 当然只接受字符串,而不是IHtmlStrings,如果我返回一个IHtmlString 然后调用ToString() 那么好处就失去了,所以我最终还是会看到一些文本字符串,就像它们被编码一样.有什么建议吗?
  • @Simone 我认为这不适合您现在的设计。你需要重新思考你的设计。但是,如果您现在拥有@string.Format(Html.localize("textId"), "param1", "param2"),您应该能够毫不费力地将其更改为@Html.localize("textId", "param1", "param2"),您让Html.localize 在将结果填充到&lt;span&gt; 元素之前调用string.Format。
  • 好建议@hvd,我希望我可以避免它,但我想我必须忍受它。我现在正在尝试。
【解决方案2】:

我认为你应该这样创建你的方法:

  • 非助手Localize 方法应该只尝试返回本地化的string。添加 html 标签与此方法无关。 (你也可以在这里添加html标签,没有任何问题,因为在下一个方法中,我们使用HtmlString创建输出。)
  • 辅助方法,应该使用以前的方法,然后添加你需要的html标签,最后返回一个HtmlString。

代码:

public static class Extensions
{
    public static string Localize(string exp)
    {
        var ret = exp;
        try
        {
            //try to apply localized version of exp, for example:
            ret = exp + "_Localized";
        }
        catch(Exception ex)
        { 
            //Log ex
        }

        return ret;
    }

    public static IHtmlString Localize(this HtmlHelper htmlhelper, string exp)
    {
        var ret = string.Format("<span class=\"localized\" title=\"{0}\">{1}</span>",
                                exp, Localize(exp));
        return new HtmlString(ret);
    }
}

【讨论】:

  • 这会解决一些问题,但这不是我所需要的,因为 1) 我需要 span 来准确跟踪本地化过程中出现的问题,而帮助者的 Localize 对此一无所知,并且 2 ) 这不会跟踪我所做的所有本地化。如果我从控制器(而不是通过帮助程序)调用该方法,则不会采取任何额外的操作。
  • 没问题,你可以把html放回non-helper,这只是一个关于关注点分离的建议。它会按预期工作,因为我使用HtmlString 作为输出。
  • 没错,但还有一点。我的一些本地化字符串有占位符,因为它们应该传递给string.Format()。 string.Format() 当然只接受字符串,而不是IHtmlStrings,如果我返回一个IHtmlString 然后调用ToString() 那么好处就失去了,所以我最终还是会看到一些文本字符串,就像它们被编码一样.对此有何建议?
  • 您应该复制并运行并测试代码以检测其工作方式。例如要测试,在第一种方法中使用ret = exp + "&lt;a href=''&gt;Link&lt;/a&gt;"; 并查看结果。或者使用例如@Html.Localize("&lt;a href=''&gt;Link&lt;/a&gt;")你会看到方法的结果。
  • 不行,我已经在测试了。我让助手的方法返回一个IHtmlString,但是当我将它传递给string.Format() 时,问题又回来了。完整通话:string.Format( Html.Localize("textId").ToString(), param1, param2 )
【解决方案3】:

Razor 按原样渲染string。对于带有标记的扩展方法,您应该使用 HtmlString。

如果你声明你的方法如下:

public static HtmlString localize(this HtmlHelper htmlhelper, string expression)
{
    return new HtmlString(trad(textId));
}

您将能够使用自己的扩展方法,例如

@Html.localize('your string')

这将被呈现为正确的标记

【讨论】:

  • 没错,但还有一点。我的一些本地化字符串有占位符,因为它们应该传递给string.Format()。 string.Format() 当然只接受字符串,而不接受IHtmlStrings,如果我返回一个IHtmlString 然后调用ToString() 那么好处就失去了,所以我最终仍然会出现一些文本字符串,就好像它们被编码一样.有什么建议吗?
猜你喜欢
  • 1970-01-01
  • 2012-03-27
  • 1970-01-01
  • 1970-01-01
  • 2014-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多