【转】依赖注入的威力,.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
相关文章
- ASP.NET WebAPi之断点续传下载(中)
- Hosting ASP.NET Core in IIS without Kestrel
- C# -- HttpWebRequest 和 HttpWebResponse 的使用 C#编写扫雷游戏 使用IIS调试ASP.NET网站程序 WCF入门教程 ASP.Net Core开发(踩坑)指南 ASP.Net Core Razor+AdminLTE 小试牛刀 webservice创建、部署和调用 .net接收post请求并把数据转为字典格式
- 【转】.NET(C#):浅谈程序集清单资源和RESX资源 关于单元测试的思考--Asp.Net Core单元测试最佳实践 封装自己的dapper lambda扩展-设计篇 编写自己的dapper lambda扩展-使用篇 正确理解CAP定理 Quartz.NET的使用(附源码) 整理自己的.net工具库 GC的前世与今生 Visual Studio Package 插件开发之自动生
- C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志
- Word控件Spire.Doc 【页面背景】教程(1) ;C#/VB.NET:在 Word 中插入水印
- Word控件Spire.Doc 【段落处理】教程(二):C#/VB.NET:在 Word 中设置段落缩进
- Word控件Spire.Doc 转换教程(八):如何在 C#、VB.NET 中将 RTF 转换为 HTML
- .Net Core 控制台输出中文乱码
- net location
- 《精通 ASP.NET MVC 3 框架(第三版)》---- 1.2 当今的Web开发
- .Net Core 3.1 EF连接MySql数据库配置
- .net反编译的九款神器(转载)
- 在Mac OS X Yosemite 10.10.3 中搭建第一个 ASP.NET 5 Web 项目