Asp.net Core 2.0 快速入门

2018-02-03 10:19:20来源:oschina作者:得_法人点击

分享
Asp.Net Core 是开源,跨平台,模块化,快速而简单的Web框架.

Asp.net Core官网的一个源码合集,方便一次性Clone



目录
快速入门
安装
一个最小的应用
项目模板
路由
静态文件
页面渲染
请求
错误和重定向
关于响应
会话
日志
配置
国际化

持续更新,也可以通过我的网站访问,欢迎探讨交流


快速入门
安装

下载安装 .NET SDK


查看dotnet sdk 版本


$ dotnet --version`
2.1.4

创建项目目录


$ mkdir study
$ cd study

使用 dotnet new 命令创建项目


$ dotnet new console -n Demo
$ cd Demo

在 VS Code中打开Demo文件夹


一个最小的应用

打开 Program.cs


using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
namespace Demo
{
class Program
{
static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseStartup()
.Build();
host.Run();
}
}class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Hello, World!");
});
}
}
}

安装相关的Nuget包


$ dotnet add package Microsoft.AspNetCore.Hosting --version 2.0.1
$ dotnet add package Microsoft.AspNetCore.Server.Kestrel --version 2.0.1

下载依赖项


$ dotnet restore

运行


$ dotnet run

输出结果:


Hosting environment: Production
Content root path: C:/netcore/study/Demo/bin/Debug/netcoreapp2.0/
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.
项目模板

根据指定的模板,创建新的项目、配置文件或解决方案。


$ dotnet new -h
使用情况: new [选项]
选项:
-h, --help 显示有关此命令的帮助。
-l, --list 列出包含指定名称的模板。如果未指定名称,请列出所有模板。
-n, --name 正在创建输出的名称。如果未指定任何名称,将使用当前目录的名称。
-o, --output 要放置生成的输出的位置。
-i, --install安装源或模板包。
-u, --uninstall 卸载一个源或模板包。
--type基于可用的类型筛选模板。预定义的值为 "project"、"item" 或 "other"。
--force强制生成内容,即使该内容会更改现有文件。
-lang, --language 指定要创建的模板的语言。
模板短名称语言标记
--------------------------------------------------------------------------------------------------------
Console Application console [C#], F#, VB Common/Console
Class libraryclasslib[C#], F#, VB Common/Library
Unit Test Project mstest[C#], F#, VB Test/MSTest
xUnit Test Projectxunit [C#], F#, VB Test/xUnit
ASP.NET Core Emptyweb[C#], F# Web/Empty
ASP.NET Core Web App (Model-View-Controller)mvc[C#], F# Web/MVC
ASP.NET Core Web Apprazor [C#]Web/MVC/Razor Pages
ASP.NET Core with Angularangular [C#]Web/MVC/SPA
ASP.NET Core with React.js react [C#]Web/MVC/SPA
ASP.NET Core with React.js and Reduxreactredux[C#]Web/MVC/SPA
ASP.NET Core Web APIwebapi[C#], F# Web/WebAPI
global.json fileglobaljsonConfig
NuGet Config nugetconfig Config
Web Config webconfig Config
Solution FileslnSolution
Razor Page page Web/ASP.NET
MVC ViewImportsviewimports Web/ASP.NET
MVC ViewStartviewstart Web/ASP.NET
Examples:
dotnet new mvc --auth Individual
dotnet new page --namespace
dotnet new --help

使用dotnet new 选择 console 模板 创建项目


$ dotnet new console -n Demo
$ cd Demo

创建后的项目文档结构是


.
├── Demo
│ ├── Demo.csproj
│ └── Program.cs
路由
启用,配置路由
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
namespace Demo {
class Startup {
public void ConfigureServices (IServiceCollection services) {
//启用路由
services.AddRouting ();
}
public void Configure (IApplicationBuilder app) {
//配置路由
app.UseRouter (routes => {
//根路由 (/)
routes.MapGet("", context =>
{
return context.Response.WriteAsync("Hello, World!");
});
//在根路由 (/) 上,配置 /hello Get请求的路由
routes.MapGet ("hello", context => {
return context.Response.WriteAsync ("Got a Get request at /hello");
});
});
}
}
}

安装相关的Nuget包


$ dotnet add package Microsoft.AspNetCore.Routing --version 2.0.1

下载依赖项


$ dotnet restore

运行


$ dotnet run

访问 http://localhost:5000/hello ,输出结果:


Got a Get request at /hello

对 /user 路由的 POST 请求进行响应:


routes.MapPost("hello", context => {
return context.Response.WriteAsync ("Got a Post request at /hello");
})

对 /user 路由的 PUT 请求进行响应:


routes.MapPut("hello", context => {
return context.Response.WriteAsync ("Got a Put request at /hello");
})

对 /user 路由的 DELETE 请求进行响应:


routes.MapDelete("hello", context => {
return context.Response.WriteAsync ("Got a Dlete request at /hello");
})
静态文件
启用,配置静态资源

创建 wwwroot文件夹


$ mkdir wwwroot
$ cd wwwroot

复制 index.html 到 wwwroot目录


$ mkdir images
$ cd images

复制 favicon.png 到 images文件夹下


项目结构图如下:
.
├── Demo
│ ├── wwwroot
│ │ ├── images
│ │ │ ├── favicon.png
│ │ ├── index.html
│ ├── Demo.csproj
│ └── Program.cs

更改 Program.cs,设置ContentRoot路径为当前项目根目录,启用静态资源


using System;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
namespace Demo {
class Program {
static void Main (string[] args) {
Console.WriteLine (AppContext.BaseDirectory);
var host = new WebHostBuilder ()
.UseKestrel ()
//设置 ContentRoot, ContentRoot是任何资源的根路径,比如页面和静态资源
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup()
.Build ();
host.Run ();
}
}
class Startup {
public void Configure (IApplicationBuilder app) {
//使用静态资源,默认的目录是 /wwwroot
app.UseStaticFiles ();
}
}
}

运行


http://localhost:5000/index.html


http://localhost:5000/images/favicon.png


配置其他文件夹

新建文件夹myfiles


$ mkdir myfiles
$ cd myfiles

创建一个新的 index.html到myfiles文件夹,配置并使用myfiles文件夹


app.UseStaticFiles (new StaticFileOptions {
FileProvider = new PhysicalFileProvider (
Path.Combine (Directory.GetCurrentDirectory (), "myfiles")),
RequestPath = "/myfiles"
});

运行


http://localhost:5000/myfiles/index.html


页面渲染
Razor模板引擎

Asp.net Core自带的模板引擎是 Razor模板引擎,传统的Razor页面以cshtml结尾, 阅读Razor语法
遗憾的是Razor模板引擎在Asp.net Core中封装在了MVC模块之中,需要做一些扩展才可以单独拿出来使用


创建模板页面

创建 views文件夹


$ mkdir views
$ cd views

创建 index.cshtml 页面









    @for (int i = 0; i < 5; i++)
    {
  • 第@(i + 1)行

  • }



使用模板
using System;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
namespace Demo
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(AppContext.BaseDirectory);
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup()
.Build();
host.Run();
}
}
class Startup
{
public void ConfigureServices(IServiceCollection services)
{
//启用Mvc
services.AddMvc();
//扩展类
services.AddSingleton();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouter(routes =>
{
//根路径 /
routes.MapGet("", context =>
{
return context.Render("/views/index.cshtml");
}
});
}
}
}

安装相关的Nuget包


$ dotnet add package Microsoft.AspNetCore.Mvc --version 2.0.2

下载依赖项


$ dotnet restore

运行


$ dotnet run

结果


第1行
第2行
第3行
第4行
第5行
渲染数据

新增实体类 UserInfo


public class UserInfo
{
public string Name { get; set; }
public int Age { get; set; }
}

新增user.cshtml页面


@using Demo;
@model UserInfo







  • 姓名:@Model.Name

  • 年龄:@Model.Age




更改Program.cs


app.UseRouter(routes =>
{
//根路径 /
routes.MapGet("", context =>
{
return context.Render("/views/index.cshtml");
}
routes.MapGet("/user", context =>
{
return context.Render("/views/user.cshtml", new UserInfo() { Name = "张三", Age = 18 });
});
});

运行


$ dotnet run

结果


姓名:张三
年龄:18
请求数据
QueryString
var queryCollection = context.Request.Query;
foreach (var item in queryCollection)
{
Console.WriteLine(item.Key + ":" + item.Value);
}
Form
if (context.Request.ContentType.ToLower().Contains("application/x-www-form-urlencoded")
{
var formCollection = context.Request.Form;
foreach (var item in formCollection)
{
Console.WriteLine(item.Key + ":" + item.Value);
}
}
Files
var fileCollections = context.Request.Form.Files;
var rootPath = context.RequestServices.GetService().ContentRootPath;
foreach (var item in fileCollections)
{var path = Path.Combine(rootPath,item.FileNa
using (var stream = new FileStream(path, FileMode.Create))
{
await item.CopyToAsync(stream);
}
Console.WriteLine(item.FileName + ":" + item.Length);
}
Header
var headerCollection = context.Request.Headers;
foreach (var item in headerCollection)
{
Console.WriteLine(item.Key + ":" + item.Value);
}
Body
StreamReader reader = new StreamReader(context.Request.Body);
string text = reader.ReadToEnd();
Cookies
var cookieCollection=context.Request.Cookies;
foreach (var item in cookieCollection)
{
Console.WriteLine(item.Key + ":" + item.Value);
}
错误和重定向
重定向
context.Response.Redirect("path")
状态代码页
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.IO;
using System.Text.Encodings.Web;
namespace Demo
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(AppContext.BaseDirectory);
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup()
.Build();
host.Run();
}
}
class Startup
{
public void ConfigureServices(IServiceCollection services)
{
//启用路由
services.AddRouting();
services.AddMvc();
services.AddSingleton();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//启用状态码页
app.UseStatusCodePages();
app.UseRouter(routes =>
{
//根路径 /
routes.MapGet("", context =>
{
return context.Render("/views/index.cshtml");
}
});
}
}
}
自定义状态码页

新增 404.cshtml








Oops! Page Not Found !




配置和使用自定义的状态码页


app.UseStatusCodePagesWithRedirects("/status/{0}");
app.UseRouter(routes =>
{
//""
routes.MapGet("", context =>
{
return context.Response.WriteAsync("root path");
});
routes.MapGet("status/{code}", (request, response, routeData) =>
{
var statusCodePagesFeature = request.HttpContext.Features.Get();
var code = routeData.Values["code"];
if (statusCodePagesFeature != null && code!=null && code.ToString() == "404")
{
//跳转到自定义的404页面
return request.HttpContext.Render("/views/404.cshtml");
}
else
{
return response.WriteAsync(HtmlEncoder.Default.Encode("状态码:"+ routeData.Values["code"]));
}
});
});
异常错误页

开发异常页面,Asp.net Core自带


app.UseDeveloperExceptionPage();

新增测试路由,抛出空指针异常


env.EnvironmentName = EnvironmentName.Development;
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/error");
}
app.UseRouter(routes =>
{
//""
routes.MapGet("", context =>
{
return context.Response.WriteAsync("root path");
}
//test
routes.MapGet("test", context =>
{
throw new Exception("空指针异常!!!");
});
});

访问http://localhost:57393/test,得到下面的页面
nullexception


自定义异常页面
env.EnvironmentName = EnvironmentName.Production;
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
//自定义异常错误页面
app.UseExceptionHandler("/error");
}
app.UseRouter(routes =>
{
//""
routes.MapGet("", context =>
{
return context.Response.WriteAsync("root path");
}
//test
routes.MapGet("test", context =>
{
throw new Exception("空指针异常!!!");
});//自定义异常错误页面
routes.MapGet("error", context =>
{
context.Response.StatusCode = 500;
context.Response.ContentType = "text/html";
var error = context.Features.Get();
if (error != null)
{
return context.Response.WriteAsync("

" + HtmlEncoder.Default.Encode("发生了错误: " + error.Error.Messa + "

");
}
else
{
return context.Response.WriteAsync("

" + HtmlEncoder.Default.Encode("Oops! 发生了错误,请联系管理员")"

");
}
});
});
关于响应
会话
Session

新增登陆页面login.cshtml























添加并启用Session,输入用户名和密码,点击登陆,保持Session数据,登陆成功跳转到/home路由页面,访问Session数据,显示当前登陆的用户名


using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.IO;
using System.Threading.Tasks;
namespace Demo
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(AppContext.BaseDirectory);
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup()
.Build();
host.Run();
}
}
class Startup
{
public void ConfigureServices(IServiceCollection services)
{
//启用路由
services.AddRouting();
services.AddMvc();
services.AddSingleton();
//增加Session
services.AddSession();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseDeveloperExceptionPage();
// 启用Session
app.UseSession();
app.UseRouter(routes =>
{
routes.MapGet("", (request, response, routeData) =>
{
return request.HttpContext.Render("/views/login.cshtml");
});
routes.MapGet("home", context =>
{
string userName = context.Session.GetString("userName");
if (!string.IsNullOrEmpty(userName))
{
return context.Response.WriteAsync("User:" + userName);
}
else
{
context.Response.Redirect("/");
return Task.CompletedTask;
}
});
routes.MapPost("login", context =>
{
var userName = context.Request.Form["UserName"].ToString();
var password = context.Request.Form["PassWord"].ToString();
if (userName.Equals("admin") && password.Equals("123456"))
{
context.Session.SetString("userName", password);
context.Response.Redirect("/home");
return Task.CompletedTask;
}
else
{
throw new Exception("用户名或密码错误");
}
}); });
}
}
}
日志
安装Nuget包
$ dotnet add package Microsoft.Extensions.Logging --version 2.0.0
$ dotnet add package Microsoft.Extensions.Logging.Console --version 2.0.0

下载依赖项


$ dotnet restore
添加日志模块
//启用日志
services.AddLogging(builder=> {
//使用控制台日志提供程序
builder.AddConsole();
});
创建ILogger实例
var logger = context.RequestServices.GetService> ();
//记录日志
logger.LogInformation("before hello world");
日志分类

日志的类别,可以是任意字符串,默认是完全限定的类名,例如: Demo.Startup


日志级别
logger.LogTrace();
logger.LogDebug();
logger.LogInformation();
logger.LogWarning();
logger.LogError();
logger.LogCritical();
日志过滤

给日志分类为 Demo.Startup的日志类别限定最小的日志级别是LogLevel.Information


services.AddLogging(builder=> {
builder.AddFilter("Demo.Startup", LogLevel.Information);
builder.AddConsole();
});

访问更多关于日志类别,级别,模板,过滤,作用域的说明日志类别


配置
添加配置
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace Demo
{
class Program
{
static void Main(string[] args)
{
var configBuilder = new ConfigurationBuilder();
configBuilder.AddInMemoryCollection(new Dictionary() {
{ "name","zhangsan"},
{ "age","18"}
});
var config = configBuilder.Build();
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseConfiguration(config)
.UseStartup()
.Build();
host.Run();
}
}
}
读取配置
app.UseRouter(routes =>
{
routes.MapGet("", context =>
{
var config = context.RequestServices.GetService();
string name = config["name"];
string age = config["age"];
return context.Response.WriteAsync("name:"+name+",Age:"+age);
});
});
国际化
添加依赖的Nuget包
$ dotnet add package Microsoft.Extensions.Localization --version 2.0.1

下载依赖项


$ dotnet restore
资源文件命名规则

命名规则 {分类名称}.{语言区域名称}.resx


分类名称:默认的分类名称就是类型的FullName,在AssemblyName后的相对路径,比如Demo.Startup,程序集的名称Demo,就剩下了Startup
语言区域名称: 语言区域名称有zh-CN,en-US,更多

特殊条件下你也可以将资源文件和类定义文件放在同一个目录,这样资源文件的分类名称就是**{类名称}.{语言区域名称}.resx**


添加资源文件
新建 myresources文件夹
新建 Startup.en-US.resx 新增项 name是sayhi,value是 HelloWorld
新建 Startup.zh-CN.resx 新增项 name是sayhi,value是 世界你好
添加本地化
services.AddLocalization(options =>
options.ResourcesPath = "myresources";
});
启用本地化
var cultureList = new List() {
new CultureInfo("en-US"),
new CultureInfo("zh-CN")
};
var options = new RequestLocalizationOptions()
{
SupportedCultures = cultureList,
SupportedUICultures = cultureList,
DefaultRequestCulture = new RequestCulture("zh-CN")
};
//新建基于Query String的多语言提供程序
var provider = new QueryStringRequestCultureProvider();
provider.QueryStringKey = "culture";
provider.UIQueryStringKey = "uiculture";
//删除所有多语言提供程序
options.RequestCultureProviders.Clear();
options.RequestCultureProviders.Add(provider);
资源文件读取
var stringLocalizer = context.RequestServices.GetService>();
string sayhi = stringLocalizer["sayhi"];

访问 http://localhost:57393/?culture=en-US 切换为英文版本,默认的语言是中文


多语言提供程序
通过Query String,[默认自带]
通过Cookie,[默认自带]
通过Accept-Language header,[默认自带]
通过RouteData
模板格式化
string username="张三";
string localizedString = _localizer["Hello {0}!", username];

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台