Asp.net Core 入門實戰


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<Startup>()
                .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 library                                     classlib         [C#], F#, VB                                                                                                                                                                                                     Common/Library
Unit Test Project                                 mstest           [C#], F#, VB                                                                                                                                                                                                     Test/MSTest
xUnit Test Project                                xunit            [C#], F#, VB                                                                                                                                                                                                     Test/xUnit
ASP.NET Core Empty                                web              [C#], F#                                                                                                                                                                                                         Web/Empty
ASP.NET Core Web App (Model-View-Controller)      mvc              [C#], F#                                                                                                                                                                                                         Web/MVC
ASP.NET Core Web App                              razor            [C#]                                                                                                                                                                                                             Web/MVC/Razor Pages
ASP.NET Core with Angular                         angular          [C#]                                                                                                                                                                                                             Web/MVC/SPA
ASP.NET Core with React.js                        react            [C#]                                                                                                                                                                                                             Web/MVC/SPA
ASP.NET Core with React.js and Redux              reactredux       [C#]                                                                                                                                                                                                             Web/MVC/SPA
ASP.NET Core Web API                              webapi           [C#], F#                                                                                                                                                                                                         Web/WebAPI
global.json file                                  globaljson                                                                                                                                                                                                                        Config
NuGet Config                                      nugetconfig                                                                                                                                                                                                                       Config
Web Config                                        webconfig                                                                                                                                                                                                                         Config
Solution File                                     sln                                                                                                                                                                                                                               Solution
Razor Page                                        page                                                                                                                                                                                                                              Web/ASP.NET
MVC ViewImports                                   viewimports                                                                                                                                                                                                                       Web/ASP.NET
MVC ViewStart                                     viewstart                                                                                                                                                                                                                         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<Startup>()
                .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 頁面

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
</head>
<body>
    <ul>
        @for (int i = 0; i < 5; i++)
        {
            <li>第@(i + 1)行</li>
        }
    </ul>
</body>
</html>

使用模板

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<Startup>()
                .Build();
            host.Run();
        }
    }

    class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            //啟用Mvc
            services.AddMvc();

            //擴展類
            services.AddSingleton<RazorViewRenderer>();

        }
        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
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
</head>
<body>
    <ul>
        <li>姓名:@Model.Name</li>
        <li>年齡:@Model.Age</li>
    </ul>
</body>
</html>

更改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<IHostingEnvironment>().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);
}
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<Startup>()
                .Build();
            host.Run();
        }
    }

    class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            //啟用路由
            services.AddRouting();
            services.AddMvc();
            services.AddSingleton<RazorViewRenderer>();

        }
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            //啟用狀態碼頁
            app.UseStatusCodePages();

            app.UseRouter(routes =>
            {
                //根路徑 /
                routes.MapGet("", context =>
                {
                    return context.Render("/views/index.cshtml");
                }
            });
        }

    }
}

自定義狀態碼頁

新增 404.cshtml

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
</head>
<body>
    <h1> Oops! Page Not Found ! </h1>
</body>
</html>

配置和使用自定義的狀態碼頁

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<IStatusCodePagesFeature>();
        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<IExceptionHandlerFeature>();
        if (error != null)
        {
            return context.Response.WriteAsync("<h1>" + HtmlEncoder.Default.Encode("發生了錯誤: " + error.Error.Messa + "</h1>");
        }
        else
        {
            return context.Response.WriteAsync("<h1>" + HtmlEncoder.Default.Encode("Oops! 發生了錯誤,請聯系管理員")"</h1>");
        }
    });
});

關於響應

會話

Session

新增登陸頁面login.cshtml

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
</head>
<body>
    <form action="/login" method="post">
        <div>
            <label>用戶名:</label>
            <input  type="text" name="UserName" />
        </div>
        <div>
            <label>密碼:</label>
            <input type="password" name="PassWord" />
        </div>
        <div>
            <input type="submit" value="登陸" />
        </div>
    </form>
</body>
</html>

添加並啟用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<Startup>()
                .Build();
            host.Run();
        }
    }

    class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            //啟用路由
            services.AddRouting();
            services.AddMvc();
            services.AddSingleton<RazorViewRenderer>();
            //增加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<ILogger<Startup>> ();
//記錄日志
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<string, string>() {
                { "name","zhangsan"},
                { "age","18"}
            });
            var config = configBuilder.Build();

            var host = new WebHostBuilder()
                .UseKestrel()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseConfiguration(config)
                .UseStartup<Startup>()
                .Build();
            host.Run();
        }
    }
}

讀取配置

app.UseRouter(routes =>
{
    routes.MapGet("", context =>
    {
        var config = context.RequestServices.GetService<IConfiguration>();
        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<CultureInfo>() {
         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<IStringLocalizer<Startup>>();
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];


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM