有园友在博问中提了这样一个问题 —— .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编码的问题的更多相关文章

  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. 转载-《Python学习手册》读书笔记

    转载-<Python学习手册>读书笔记 http://www.cnblogs.com/wuyuegb2312/archive/2013/02/26/2910908.html

  2. springboot-yml内list、map组合写法

    yml:myProps: varmaplist: key11: - t1 - t2 - t3 key22: - t11 - t22 - t33 list: - topic1 - topic2 - to ...

  3. 面试-java反射

    问题:简述Java中的反射使用 答: 1.作用: 可以通过配置文件来动态配置和加载类,以实现软件工程理论里所提及的类与类,模块与模块之间的解耦.反射最经典的应用是spring框架. 2. 定义 反射简 ...

  4. centos 7 rabbitmq 3.7.12 erlang 20.3源码安装

    1.下载erlang 官网地址 http://www.erlang.org/download 挑选合适的版本 然后 建议20.3运行命令 wget http://erlang.org/download ...

  5. spring-petclinic性能调优实战(转)

    1.spring-petclinic介绍 spring-petclinic是spring官方做的一个宠物商店,结合了spring和其他一些框架的最佳实践. 架构如下: 1)前端 Thymeleaf做H ...

  6. Oracle中的位图索引和函数索引

    位图索引 同样的,先说是什么,再说为什么. 上篇我们说过BTREE索引是将数据表的索引列和行号排序后以树状形式存在磁盘中.那位图索引是什么样的呢? 现有如下日志表,有操作类型字段op_type,该字段 ...

  7. Android系统分析之运营商显示流程分析之运营商信息的读取流程二

    运营商显示流程分析之运营商信息的读取流程 一. SIM卡运营商信息的读取 从前面的 运营商信息的获取和赋值 可以知道SIM卡运营商的赋值最终是在 SIMRecords 中完成的, 而SIM卡信息的相关 ...

  8. sqllite中实现字符串分割

    WITH split(word, str) AS (    -- alternatively put your query here    -- SELECT '', category||',' FR ...

  9. MyBatis-plus使用

    https://blog.csdn.net/qq_32867467/article/details/82944674 官网: https://mp.baomidou.com/guide/optimis ...

  10. Unity3D制作红色射线

    1.在发射射线的位置创建一个空物体用于存储发射点的位置信息. 2.制作射线,为发射射线物体添加LineRenderer组件  制作Material材质并把其类型改为Particles/Addictiv ...