http://www.codesnippet.info/ 手工翻译了本文,拥有完整的版权。请勿进行未授权的转载。
原文地址 : 从ASP.NET 升级到ASP.NET5(RC1)
本网站授权
简书 www.jianshu.com
博客园 www.cnblogs.com 转载
译者注:当前时间点,MVC6 RC2已经Release了。
ASP.NET 5 是一次令人惊叹的对于ASP.NET的创新革命. 他将构建目标瞄准了 .NET Core CLR(译者:Core是一个.NET framework的精简版本,所以可以快速的在Linux,OSX等平台上借助于MONO实现。), 同时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. 上路吧。
The Random Acts of Kindness home page.
我原创了RandomActs这样的一个网站,原本是为了我在2013年和2014年关于单元测试的一些演讲(talk)。RandomActs是一个架空的用来跟踪别人的善举的网站。这是一种类似于做善事(“do good”译者注:呵呵。。。)的在线社交活动的项目。你使用它来创建Acts (事件), Actors (志愿者), 然后将 actors 和 acts进行配对.所有的数据被保存在一个SQL Server数据库中,一共有3张表格RandomActs, RandomActors, and RandomActActors。
RandomActs 做得比一般的仅仅使用框架的Demo要好。 它使用了repository 类(译者注:貌似没有好的中文对应,EF术语) 它的 controllers也涉及到了使用依赖注入(dependency injection )的 repository 类 . 他还使用了 Entity Framework 的延迟加载特性(Lazy Load) 来计算Acts和Actors的数量. 同时他还内置了一个“等待队列”,如果志愿者的数量超过了需要做的善举的数量(译者注:活来不及干,就排队呗)。
尽管下文所要描述的步骤是为了我的程序定制的,但是我相信,这也会和你的程序相似,所以你最好能够按照步骤来升级。显而易见,如果您的项目很复杂,尤其你的解决方案包含了多个项目(Project),使用了很多第三方库(译者注:如果你的第三方库不支持NET Core,比如使用了很多绘图的库,只能呵呵了),你可能需要做更多的工作。无论如何,希望本文至少能够给你指出一条明道在升级这条都是坑的路上。
本文使用的是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)
ASP.NET5的项目结构和之前的ASP.NET项目结构可谓了天壤之别啊。
盗图:来自于 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下面)
<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>
打开 project.json添加下面一个配置项目 (这样的话Nuget就会开始下载这两个Package了):
"EntityFramework.Commands": "7.0.0-rc1-final",
"EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final"
别忘了再添加这个 project.json:
"ef": "EntityFramework.Commands"
别问我有什么用,我不懂EF
appsettings.json: 看清楚了,不是project.json!!!
"ConnectionStrings": {
"RandomActsDB" : "Server=.;Database=RandomActs5DB;Trusted_Connection=True;MultipleActiveResultSets=True;"
}
这里认为你用的是高大上的MSSQL,其他数据库爱好者(MongoDB是最好的数据库),请酌情修改。
又是我不懂的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(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 方法的Controller,添加引用
using Microsoft.AspNet.Mvc.Rendering;
继续友情提示,看看令人抓狂的ErrorList吧
在 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?}");
}
startup.cs. 添加这些 ConfigureServices 方法去实现依赖注入吧。
services.AddScoped<IRandomActRepository, RandomActRepository>();
services.AddScoped<IRandomActorRepository, RandomActorRepository>();
services.AddScoped<IRandomActActorRepository, RandomActActorRepository>();
每一个控制器有两个构造器,第一个现在不需要了,应为上面的依赖注入已经代劳了。那就干掉第一个构造器吧,就是带有this的扩展方法的构造器。
public ActController() : this(new RandomActRepository())
{
}
: base("RandomActsDB")
这样整个工程现在就不会报错了,世界就清净了。如果还有错误,好好的看一下还有什么漏网之鱼。如果你现在就急不可耐想要运行工程,呵呵,一个运行时所与正在路上。你还木有一个数据库连接呢。这个错误有时候会让你抓狂( head scratching ),直到你灵光乍现( "ah ha" moment)意识到你的repository类需要修改用来支持injected DbContex的接受者。(modified to receive the injected DbContext.)
继续修改吧,每一个Repository类,去掉这行代码
RAOKContext context = new RAOKContext();
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!!如果发生错误,瞅瞅第五步做对了吗,
一些页面使用到了不再需要的script bundle,这样会出现运行时错误,将这些代码从页面的最底下删掉就可了。
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
如果你现在屁颠屁颠的开始运行你的代码,一个”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>
2024 - 快车库 - 我的知识库 重庆启连科技有限公司 渝ICP备16002641号-10
企客连连 表单助手 企服开发 榜单123