【转】依赖注入的威力,.NET Core的魅力:解决MVC视图中的中文被html编码的问题
有园友在博问中提了这样一个问题 —— .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));
转自:http://www.cnblogs.com/dudu/p/5879913.html
【转】依赖注入的威力,.NET Core的魅力:解决MVC视图中的中文被html编码的问题的更多相关文章
- 依赖注入的威力,.NET Core的魅力:解决MVC视图中的中文被html编码的问题
		
有园友在博问中提了这样一个问题 —— .NET Core 中文等非英文文字html编码输出问题,到我们的 ASP.NET Core 项目中一看,也是同样的问题. 比如下面的Razor视图代码: @{ ...
 - 解决.NET Core MVC 视图中的中文被html编码的问题
		
在 .net core mvc 视图输出 变量的时候 默认使用的是 UnicodeRanges.BasicLatin 进行的编码 所以 输出中文后在查看源码的时候是进过编码了的 . 解决方案 在 ...
 - ASP。使用依赖注入的asp.net Core 2.0用户角色库动态菜单管理
		
下载source code - 2.2 MB 介绍 在开始这篇文章之前,请阅读我的前一篇文章: 开始使用ASP.NET Core 2.0身份和角色管理 在上一篇文章中,我们详细讨论了如何使用ASP.N ...
 - Asp.Net Core 项目实战之权限管理系统(4) 依赖注入、仓储、服务的多项目分层实现
		
0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...
 - ASP.NET Core 中文文档 第三章 原理(10)依赖注入
		
原文:Dependency Injection 作者:Steve Smith 翻译:刘浩杨 校对:许登洋(Seay).高嵩 ASP.NET Core 的底层设计支持和使用依赖注入.ASP.NET Co ...
 - net core 依赖注入问题
		
net core 依赖注入问题 最近.net core可以跨平台了,这是一个伟大的事情,为了可以赶上两年以后的跨平台部署大潮,我也加入到了学习之列.今天研究的是依赖注入,但是我发现一个问题,困扰我很久 ...
 - ASP.NET Core 依赖注入(DI)简介
		
ASP.NET Core是从根本上设计来支持和利用依赖注入. ASP.NET Core应用程序可以通过将其注入到Startup类中的方法中来利用内置的框架服务,并且应用程序服务也可以配置为注入. AS ...
 - ASP.NET Core 2.0 : 六. 举个例子来聊聊它的依赖注入
		
本文通过一个维修工与工具库的例子形象的描述一下为什么要用依赖注入.它的工作原理是什么样的, 然后根据这个类比一下ASP.NET Core 中的依赖注入, 从而深刻了解它的使用方法.注意事项以及回收机制 ...
 - [译]ASP.NET Core依赖注入深入讨论
		
原文链接:ASP.NET Core Dependency Injection Deep Dive - Joonas W's blog 这篇文章我们来深入探讨ASP.NET Core.MVC Core中 ...
 
随机推荐
- Lists.newArrayListWithExpectedSize( int estimatedSize)
			
Lists.newArrayListWithExpectedSize( int estimatedSize) 构造一个期望长度为estimatedSize的ArrayList实例. 源码: publ ...
 - 【shell】awk按域去除重复行
			
首先解释一下什么叫“按域去除重复行”: 有的时候我们需要去除的重复行并不是整行都重复,两行的其中一列的元素相同我们有的时候就需要认定这两行重复,因此有了今天的内容. 去除重复行shell有一个原生命令 ...
 - centos6.9 PHP的编译安装并连接nginx
			
1.安装yum -y install libxml2-devel openssl-devel bzip2-devel libmcrypt-devel 解决php包的依赖关系,可能libmcrypt会报 ...
 - Eclipse如何导入maven项目,以及配置maven
			
Eclipse如何导入maven项目,以及配置maven 一.准备工作 1. eclipse,安装了eclipse 2. 一个需要导入的maven项目 3. 下载好了的压缩包apache-maven- ...
 - VMware install  MikroTik RouterOS
			
1 download the vmdk from Mikro Tik official website 2 create a new vmware host with use an exited vm ...
 - USACO比赛题泛刷
			
随时可能弃坑. 因为不知道最近要刷啥所以就决定刷下usaco. 优先级排在学习新算法和打比赛之后. 仅有一句话题解.难一点的可能有代码. 优先级是Gold>Silver.Platinum刷不动. ...
 - MySQL 之 索引原理与慢查询优化
			
当考虑到数据多的时候,并且要加速查询时候,就不得不 用到索引了. 索引本质:通过不断地缩小想要获取数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件, 也就是说,有了这种索引机制,我们可 ...
 - 错误模块“AspNetCoreModuleV2"解决
			
如图 HTTP 错误 500.21 - Internal Server Error 处理程序"aspNetCore"在其模块列表中有一个错误模块"AspNetCoreMo ...
 - 8、Dockerfile详解
			
除了init之外,每一个进程都应该是其他进程的子进程(init是内核启动的),当手动启动nginx时,那么这个nginx就以shell子进程存在.当打开一个命令行提示符时,这个就相当于在运行一个she ...
 - [mysql]You must reset your password using ALTER USER statement before executing this statement.
			
原因分析: MySQL版本5.6.6版本起,添加了password_expired功能,它允许设置用户的过期时间.这个特性已经添加到mysql.user数据表,但是它的默认值是”N”,可以使用ALTE ...