博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
依赖注入的威力,.NET Core的魅力:解决MVC视图中的中文被html编码的问题
阅读量:6310 次
发布时间:2019-06-22

本文共 2639 字,大约阅读时间需要 8 分钟。

有园友在博问中提了这样一个问题 —— ,到我们的 ASP.NET Core 项目中一看,也是同样的问题。

比如下面的Razor视图代码:

@{    ViewBag.Title = "代码改变世界";}@ViewBag.Title

输出的html代码变成了:

代码改变世界

上面的 @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中实现的,命名空间是  。

写个.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
optionsAccessor, IModelMetadataProvider metadataProvider, IUrlHelperFactory urlHelperFactory, HtmlEncoder htmlEncoder, ClientValidatorCache clientValidatorCache){}

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

码上一行,你就知道。

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

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

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

代码改变世界

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

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

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

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

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

转载于:https://www.cnblogs.com/dudu/p/5879913.html

你可能感兴趣的文章
ssh
查看>>
订单的子单表格设置颜色
查看>>
Office365 Exchange Hybrid 番外篇 ADFS后端SQL群集(一)
查看>>
9个offer,12家公司,35场面试,从微软到谷歌,应届计算机毕业生的2012求职之路...
查看>>
lvs fullnat部署手册(三)rs内核加载toa篇
查看>>
C++策略模式
查看>>
我的友情链接
查看>>
oracle表分区详解
查看>>
网络编程中常见结构体
查看>>
SSL/TLS原理详解
查看>>
Docker 自定义SSH服务镜像
查看>>
JavaScript强化教程 —— Cocos2d-JS自动JSB绑定规则修改
查看>>
configure: error: in `/root/httpd-2.2.11/srclib/apr': c
查看>>
CentOS7搭建Kubernetes-dashboard管理服务
查看>>
buildroot下查找外部编译器通过ext-toolchain-wrapper调用的参数
查看>>
MySQL Replication 主主配置详细说明
查看>>
Linux的任务调度
查看>>
在Android studio中添加jar包方法如下
查看>>
iframe 在ie下面总是弹出新窗口解决方法
查看>>
分享10款漂亮实用的CSS3按钮
查看>>