1. 首页
  2. 文章列表
  3. 解决ASP.NET Core MVC的Razor视图渲染中文乱码的问题

同样也是在迁移.NET Framework项目到.NET Core时踩的一个坑,在我以为已经迁移完成的时候,在浏览器里偶然按下Ctrl+U时发现,我的中文呢,怎么全是Unicode编码,然后导致的问题就是弹出的模态框,也是Unicode编码的中文字;

懒得勤快的博客_互联网分享精神

然后,Fuck,怎么回事,又陷入了沉思

懒得勤快的博客_互联网分享精神

于是又新开一个项目来研究这到底是为什么?

我新建了一个最简单的razor视图

@{
    string str = "懒得勤快的博客";
}
欢迎来到 @str

程序跑起来之后,浏览器看到确实没什么问题

懒得勤快的博客_互联网分享精神

但是Ctrl+U,乍一看,变量部分变成了Unicode编码,这肯定不是我想要的样子啊!

懒得勤快的博客_互联网分享精神

怎么办?又去微软网站扒文档,发现.NET Core的@符相当于下面这样的代码:

@Html.Raw(Html.Encode(str))

这就好理解了,中文确实是被Unicode编码了,但是,我要挨着去把每处用@符渲染的文本都改成@Html.Raw(str)这样写么?那我不得疯掉?!

这肯定是有解决办法的,于是,我想到了反编译,把Html.Encode通过Resharper反编译后,发现其核心代码简化之后是这样的:

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

它其实是调用了接口类IHtmlGenerator的Encode方法, 但是,这好像没什么用?继续反编译,发现这玩意儿好像不是MVC里面的,因为命名空间在System.Text.Encodings.Web下,为了确保是不是它的锅,我写了个简单的控制台程序来验证:

public class Program
{
    public static void Main(string[] args)
    {            
        string s=HtmlEncoder.Default.Encode("懒得勤快");
        Console.WriteLine(s);
    }
}

输出结果:

懒得勤快的博客_互联网分享精神

看来确实是它的锅;而且在HtmlEncoder点的时候,除了Default,Resharper还给我建议了两个Create方法,那看看Create是什么效果吧;

在点Create方法的时候,需要传入参数,它需要一个UnicodeRange类型的参数,那我输入UnicodeRange然后智能提示一下,Resharper给了我一堆的参数;

懒得勤快的博客_互联网分享精神

我看到了有个All,那就用它吧!

于是,代码改成了这样:

public class Program
{
    public static void Main(string[] args)
    {            
        string s=HtmlEncoder.Create(UnicodeRanges.All).Encode("懒得勤快");
        Console.WriteLine(s);
    }
}

跑起来一看,这个没问题!

懒得勤快的博客_互联网分享精神

然后想想怎么让razor用HtmlEncoder.Create(UnicodeRanges.All)去渲染文本,先研究下HtmlEncoder.Default是怎么被创建的,继续反编译,发现HtmlEncoder.Default的创建是这样的:

懒得勤快的博客_互联网分享精神

原来字符集用的是BasicLatin,难怪中文显示乱码,背你妈的时,为什么不用UnicodeRanges.All???为了节省几个字节的内存么?!

既然找到问题了,那离解决问题又进了一步,怎么替换掉HtmlEncoder.Default,让MVC去调HtmlEncoder.Create(UnicodeRanges.All)?

回到最初的反编译结果,去反编译看 MVC HtmlGenerator的源码;

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

这是一种很熟悉的写法!肯定是依赖注入来的!是不是我重新注入一个HtmlEncoder实例,覆盖掉原来的,就可以了?那我先试试看吧,在Startup.cs里面加了一行:

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

重新把代码跑起来,奇迹的发现,问题解决了!

懒得勤快的博客_互联网分享精神

顺便也找到了网上更好地解决方案:

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

这问题肯定不是我一个人遇到

分享到:

速鹰666高速全隧道机场,每日签到免费领流量 [推广]

速鹰666高速全隧道机场,每日签到免费领流量

真正大鸡场,100多个节点,V2ray节点50多个。港台美日新均有白嫖节点,每日签到送1-7G流量。多条BGP中转/Azure/Dmit/HKT/Hinet/多点IPLC/保证高端用户使用需求。

相关推荐:

Autofac在.NET Core中的属性注入 浅谈http断点续传的原理以及.NET代码实现,看似挺高端,其实很简单
深入浅出依赖注入容器——Autofac .NET Office组件神器——Aspose.Total 20.6学习版下载
博主开源项目——基于EntityFrameworkCore和Lucene.NET实现的全文搜索引擎库 零度分享.NET Core2.2微服务入门实战教程
奉献两套Asp.Net Core最新视频教程 博主开源项目——本站博客项目MyBlogs.Core,基于.NET Core 3.1
一些小众冷门但却非常实用的.NET(Core)开源库推荐 ASP.NET Core MVC/WebAPI中另辟蹊径的全局统一异常处理方式

版权声明:

🈲⚠本文为作者原创,仅用于本站访客学习、研究和交流目的,未经授权禁止转载。️⚠🈲

评论区: