从ASP.NET 升级到ASP.NET5(RC1) - 翻译

前言

ASP.NET 5 是一次使人惊叹的对于ASP.NET的创新革命. 他将构建目标瞄准了 .NET Core CLR, 同时ASP.NET又是对于云服务进行优化,而且是跨平台的框架.不少文章已经称赞过了新的平台的优势. 可是在这篇文章中,我将展现给你们一个用VisualStudio2013,ASP.NET 4.5,MVC5,Entity Frameworkd 7编写的小型的Demo,而后将其升级到VisualStudio2015,ASP.NET 4.5,MVC5,Entity Frameworkd 7。这个新的网站将能同时运行在.NET 4.6 CLR 和 .NET Core CLR. 上路吧。html

The Random Acts of Kindness home page.
The Random Acts of Kindness home page.前端

版权说明

http://www.codesnippet.info/ 手工翻译了本文,拥有完整的版权。请勿进行未受权的转载。
更好的阅读体验:从ASP.NET 升级到ASP.NET5(RC1)jquery

本网站受权转载git

博客园 www.cnblogs.com
简书 www.jianshu.comgithub

译者注:当前时间点,MVC6 RC2已经Release了。web

The Random Acts 网站

我原创了RandomActs这样的一个网站,本来是为了我在2013年和2014年关于单元测试的一些演讲(talk)。RandomActs是一个架空的用来跟踪别人的善举的网站。这是一种相似于作善事(“do good”译者注:呵呵。。。)的在线社交活动的项目。你使用它来建立Acts (事件), Actors (志愿者), 而后将 actors 和 acts进行配对.全部的数据被保存在一个SQL Server数据库中,一共有3张表格RandomActs, RandomActors, and RandomActActors。shell

RandomActs 作得比通常的仅仅使用框架的Demo要好。 它使用了repository 类(译者注:貌似没有好的中文对应,EF术语) 它的 controllers也涉及到了使用依赖注入(dependency injection )的 repository 类 . 他还使用了 Entity Framework 的延迟加载特性(Lazy Load) 来计算Acts和Actors的数量. 同时他还内置了一个“等待队列”,若是志愿者的数量超过了须要作的善举的数量(译者注:活来不及干,就排队呗)。数据库

尽管下文所要描述的步骤是为了个人程序定制的,可是我相信,这也会和你的程序类似,因此你最好可以按照步骤来升级。显而易见,若是您的项目很复杂,尤为你的解决方案包含了多个项目(Project),使用了不少第三方库(译者注:若是你的第三方库不支持NET Core,好比使用了不少绘图的库,只能呵呵了),你可能须要作更多的工做。不管如何,但愿本文至少可以给你指出一条明道在升级这条都是坑的路上。express

版本和代码库

本文使用的是Beta 8 updated for RC1 ,源代码以下:
The ASP.NET 4.x version of the project can be cloned here: https://github.com/plitwin/RandomActs.git
The ASP.NET 5 (RC1) version can be cloned here: https://github.com/plitwin/RandomActs5.git
大伙看清楚啊,是Beta8!!!
大伙看清楚啊,是Beta8!!!
大伙看清楚啊,是Beta8!!!
(Important Thing Repeat Three Times)json

迁移步骤

事前准备

ASP.NET5的项目结构和以前的ASP.NET项目结构可谓了天壤之别啊。

  • 全部的代码都在src目录底下了。(之前是在Project下面的)
  • 全部的静态文件都放到了wwwroot子文件夹下面去了。
  • web.config 木有了。。取而代之的是一系列的JSON文件,最重要的是 project.json.
  • Global.asax 也木有了。。路由设定( Routing)放在一个新的文件了 startup.cs.
  • startup.cs 也能够依赖注入的(dependency injection ),只是默认不启用罢了。
    这就意味着,你不能舒舒服服的用VS2015打开MVC6工程,而后按下一个诸如叫作“升级”的按钮,泡一杯咖啡和前台小姑娘聊聊天,接受一个天猫快递,打一盘LOL,而后就大功告成了。别作梦了,至少如今尚未这个一个按钮,也不知道之后会不会有。(It doesn't exist. Not at this point,not sure if it ever will.)。你也别期望可以新建一个空的ASP.NET5的工程,而后将你如今的代码拖曳进来,而后就完事了。因为一些根本性的变动,一些必要的升级手段是必须的。

盗图:来自于 Visual Studio 2015 开发 ASP.NET 5 有何变化?

第一步,新建一个工程

新建一个工程,输入解决方案名称,如下省略500字。注意,选择 ”No authentication “,固然若是你愿意,也能够保留标准配置。


这个时候,你最好试试看,能不能编译成功,是否是会有诡异的错误,有没有出来欢迎页面。
(译者注:可能Package展开错误,或者其余错误,按照惯例,从新启动VS,13.8384%的几率能够修复这个问题。修很差就上博客园,百度,雅虎,天猫,京东看看,反正也修很差,不如先血拼一下)

第二步: 复制现有的文件

是时候复制文件了(Time to do something). 因为前文所诉,两个版本之间差距蛮大的,因此请按照下面的步骤作。
新建一个Models文件夹,将原工程的Model文件都放在新工程的Models文件夹中。
复制全部的Controller文件到新的文件夹中。
复制全部View到新的View中
Act
ActActor
Actor
别复制其余的View啊。。。

第三步: 复制导航栏

鉴于ASP.NET 5 对 _Layout.chshtml 文件作了重大修改 (客户端如何或许文件), 请将下面的代码段放到你的_Layout.cshtml 。(在哪?Shared views下面)

  • 修复标题(title),这样就能够明显标识出这是你的网站。将你原来页脚的代码页放到 footer 标签中吧。(译者注:语义化HTML5)
  • 使用新的Tag-Helper系统来新建一个指向Home的连接。(译者注:呵呵,前端工程师看着很开心,和HTML语法好像啊)
<a asp-controller="Home" asp-action="Index" class="navbar-brand">New Project</a>

将 “Home” 改成 “Act”, 将全部 “New Project” 改成 “Random Acts of Kindness”.
接下来修改全部的导航连接吧,固然也是使用高大上的Tag-Helper,最后的完成效果应该以下所示。Great。。
这一步大部分人均可以无障碍理解的吧。。。

<div class="navbar-collapse collapse">
          <ul class="nav navbar-nav">
             <li><a asp-controller="Act" asp-action="Index">Events</a></li>
             <li><a asp-controller="Actor" asp-action="Index">Volunteers</a></li>
             <li><a asp-controller="Act" asp-action="About">About</a></li>
             <li><a asp-controller="Act" asp-action="Contact">Contact</a></li>
         </ul>
      </div>

第四步: Entity Framework 7 登场

打开 project.json添加下面一个配置项目 (这样的话Nuget就会开始下载这两个Package了):

"EntityFramework.Commands": "7.0.0-rc1-final",
    "EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final"

别忘了再添加这个 project.json:

"ef": "EntityFramework.Commands"

别问我有什么用,我不懂EF

第五步:Connection String

appsettings.json: 看清楚了,不是project.json!!!

"ConnectionStrings": {
    "RandomActsDB" :  "Server=.;Database=RandomActs5DB;Trusted_Connection=True;MultipleActiveResultSets=True;"
  }

这里认为你用的是高大上的MSSQL,其余数据库爱好者(MongoDB是最好的数据库),请酌情修改。

第六步:注册EF的Dependency Injection

又是我不懂的EF。。。。

下面的这些加在 startup.cs:

using Microsoft.Data.Entity;
using RandomActs.Models;
Add the following code to the Configure Services method.
var cnx = Configuration.Get<string>("ConnectionStrings:RandomActsDB");
services.AddEntityFramework()
       .AddSqlServer()
       .AddDbContext<RAOKContext>(options => options.UseSqlServer(cnx));

第七步: 全局检索和替换

开始放大招了,全局替换。。。老外胆够肥啊。。。。
要么我也替换”Replace“ 为 ”替换“ 。。。

Replace "System.Data.Entity" with "Microsoft.Data.Entity"
Replace "System.Web.Mvc" with "Microsoft.AspNet.Mvc"
Replace "using System.Web;" with an empty string (effectively deleting all these using statements)
Replace "HttpStatusCode.BadRequest" with "(int) HttpStatusCode.BadRequest"

第八步:修复 Bind 语法

Bind 特性的语法已经简化了(别简化啊。。。).你能够用新的语法来代替 [Bind(Include="item1, item2, item3")], 如今能够这样用了 [Bind("item1","item2","item3")] . 举个栗子。。。。

变身前

public ActionResult Edit([Bind(Include="RandomActId,Title")] RandomAct randomact)

变身后

public ActionResult Edit([Bind("RandomActId","Title")] RandomAct randomact)

友情提示:
编译一下,看到一大推错误信息,你就知道那些地方须要修改了。(做者原文啊)

第九步: 修复 SelectList

任何使用SelectList 方法的Controller,添加引用

using Microsoft.AspNet.Mvc.Rendering;

继续友情提示,看看使人抓狂的ErrorList吧

第十步:修复 Entity Framework Find 方法

在 repository 类中, 替换全部Entity Framework Find 方法为 SingleOrDefault 方法 包括全部lambda expression限制返回件数的地方

举个栗子:

变身前

context.RandomActors.Find(id);

变身后

context.SingleOrDefault(x => x.RandomActorId == id);

第十一步: 修复路由

startup.cs

app.UseMvc(routes =>
{
   routes.MapRoute(
      name: "default",
      template: "{controller=Act}/{action=Index}/{id?}");
}

第十二步: 修复路由 设定Repository类的依赖注入( Dependency Injection )

startup.cs. 添加这些 ConfigureServices 方法去实现依赖注入吧。

services.AddScoped<IRandomActRepository, RandomActRepository>();
services.AddScoped<IRandomActorRepository, RandomActorRepository>();
services.AddScoped<IRandomActActorRepository, RandomActActorRepository>();

每个控制器有两个构造器,第一个如今不须要了,应为上面的依赖注入已经代劳了。那就干掉第一个构造器吧,就是带有this的扩展方法的构造器。

public ActController() : this(new RandomActRepository())
{
}

第十三步:修改Repository 类中对于 DbContext 的引用,来支持Dependency Injection

  1. 将这些在RAOKContext 类中的构造器干掉,在 RAOKContext.cs (你也能够干掉整个构造器)
: base("RandomActsDB")
  1. 这样整个工程如今就不会报错了,世界就清净了。若是还有错误,好好的看一下还有什么漏网之鱼。若是你如今就急不可耐想要运行工程,呵呵,一个运行时所与正在路上。你还木有一个数据库链接呢。这个错误有时候会让你抓狂( head scratching ),直到你灵光乍现( "ah ha" moment)意识到你的repository类须要修改用来支持injected DbContex的接受者。(modified to receive the injected DbContext.)

  2. 继续修改吧,每个Repository类,去掉这行代码
RAOKContext context = new RAOKContext();
  1. 将上面的代码改为这个样子
public RAOKContext context { get; private set; }
        public RandomActActorRepository(RAOKContext raokcontext)
        {
            context = raokcontext;
        }

上面的是RandomActActorRepository的示范. 构造器的名字不要搞错啊。

第十四步: 新建数据库

我起初无心将这步也添加进来的,由于我是经过迁移一个现存的数据库来取代新建的。
回头细想,可能你没有一个数据库,因此你可能须要一些新建数据库的命令。
这些可怜的命令你执行一次就能够了。打开VS 命令提示(command prompt ),切换到Project文件夹,轻轻键入下面的命令,而后就能够了。

dnx ef migrations add CreateRandomActsDB
dnx ef database update

这样的话,数据库的基本雏形就完成了,使用EF的迁移工具,提交更改给SQLServer,而后就么有而后了。
友情提示: ef 将须要第五步的Connection String!!若是发生错误,瞅瞅第五步作对了吗,

第十五步 去掉 jqueryval Script References

一些页面使用到了再也不须要的script bundle,这样会出现运行时错误,将这些代码从页面的最底下删掉就可了。

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

第十六步:修复Lazy Loading

若是你如今屁颠屁颠的开始运行你的代码,一个”ArgumentNullException: Value cannot be null.“错误将会不期而遇。
为何呢?EF7 RC1尚未实现 lazy loading!!!!!(我和个人小伙伴都惊呆了)
若是你使用过以前版本的EF,你应该体验过魔术般的LazyLoading(the magic of lazy loading)隐示的(implicitly )按需求加载须要的数据。可是如今这个版本的EF,它隔屁了。(或许如今已经实现了,EF不懂的路过)
解决方式是,显示的(explicitly)在须要数据以前,就加载他们。
(本人不懂EF,下面这段,大伙看着办吧。不误人子弟了)
The solution is to explicitly enable eager loading whenever related entities will be needed for a given entity. The RandomActs app took advantage of lazy loading for the volunteer dropdown in the ActActorContoller class and for the counts that are displayed on the views of the ActController and the ActorController classes.

从ActController的 Index 方法中将延迟加载换成抢先加载:

变身前

return View(actRepository.All);

变身后

return View(actRepository.AllIncluding(x => x.Actors));

ActorController也如法炮制
变身前

return View(actorRepository.All);

变身后

return View(actorRepository.AllIncluding(x => x.Acts));

ActActorController也是如此. 不过考虑到第十步的SingleOrDefault 问题,请这样修改
变身前

return context.RandomActs.SingleOrDefault(x => x.RandomActId == id);

变身后

return this.AllIncluding(x => x.Actors).SingleOrDefault(x => x.RandomActId == id);

RandomActActorRepository也如法炮制
变身前

return context.RandomActActors.Where(x => x.RandomActId == actId);

变身后

return context.RandomActActors.Where(x => x.RandomActId == actId).Include(x => x.Actor).Include(x => x.Act);

最后是 ActActorController
变身前

return context.RandomActActors.SingleOrDefault(x => x.RandomActActorId == id);

变身后

return context.RandomActActors.Include(x => x.Actor).Include(x => x.Act).SingleOrDefault(x => x.RandomActActorId == id);

可选

RandomActs如今能够无障碍运行了,不过,若是你想更加有ASP.NET5的范,你还能够更加优化代码

继续全局检索替换 "ActionResult" 为 "IActionResult".
将Html helper 方法改成Tag Helper ,若是你闲的蛋疼。
变身前

@Html.TextBoxFor(model => model.Title, new { style = "width: 400px" })

变身后

<input asp-for="Title" style="width: 400px" />

变身前

@using (Html.BeginForm())
 {
 }

变身后

<form asp-controller="Act" asp-action="Edit" method="post">
        </form>

感谢网友的指正
引用dudu的文章 http://www.cnblogs.com/dudu/p/dotnet-core-framework-mono.html

在.NET Core推出以前,.NET Core是参考.NET Framework从新开发的.NET实现,Mono是.NET Framework的一个开源的、跨平台的实现。
若是拿操做系统打个比方,这时,.NET Framework是Unix,.NET Core是Linux,Mono是Mac OS X。
在.NET Core推出以后,.NET Framework与Mono将基于.NET Core从新构建。.NET Framework将成为.NET Core在Windows上的一个发行版,Mono将成为.NET Core的一个跨平台发行版。
再拿操做系统打个比较,那时,.NET Core是Linux,.NET Framework是Ubuntu,Mono是Red Hat。

原文来自于 Migrating an ASP.NET MVC 5 App to ASP.NET 5 (RC1)

ASP.NET从MVC5升级到MVC6 总目录

相关文章
相关标签/搜索