有园友在博问中提了这样一个问题 —— .NET Core 中文等非英文文字html编码输出问题,到我们的 ASP.NET Core 项目中一看,也是同样的问题。

比如下面的Razor视图代码:

@{
ViewBag.Title = "代码改变世界";
}
<title>@ViewBag.Title</title>

输出的html代码变成了:

<title>代码改变世界</title>

上面的 @ViewBag.Title 实际上等同于下面的代码:

@Html.Raw(Html.Encode(ViewBag.Title))

所以解决这个问题需要从ASP.NET Core MVC中的HtmlHelper下手(上面代码中Html的类型就是HtmlHelper)。

从GitHub上签出MVC的源代码看看HtmlHelper.Encode()的实现:

private readonly IHtmlGenerator _htmlGenerator;
public string Encode(string value)
{
return _htmlGenerator.Encode(value);
}

实际调用的是IHtmlGenerator接口的Encode()方法,MVC中实现这个接口的是DefaultHtmlGenerator,其对应的Encode()实现代码如下:

private readonly HtmlEncoder _htmlEncoder;
public string Encode(string value)
{
return !string.IsNullOrEmpty(value) ? _htmlEncoder.Encode(value) : string.Empty;
}

原来真正干活的主角是HtmlEncoder,但它不是在MVC中实现的,而是在.NET Core Framework中实现的,命名空间是 System.Text.Encodings.Web 。

写个.NET Core控制台程序直接调用HtmlEncoder看看是不是就是它惹的祸。

public class Program
{
public static void Main(string[] args)
{
Console.WriteLine(HtmlEncoder.Default.Encode("代码改变世界"));
}
}

输出结果与MVC中是同样的问题。

试试不用默认的HtmlEncoder实例(HtmlEncoder.Default),而是自己调用HtmlEncoder.Create()方法创建实例,这时发现了UnicodeRange参数类型。

public static HtmlEncoder Create(params UnicodeRange[] allowedRanges);

当使用UnicodeRanges.All作为参数创建HtmlEncoder实例时,问题就解决了。

Console.WriteLine(HtmlEncoder.Create(UnicodeRanges.All).Encode("代码改变世界"));

紧接着从GitHub上签出System.Text.Encodings.Web的源代码,看看HtmlEncoder.Default对应的HtmlEncode实例是如何被创建的:

internal readonly static DefaultHtmlEncoder Singleton = new DefaultHtmlEncoder(new TextEncoderSettings(UnicodeRanges.BasicLatin));

原来用的是UnicodeRanges.BasicLatin,难怪中文会被编码,搞不懂为什么默认不用UnicodeRanges.All?

知道了问题的原因,解决起来就不难了,只要我们以HtmlEncoder.Create(UnicodeRanges.All)创建HtmlEncoder实例,并替换掉MVC中所用的默认HtmlEncoder实例。那如何替换呢?

回到MVC的源代码中,看看DefaultHtmlGenerator的实现,发现它的构造函数参数中有HtmlEncoder:

public DefaultHtmlGenerator(
IAntiforgery antiforgery,
IOptions<MvcViewOptions> optionsAccessor,
IModelMetadataProvider metadataProvider,
IUrlHelperFactory urlHelperFactory,
HtmlEncoder htmlEncoder,
ClientValidatorCache clientValidatorCache)
{
}

根据.NET从上到下、由内而外全面依赖注入的秉性,这个地方应该也是依赖注入的,我们只需注入一个新的HtmlEncoder实例即可,是不是这样呢?

码上一行,你就知道。

在 Startup.cs 的 ConfigureServices() 方法中添加下面的一行代码:

services.AddSingleton(HtmlEncoder.Create(UnicodeRanges.All));

运行ASP.NET Core站点,输出结果如下:

<title>代码改变世界</title>

一行注入,立马解决。依赖注入的威力,.NET Core的魅力。

更新1:根据 零度的火 的评论,更好的解决方法是

services.Configure<WebEncoderOptions>(options =>
{
options.TextEncoderSettings = new TextEncoderSettings(UnicodeRanges.All);
});

更新2:后来发现更好的解决方法

services.Configure<WebEncoderOptions>(options =>
options.TextEncoderSettings = new TextEncoderSettings(UnicodeRanges.BasicLatin,
UnicodeRanges.CjkUnifiedIdeographs));

依赖注入的威力,.NET Core的魅力:解决MVC视图中的中文被html编码的问题的更多相关文章

  1. 【转】依赖注入的威力,.NET Core的魅力:解决MVC视图中的中文被html编码的问题

    有园友在博问中提了这样一个问题 —— .NET Core 中文等非英文文字html编码输出问题,到我们的 ASP.NET Core 项目中一看,也是同样的问题. 比如下面的Razor视图代码: @{ ...

  2. 解决.NET Core MVC 视图中的中文被html编码的问题

    在  .net core mvc 视图输出 变量的时候 默认使用的是 UnicodeRanges.BasicLatin  进行的编码 所以 输出中文后在查看源码的时候是进过编码了的 . 解决方案 在 ...

  3. ASP。使用依赖注入的asp.net Core 2.0用户角色库动态菜单管理

    下载source code - 2.2 MB 介绍 在开始这篇文章之前,请阅读我的前一篇文章: 开始使用ASP.NET Core 2.0身份和角色管理 在上一篇文章中,我们详细讨论了如何使用ASP.N ...

  4. Asp.Net Core 项目实战之权限管理系统(4) 依赖注入、仓储、服务的多项目分层实现

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

  5. ASP.NET Core 中文文档 第三章 原理(10)依赖注入

    原文:Dependency Injection 作者:Steve Smith 翻译:刘浩杨 校对:许登洋(Seay).高嵩 ASP.NET Core 的底层设计支持和使用依赖注入.ASP.NET Co ...

  6. net core 依赖注入问题

    net core 依赖注入问题 最近.net core可以跨平台了,这是一个伟大的事情,为了可以赶上两年以后的跨平台部署大潮,我也加入到了学习之列.今天研究的是依赖注入,但是我发现一个问题,困扰我很久 ...

  7. ASP.NET Core 依赖注入(DI)简介

    ASP.NET Core是从根本上设计来支持和利用依赖注入. ASP.NET Core应用程序可以通过将其注入到Startup类中的方法中来利用内置的框架服务,并且应用程序服务也可以配置为注入. AS ...

  8. ASP.NET Core 2.0 : 六. 举个例子来聊聊它的依赖注入

    本文通过一个维修工与工具库的例子形象的描述一下为什么要用依赖注入.它的工作原理是什么样的, 然后根据这个类比一下ASP.NET Core 中的依赖注入, 从而深刻了解它的使用方法.注意事项以及回收机制 ...

  9. [译]ASP.NET Core依赖注入深入讨论

    原文链接:ASP.NET Core Dependency Injection Deep Dive - Joonas W's blog 这篇文章我们来深入探讨ASP.NET Core.MVC Core中 ...

随机推荐

  1. JSONP跨域的原理解析( 一种脚本注入行为)

    JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重要的安全性限制, 被称为“some-Origin Policy”(同源策略).这一策略对于Jav ...

  2. exe文件放在其他位置

    set PATH=%PATH%;%UGII_ROOT_DIR%call "E:\ZY\exe\uds_rename_parts_mohao.exe"E:\ZY\exe\uds_re ...

  3. Linux中的工作管理(Job Control )

    以前使用Linux老是会不小心按下Ctrl + z,然后就出现看不懂的情况,以为程序突然就没了,今天专门研究了下Linux下的几个快捷键和工作管理. 其中找到一篇很不错的文章,大部分是里面转载的. 原 ...

  4. PostMan插件安装

    一直没装上postman,今天运气好,竟装上了 给大家show一下吧,也希望大家跟我一样走弯路甚至于走不过去!:) 1.下载Postman_v4.1.3.rar,这个是我测试验证并打包的: 加QQ群: ...

  5. 开园第一篇 - 论移动开发环境 IOS与Android的差异

    首先,在真正写技术之前做个自我简介.本人08年开始学c语言 一年后,转vc++.开始接触MFC MFC做了两年.转眼11年了我考上了一个不知名的大专.搞C++发现没有市场了因为当时酷狗腾讯的软件已经日 ...

  6. Selenium IDE和Selenium RC的安装

    1       安装FireBug和FirePath 1.在火狐浏览器中,点击”添加附件”按钮,弹出”附加组件管理器”页面 2.在弹出页面中,输入“fireBug”,点击“搜索”按钮,弹出fireBu ...

  7. 【线段树套平衡树】【pb_ds】bzoj3196 Tyvj 1730 二逼平衡树

    线段树套pb_ds里的平衡树,在洛谷OJ上测试,后三个测试点TLE #include<cstdio> #include<algorithm> #include<ext/p ...

  8. DNS配置

    配置永久IP: cd  /etc/sysconfig/network-scripts/ 主DNS服务器配置: 由于caching-nameserver软件包提供了各种配置文件的模板,大大降低了BIND ...

  9. Android 文章列表

    Android  --列表-- Android(1)-Handler Looper Message MessageQueuehttp://www.cnblogs.com/TS-qrt/articles ...

  10. Visual Assist X 工具栏不显示 toolbar

    Visual Assist X ,工具栏,不显示, toolbar 1)首先确认安装顺序是否正确,先安装VC,再安装Visual Assist X 2)确认安装的Visual Assist是否添加到V ...