Blazor分(Client,或者叫WebAssembly)和Server两种模式,所以在Blazor Client在IE 11浏览器上运行是不可能的,是因为微软对IE 11的支持已经改变为补丁更新了,已经主推新版Edge(基本Chromium).所以本文主要支持IE 11和老版Edge也是要通过插件进行支持的.
*如果使用Blazor,一定要使用.Net 5,在.Net 5对Blazor进行不少优化,性能提高了不少,如果.Net 6出来了,则优先使用.Net 6.从github看.Net 和 asp.net core最近提交的源码还在对Blazor进行大量的改进.
Blazor Server默认模版新建的项目.在IE 11看看效果
因为Blazor项目模版默认在调试开启IIS Express,在Asp.Net Core中IIS Express调试的时候,个人觉得没什么用,主要是在调试的时候笔记本的风扇呼呼的响,所以基本在建好项目之后,都会手动在Properties/launchSettings.json配置中进行删除.
启动项目,在IE 11中,查看运行效果,样式没什么问题(Blazor中使用UI是bootstrap)
在Counter Component(组件,和WebForm时代的控件差不多,可以看看
学习Asp.Net Core Blazor ),Counter组件功能是没法使用的,按钮单击之后,并没有进行计数(这一块是WebSocket进行通信的)
在IE 11中,要像正常使用,还是需要第三方插件进行兼容支持.
引入BlazorPolyfill.Server组件,兼容IE 11
在NuGet管理器中,搜索 BlazorPolyfill.Server ,并进行安装,依赖有点多,安装有点慢.
这里主要是在.Net 5使用,和在.Net Core 3.1的时候不同,是否加载blazor.polyfill.min.js在中间件处理
查看所依赖的库
在安装BlazorPolyfill.Server之后,在项目代码中注册该中间件和使用该中间件.
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<WeatherForecastService>();
services.AddBlazorPolyfill();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
}
app.UseBlazorPolyfill();
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
在_Host.cshtml中
@page "/"
@namespace BlazorServerApp.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>BlazorServerApp</title>
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
<link href="BlazorServerApp.styles.css" rel="stylesheet" />
</head>
<body>
<component type="typeof(App)" render-mode="ServerPrerendered" />
<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for details.
</environment>
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
@*引入支持IE 11的blazor.polyfill.min.js脚本文件,该脚本文件是嵌入BlazorPolyfill.Server.dll的资源中 *@
<script src="_framework/blazor.polyfill.min.js"></script>
<script src="_framework/blazor.server.js"></script>
</body>
</html>
对比在新版Edge和IE 11浏览器中,blazor.polyfill.min.js请求响应大小:
BlazorPolyfill.Server中间件源码
看看BlazorPolyfill.Server目录:
public static IApplicationBuilder UseBlazorPolyfill(
this IApplicationBuilder builder, BlazorPolyfillOptions options)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
if (options is null)
{
throw new ArgumentNullException(nameof(options));
}
if (options.ForceES5Fallback)
{
HttpRequestExtensions.ForceES5FallbackFlag();
}
InitReact(builder);
builder.Use((context, next) =>
{
if (!IsBlazorPolyfillLibCached())
{
CacheBlazorPolyfillLib();
}
return next();
});
builder.MapWhen(ctx =>
ctx.Request.BrowserNeedES5Fallback()
&& ctx.Request.Path.StartsWithSegments("/_framework")
&& ctx.Request.Path.StartsWithSegments("/_framework/blazor.server.js"),
subBuilder =>
{
subBuilder.Run(async (context) =>
{
var fileContent = GetPatchedBlazorServerFile();
await HttpRequestManager.ManageRequest(context, fileContent);
});
});
builder.MapWhen(ctx =>
ctx.Request.Path.StartsWithSegments("/_framework")
&& (
ctx.Request.Path.StartsWithSegments("/_framework/blazor.polyfill.js")
|| ctx.Request.Path.StartsWithSegments("/_framework/blazor.polyfill.min.js")
),
subBuilder =>
{
subBuilder.Run(async (context) =>
{
bool isMinified = context.Request.Path.StartsWithSegments("/_framework/blazor.polyfill.min.js");
var fileContent = GetIE11BlazorPolyfill(context.Request.BrowserNeedES5Fallback(), isMinified);
await HttpRequestManager.ManageRequest(context, fileContent);
});
});
return builder;
}
private static FileContentReference _ie11Polyfill = null;
private static FileContentReference _ie11PolyfillMin = null;
private static FileContentReference _fakeie11Polyfill = null;
private static FileContentReference GetIE11BlazorPolyfill(bool isIE11, bool isMinified)
{
if (!isIE11)
{
if (_fakeie11Polyfill == null)
{
string fakeContent = "var _fakeBlazorPolyfill = { };";
string Etag = EtagGenerator.GenerateEtagFromString(fakeContent);
DateTime buildTime = GetBlazorPolyfillServerBuildDate();
_fakeie11Polyfill = new FileContentReference()
{
Value = fakeContent,
ETag = Etag,
LastModified = buildTime,
ContentLength = System.Text.UTF8Encoding.UTF8.GetByteCount(fakeContent).ToString(CultureInfo.InvariantCulture)
};
}
return _fakeie11Polyfill;
}
else
{
if (isMinified)
{
if (_ie11PolyfillMin == null)
{
var assembly = GetBlazorPolyfillAssembly();
var resources = assembly.GetManifestResourceNames();
var resourceName = resources.Single(str => str.EndsWith("blazor.polyfill.min.js"));
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
string js = reader.ReadToEnd();
string Etag = EtagGenerator.GenerateEtagFromString(js);
DateTime buildTime = GetBlazorPolyfillServerBuildDate();
_ie11PolyfillMin = new FileContentReference()
{
Value = js,
ETag = Etag,
LastModified = buildTime,
ContentLength = System.Text.UTF8Encoding.UTF8.GetByteCount(js).ToString(CultureInfo.InvariantCulture)
};
}
}
return _ie11PolyfillMin;
}
else
{
if (_ie11Polyfill == null)
{
var assembly = GetBlazorPolyfillAssembly();
var resources = assembly.GetManifestResourceNames();
var resourceName = resources.Single(str => str.EndsWith("blazor.polyfill.js"));
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
string js = reader.ReadToEnd();
string Etag = EtagGenerator.GenerateEtagFromString(js);
DateTime buildTime = GetBlazorPolyfillServerBuildDate();
_ie11Polyfill = new FileContentReference()
{
Value = js,
ETag = Etag,
LastModified = buildTime,
ContentLength = System.Text.UTF8Encoding.UTF8.GetByteCount(js).ToString(CultureInfo.InvariantCulture)
};
}
}
return _ie11Polyfill;
}
}
}