[译]初识.NET Core & ASP.NET Core
原文:点这
本文的源代码在此:
你过你是.NET Core的入门者,你可以先看看下面这篇文章:
命令行工具
我是在Windows上创建这个应用的,但是你可以在安装了.NET SDK的Mac或者Linux上面做同样的事情.
从http://dot.net这下载.NET SDK. 下载并安装完.NET SDK后开始创建一个新项目于.
步骤如下:
- 创建一个新文件夹
- CD到这个文件夹下
- 在命令行窗口运行
dotnet new
创建一个新项目 - 运行
dotnet restore
下载必要的NuGet包 - 运行
dotnet run
运行你的项目
可以看到我们只需要3步就完成了从创建到运行一个.NET应用的所有工作.
首先使用dotnet new
创建一个项目,此时在项目文件夹下会有一个program.cs
文件它包含一个public Main()
方法, 就像其他的控制台程序一样.
然后你需要使用dotnet restore
来下载项目所需的NuGet包. 空项目自己下载所需要的依赖包.
一旦你从NuGet下载完了所以依赖的包后使用dotnet run
来运行你的项目:
现在你可以打开自动生成的program.cs
文件,修改代码, 如下:
using System;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World. Time is: " +
DateTime.Now.ToString("t"));
}
}
}
回到命令窗口运行dotnet run
你可以看到如下输出.
Hello World. Time is: 5:36 PM
注意当你运行dotnet run
的时候会自动编译你的代码. 这里没有显性的编译步骤 - 当然你可以使用dotnet build
来显性的编译项目.
回顾一下:
- 安装.NET
- 运行3个命令
- 一些可运行的.NET代码
我的可执行程序在哪?
你可能注意到我们没有执行一个EXE文件, 我们只是在包含project.json
的文件夹中执行了dotnet run
, project.json
文件中会告诉我们如何启动应用.
代码被编译放到了bin
目录下的dll
中.
ASP.NET是怎么样的呢?
ASP.NET Core是一个运行了Web server的控制台应用.
下面修改Main函数,让程序变成一个Web应用在浏览器上跑起来:
using System;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Run(async (context) =>
{
await context.Response.WriteAsync(
"Hello World. The Time is: " +
DateTime.Now.ToString("hh:mm:ss tt"));
});
}
}
}
下面需要修改下project.json
添加上Kestrel Web server和Http extensions:
"dependencies": {
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0"
},
"frameworks": { ... }
现在回到命令行运行
dotnet restore
获取依赖包,再运行
dotnet run
现在你应该能看到一个提示,Web服务器在5000端口上启动了. 在浏览器中打开http://localhost:5000,现在你应该可以看到来自于ASP.NET Core的问候了:
Hello World. The Time is: 6/3/2016 2:32:20 PM
可以看到一样的控制台应用结构被用来服务ASP.NET了.
Middleware
Main()
中的代码使用了Kestrel,并对其进行了配置用来处理Web请求. 配置委托给了Startup
类来处理,通常Startup
应该放在一个单独的文件中.
在Startup
类中我们可以使用自定义的中间件来影响ASP.NET管道. Middleware本质上如同经典ASP.NET的HttpHandler
和HttpModule
.
App.Run()
上面的代码中Startup
使用了App.Run()
中间件.
App.Use - Middleware Modules
如果说App.Run()
是个Http handler, 那么App.Use()
就像个HttpModule. App.Use()可以串联起来按照指定的顺序来执行. 修改代码用来在每个请求的前后来执行一定的任务.
在Configure
方法的App.Run()
前添加下面代码:
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Pre Processing");
await next();
await context.Response.WriteAsync("Post Processing");
});
按Ctrl-c
停止服务后运行dotnet run
重新运行程序,结果如下:
Pre Processing...Hello World. The Time is: 6/3/2016 3:10:19 PMPost Processing...
可以看到App.Use()
的输出包裹住了App.Run()
的输出. .
使用ASP.NET MVC
光向上面一样使用App.Use()
和App.Run()
还达不到创建一个正式项目的程序.
当你创建一个Web应用的时候你需要使用更高级的东西比如ASP.NET MVC. 比起自己来实现中间件, ASP.NET MVC提供了丰富的中间件让你及其方便的来创建Web应用. 一旦配置好, 创建一个经典的ASP.NET Core MVC应用和之前你创建ASP.NET MVC应用一样简单.
下面我们在Startup
中加入ASP.NET MVC,并创建一个简单的API用来返回JSON数据.
首先在project.json
中添加下面的包:
"Microsoft.AspNetCore.Mvc": "1.0.0"
运行dotnet restore
来现在依赖包.
修改Startup
类:
using System;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
{
app.UseMvc();
}
}
}
上面的代码在ConfigureServices()
中设置了所需的依赖注入,然后在Configure()
中使用了MVC. 这是一个典型的模式: ConfigureServices()用来初始化依赖注入. Configure() then adjusts the behavior of the middleware which is typically a more specific wrapper around App.Use(). app.AddMvc()
和app.UseMvc()
都是扩展方法,它们来自于Microsoft.AspNetCore.Mvc package.
在这个例子中MVC没用进行一些显性的配置, 但是其他的providers如EntityFrame或者Logging provider需要你配置一些连接字符串之类的.
下面来创建一个controller,代码如下:
public class HelloWorldController
{
[HttpGet("api/helloworld")]
public object HelloWorld()
{
return new
{
message = "Hello World",
time = DateTime.Now
};
}
}
这个controller有一个可以返回匿名对象数据的API端点. 因为是一个API所以它的结果会被序列化 - 通常是一个JSON格式 (依赖于客户端浏览器的accept header).
现在回到命令行运行dotnet run
. 打开http://localhost:5000/api/helloworld.
可以看到下面的结果:
{
message: "Hello World",
time: "2016-06-03T15:39:18.339626-07:00"
}
POCO Controller
注意上面的controller并没有继承Controller
类. ASP.NET Core会知道HelloWorldController
是一个Controller,因为他的后缀是Controller. 除非你需要使用Controller
的一些特性,不然你不需要继承Controller
.
添加Razor视图
接下来在controller中添加另外一个方法来展示Helloworld视图. 首先我们需要添加一些package. project.json添加下面的内容:
"Microsoft.Extensions.Configuration.FileExtensions": "1.0.0"
运行dotnet restore
, 然后在Main()
中使用.UseContentRoot()
用来提供应用的根路径
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseKestrel()
.UseStartup<Startup>()
.Build();
host.Run();
}
UseContentRoot是必须要的!
现在在Helloworld控制器中添加一个方法. 注意在ASP.NET Core MVC中支持在一个controller中同时使用API和MVC端点, 因此在这我不需要另外再创建一个controller:
[HttpGet("helloworld")]
public ActionResult HelloworldMvc()
{
ViewBag.Message = "Hello world!";
ViewBag.Time = DateTime.Now;
return View("helloworld");
//return View("~/helloworld.cshtml");
}
注意了在我们的controller是用来处理API请求的时候,controller没有继承自Controller
. 但在这我们需要让我们的controller继承Controller
,因为在这我们使用了ViewBag
和View
,他们都是Controller
的成员.
让我们的controller继承自Controller
:
public class HelloworldController : Controller
在/Views/Helloworld
文件夹下创建helloworld.cshtml
.
视图的代码非常简单,如下:
<label>Message:</label>
@ViewBag.Message
<hr/>
<label>Time:</label>
@ViewBag.Time
现在你需要在project .json
的buildoption
section中添加如下配置:
"preserveCompilationContext": true
如果你用了动态的视图这个配置是必须的.
现在回到命令行再次运行dotnet run
在浏览器中打开http://localhost:5000/helloworld
可以看到如下页面:
Message: Hello world!
---
Time: 6/3/2016 9:29:12 PM
所有的代码如下:
using System;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseKestrel()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
{
app.UseDeveloperExceptionPage();
app.UseMvc();
//app.Use(async (context, next) =>
//{
// await context.Response.WriteAsync("Pre Processing");
// await next();
// await context.Response.WriteAsync("Post Processing");
//});
// Handler of last Resort
app.Run(async (context) =>
{
await context.Response.WriteAsync(
"Hello World of the last resort. The Time is: " +
DateTime.Now.ToString("hh:mm:ss tt"));
});
}
}
public class HelloWorldController : Controller
{
[HttpGet("api/helloworld")]
public object HelloWorld()
{
return new
{
message = "Hello World",
time = DateTime.Now
};
}
[HttpGet("helloworld")]
public ActionResult HelloworldMvc()
{
ViewBag.Message = "Hello world!";
ViewBag.Time = DateTime.Now;
return View("helloworld");
//return View("~/helloworld.cshtml");
}
}
}
IIS去哪了?
到现在为止我们只是在Windows上运行了一个控制台应用, 没有使用诸如IIS之类的WEB服务器来托管我们的应用. 因为ASP.NET Core使用了一个自托管的WEB服务器(Kestrel它是一个ASP.NET Core的高性能WEB服务器 which ASP.NET Core’s high performance Web Server).
但是,并不推荐在Internet中直接通过Kestrel来访问我们的应用. 你应该使用一个前端的反向代理,例如Windows上的IIS,Linux上面的Nginx.
Running on a Mac
到目前为止我们一直是在Windows机器上来运行程序的, 但上面的代码可以不经任何修改的搬到Mac上运行!
PS: 第一次使用Markdown编辑文章,挺好。