您的位置:首页 > 编程语言 > ASP

.NET跨平台之旅:将示例站点从 ASP.NET 5 RC1 升级至 ASP.NET Core 1.0

2016-03-11 11:39 1141 查看
终于将“.NET跨平台之旅”的示例站点 about.cnblogs.com 从 ASP.NET 5 RC1 升级至 ASP.NET Core 1.0 ,经历了不少周折,在这篇博文中记录一下。

从 ASP.NET 5 到 ASP.NET Core 最大的变化,除了改名之外,就是用 dotnet cli(命令名是dotnet)取代了dnx。所以运行 ASP.NET Core 程序,首先要安装 dotnet cli,我们是在 Ubuntu 服务器上用 apt-get install dotnet 命令安装的。

运行 ASP.NET 5 程序的命令是 dnx restore + dnx web,运行 ASP.NET Core 程序的命令则变为 dotnet restore + dotnet run。dotnet 运行 ASP.NET 程序 与 dnx 有一个很大的不同,除了 project.json 与 Startup.cs 职位,还需要一个 Program.cs 。

用 dnx 运行 ASP.NET 5 程序,需要在 project.json 中配置相应的 command ,比如:

"commands":{
"web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://*:8001" }


而在 ASP.NET Core 中,不再需要这个 command ,而是交由 Program.cs 负责,比如我们这个示例项目中所用的 Program.cs 代码如下:

using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Builder;

namespace CNBlogs.AboutUs.Web
{
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseServer("Microsoft.AspNetCore.Server.Kestrel")
.UseUrls("http://*:8001")
.UseApplicationBasePath(Directory.GetCurrentDirectory())
.UseDefaultConfiguration(args)
.UseIISPlatformHandlerUrl()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
}


从上面的代码可以看出,ASP.NET Core 应用的启动工作是由 WebHostBuilder(源码)起头的,但它不是主角,只是助手,准备一些启动参数,最终把启动工作交给了真正的主角 —— WebHost,如果你对 WebHost 怎么干活的感兴趣,可以看它的 源码

弄好 Program.cs 之后,接下来就是体力活 —— 改名。

EntityFrameworkCore.MicrosoftSqlServer 改为 Microsoft.EntityFrameworkCore.SqlServer

Microsoft.AspNet.Builder 改为 Microsoft.AspNetCore.Builder

Microsoft.Data.Entity 改为 Microsoft.EntityFrameworkCore

Microsoft.AspNet.Mvc 改为 Microsoft.AspNetCore.Mvc

Microsoft.AspNet.Html.Abstractions 改为 Microsoft.AspNetCore.Html

移除 Microsoft.Dnx.Runtime 命名空间

等等

完成“改名”体力活之后,接下来的工作最费周折最累人 —— 配置 project.json , 而且现在的 project.json 不支持注释,调测配置变得更麻烦。

首先要在 project.json 中添加如下 emitEntryPoint 的配置,dnx 时期不加是可以的,现在可不行。

"compilationOptions": {
"emitEntryPoint": true
}


遇到的第一问题是 dotnet restore 时出现 not compatible with DNXCore,Version=v5.0 错误。。。后来通过在 project.json 中添加如下的配置解决了,但至今未能弄明白为什么加上看似这个不相关的配置能解决问题(或者只是表面地解决)。

"tools": {
"dotnet-publish-iis": "1.0.0-*"
}


遇到的第二个问题是 The dependency Ix-Async 1.2.5 does not support framework DNXCore,Version=v5.0 。这个问题与 Entity Framework 有关,只要在 project.json 的 dependencies 中去掉 "Microsoft.EntityFrameworkCore.SqlServer",问题就消失。后来参考 Entity Framework 的源代码,在 project.json 中添加如下的配置才解决问题:

"netstandard1.3": {
"imports": [
"dotnet5.4",
"portable-net452+win81"
]
}


接下来遇到的问题是 ASP.NET Core MVC 路由匹配问题 ,用 dotnet run 将站点运行起来后,访问任何URL都出现404错误。这是一个让人无从下手的问题,因为从 Startup.cs 中的代码看,MVC的配置无任何问题。后来还是怀疑到可能是 project.json 的问题,于是与 dotnet-cli 的示例项目 cli-samples 中的 project.json 进行对比,试了试添加如下的配置,问题竟然奇迹般地解决了(这个配置当时没有去进一步研究)。

{
"compilationOptions": {
"preserveCompilationContext": true
}
}


最后一个问题最让人无语,问题是 访问ASP.NET Core MVC站点出错:Could not load file or assembly 'Microsoft.Win32.Registry' 。不仅我们的项目有这个问题,而且 cli-samples 中的 HelloMvc 项目也有这个问题。问题发生在 Microsoft.AspNetCore.DataProtection 中,而且 DataProtectionServices.cs 中的确引用了 Microsoft.Win32.Registry,但是我们是在 Linux 上运行的,难道 Microsoft.AspNetCore.DataProtection 目前还不支持跨平台?

整个升级进程就在这里卡住了,当我们正准备暂时放弃升级至 ASP.NET Core 1.0 的时候,昨天发现 cli-samples 中的 prject.json 更新了,然后试着运行了一下 HelloMvc 项目,问题竟然神奇地解决了。立马看一下对应的 git commit



原来在 dependecies 中删除了 NETStandard.Library ,在 frameworks 中添加了 netstandardapp1.3 的配置。于是,照着这个修改了我们项目中的 project.json ,问题立马解决,我们的.NET跨平台之旅的示例站点 about.cnblogs.com 也就成功运行了起来,升级总算成功完成了。

分享一下这个示例项目中的三个文件:

project.json:

{
"compilationOptions": {
"preserveCompilationContext": true,
"emitEntryPoint": true
},
"dependencies" : {
"Microsoft.Extensions.Logging.Console": "1.0.0-*",
"Microsoft.AspNetCore.IISPlatformHandler": "1.0.0-*",
"Microsoft.AspNetCore.HttpOverrides": "1.0.0-*",
"Microsoft.AspNetCore.Mvc": "1.0.0-*",
"Microsoft.AspNetCore.StaticFiles": "1.0.0-*",
"Microsoft.AspNetCore.Diagnostics": "1.0.0-*",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0-*",
"System.Runtime.Serialization.Primitives": "4.1.0-*",
"Microsoft.EntityFrameworkCore.SqlServer": "1.0.0-*"
},
"frameworks": {
"netstandardapp1.3": {
"dependencies": {
"NETStandard.Library": "1.0.0-*"
},
"imports": [
"dnxcore50",
"portable-net45+win8"
]
}
},
"tools": { "dotnet-publish-iis": "1.0.0-*" }
}


Startup.cs:

namespace CNBlogs.AboutUs.Web
{
public class Startup
{
public Startup(IApplicationEnvironment appEnv)
{
IConfigurationBuilder builder = new ConfigurationBuilder()
.SetBasePath(appEnv.ApplicationBasePath)
.AddJsonFile("config.json", false);
Configuration = builder.Build();
}

public IConfiguration Configuration { get; set; }

public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(LogLevel.Debug);
app.UseDeveloperExceptionPage();
app.UseMvcWithDefaultRoute();
app.UseStaticFiles();
app.UseRuntimeInfoPage();
}

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();

services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<EfDbContext>(options =>
{
options.UseSqlServer(Configuration["data:ConnectionString"]);
});

services.AddTransient<ITabNavRepository, TabNavRepository>();
services.AddTransient<ITabNavService, TabNavService>();
}
}
}


NuGet.Config:

<configuration>
<packageSources>
<clear />
<add key="AspNetCI" value="https://www.myget.org/F/aspnetcidev/api/v3/index.json" />
<add key="NuGet.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: