ASP.NET Core 入门指南(菜鸡随笔)
ASP.NET Core 入门指南(菜鸡随笔)
什么是 ASP.NET Core
ASP.NET Core 是一个开源、跨平台的 Web 应用程序框架,可以在 Windows、Linux 和 macOS 上运行。它基于 .NET Core 运行时,具有高性能、可扩展性和安全性等优势。ASP.NET Core 提供了一系列的组件和中间件,使得构建 Web 应用程序变得简单快捷。
本文将介绍如何使用 ASP.NET Core 构建一个简单的 Web 应用程序,包括:
- 创建 ASP.NET Core 应用程序
- 添加 MVC 支持
- 添加 API 支持
- 添加依赖注入支持
- 添加日志记录
- 添加异常处理
- 添加缓存支持
- 添加分布式缓存支持
- 添加授权认证
创建 ASP.NET Core 应用程序
首先,打开 Visual Studio,并创建一个新的 ASP.NET Core Web 应用程序。
步骤如下:
- 打开 Visual Studio。
- 选择“创建新项目”。
- 在“创建新项目”对话框中,选择“ASP.NET Core Web 应用程序”模板。
- 输入项目名称和位置,然后单击“创建”按钮。
- 在“新建 ASP.NET Core Web 应用程序”对话框中,选择“Web 应用程序”模板。
- 选择“API”和“启用 HTTPS”选项,并单击“创建”按钮。
Visual Studio 将自动生成一个基本的 ASP.NET Core 应用程序,包含默认的配置和代码文件。
添加 MVC 支持
现在,我们需要添加 MVC 支持,以便能够构建 Web 页面和处理用户请求。
步骤如下:
打开 Startup.cs 文件。
在 ConfigureServices 方法中,添加以下代码:
services.AddControllersWithViews();
该方法用于注册 MVC 服务。
在 Configure 方法中,添加以下代码:
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
该方法用于启用 MVC 中间件,并定义默认路由。
创建 Controllers 和 Views 文件夹,并添加 HomeController.cs 和 Index.cshtml 文件。
HomeController.cs 文件内容如下:
using Microsoft.AspNetCore.Mvc;
namespace WebApplication.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
}
其中,HomeController 继承了 ASP.NET Core 提供的 Controller 基类,Index 方法返回视图。
Index.cshtml 文件内容如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Home Page</title>
</head>
<body>
<h1>Welcome to ASP.NET Core!</h1>
</body>
</html>
该文件用于呈现网站首页。
现在,运行应用程序,访问 https://localhost:5001/ 即可看到网站首页。
添加 API 支持
除了 MVC,ASP.NET Core 还提供了构建 Web API 的支持。接下来,我们将添加对 Web API 的支持,并创建一个简单的 API 来获取资源数据。
步骤如下:
打开 Startup.cs 文件。
在 ConfigureServices 方法中,添加以下代码:
services.AddHttpClient("api", client =>
{
client.BaseAddress = new Uri("https://api.example.com/");
});
该方法用于注册 HttpClient 服务,并设置 API 的基本地址。
创建 Controllers 文件夹,并添加 ResourceController.cs 文件。
ResourceController.cs 文件内容如下:
using System.Net.Http;
using Microsoft.AspNetCore.Mvc;
namespace WebApplication.Controllers
{
[ApiController]
[Route("[controller]")]
public class ResourceController : ControllerBase
{
private readonly IHttpClientFactory _httpClientFactory;
public ResourceController(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
[HttpGet]
public IActionResult Get()
{
var client = _httpClientFactory.CreateClient("api"); var response = client.GetAsync("resource").Result;if (response.IsSuccessStatusCode)
{
string result = response.Content.ReadAsStringAsync().Result;
return Ok(result);
}
return StatusCode((int)response.StatusCode);
}
}if (response.IsSuccessStatusCode)
{
string result = response.Content.ReadAsStringAsync().Result;
return Ok(result);
}
return StatusCode((int)response.StatusCode);
}
}
其中,ResourceController 继承了 ASP.NET Core 提供的 ControllerBase 基类,IHttpClientFactory 用于创建 HttpClient 实例,在 Get 方法中,我们使用 HttpClient 获取 API 数据,并返回结果。
运行应用程序,访问 https://localhost:5001/resource 即可看到 API 返回的数据。 ## 添加依赖注入支持 ASP.NET Core 提供了内置的依赖注入容器,可以方便地管理组件之间的依赖关系。
接下来,我们将添加依赖注入支持,并在 Controller 中实现依赖注入。 步骤如下:
打开 Startup.cs 文件。
在 ConfigureServices 方法中,添加以下代码:
services.AddControllersWithViews(); services.AddScoped<IResourceService, ResourceService>();
创建 Services 文件夹,并添加 IResourceService.cs 和 ResourceService.cs 文件。
IResourceService.cs 文件内容如下:
namespace WebApplication.Services
{
public interface IResourceService
{
string GetResource();
}
}
其中,IResourceService 接口定义了 GetResource 方法。
ResourceService.cs 文件内容如下:
using System.Net.Http;
namespace WebApplication.Services
{
public class ResourceService : IResourceService
{
private readonly IHttpClientFactory _httpClientFactory;
public ResourceService(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public string GetResource()
{
var client = _httpClientFactory.CreateClient("api");
var response = client.GetAsync("resource").Result;
if (response.IsSuccessStatusCode)
{
return response.Content.ReadAsStringAsync().Result;
}
return null;
}
}
}
其中,ResourceService 实现了 IResourceService 接口,使用 HttpClient 获取 API 数据,并返回结果。
打开 HomeController.cs 文件,修改代码如下:
private readonly IResourceService _resourceService;
public HomeController(IResourceService resourceService)
{
_resourceService = resourceService;
}
public IActionResult Index()
{
ViewBag.Resource = _resourceService.GetResource();
return View();
}
其中,HomeController 使用依赖注入来获取 IResourceService 实例,并在 Index 方法中调用 GetResource 方法。
运行应用程序,访问 https://localhost:5001/ 即可看到网站首页和 API 数据。
添加日志记录
日志记录对于应用程序的健壮性和可维护性非常重要。ASP.NET Core 提供了内置的日志记录机制,可以方便地记录应用程序中发生的事件和异常。接下来,我们将添加日志记录支持,并记录一些事件。
步骤如下:
打开 Startup.cs 文件。
在 ConfigureServices 方法中,添加以下代码:
services.AddLogging();
该方法用于注册日志记录服务。
在 Configure 方法中,添加以下代码:
app.UseExceptionHandler("/Home/Error");
app.UseStatusCodePagesWithRedirects("/Home/Error");
app.UseSerilogRequestLogging();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
其中,UseExceptionHandler、UseStatusCodePagesWithRedirects 和 UseSerilogRequestLogging 用于设置日志记录中间件。
创建 Services 文件夹,并添加 LoggingService.cs 文件。
LoggingService.cs 文件内容如下:
using Microsoft.Extensions.Logging;
namespace WebApplication.Services
{
public class LoggingService : ILoggingService
{
private readonly ILogger<LoggingService> _logger;
public LoggingService(ILogger<LoggingService> logger)
{
_logger = logger;
}
public void LogInformation(string message)
{
_logger.LogInformation(message);
}
public void LogWarning(string message)
{ _logger.LogWarning(message); }
public void LogError(string message)
{
_logger.LogError(message);
}
}
public interface ILoggingService
{
void LogInformation(string message);
void LogWarning(string message);
void LogError(string message);
}
}
其中,LoggingService 实现了 ILoggingService 接口,并使用 ILogger 记录日志信息。
打开 HomeController.cs 文件,修改代码如下:
private readonly IResourceService _resourceService;
private readonly ILoggingService _loggingService;
public HomeController(IResourceService resourceService, ILoggingService loggingService)
{
_resourceService = resourceService;
_loggingService = loggingService;
}
public IActionResult Index()
{
string resource = _resourceService.GetResource();
_loggingService.LogInformation("获取资源成功:" + resource);
ViewBag.Resource = resource;
return View();
}
其中,HomeController 使用依赖注入来获取 ILoggingService 实例,并在 Index 方法中调用 LogInformation 方法记录日志信息。
运行应用程序,在控制台查看日志信息。
添加异常处理
异常处理是应用程序开发中必不可少的部分。ASP.NET Core 提供了内置的异常处理机制,可以捕获和处理应用程序中发生的异常。
接下来,我们将添加异常处理支持,并捕获一些异常。
步骤如下:
打开 Startup.cs 文件。
在 ConfigureServices 方法中,添加以下代码:
services.AddControllersWithViews(options =>
{
options.Filters.Add(new ExceptionHandlingFilter());
});
services.AddSingleton<IExceptionService, ExceptionService>();
其中,AddControllersWithViews 方法用于注册 MVC 服务,并添加 ExceptionHandlingFilter 过滤器,用于处理异常;
AddSingleton 方法用于注册 IExceptionService 单例服务。
创建 Filters 和 Services 文件夹,并添加 ExceptionHandlingFilter.cs 和 ExceptionService.cs 文件。
ExceptionHandlingFilter.cs 文件内容如下:
using System;
using Microsoft.AspNetCore.Mvc.Filters;
using WebApplication.Services;
namespace WebApplication.Filters
{
public class ExceptionHandlingFilter : IExceptionFilter
{
private readonly ILoggingService _loggingService;
private readonly IExceptionService _exceptionService;
public ExceptionHandlingFilter(ILoggingService loggingService, IExceptionService exceptionService)
{
_loggingService = loggingService;
_exceptionService = exceptionService;
}
public void OnException(ExceptionContext context)
{
string errorMessage = _exceptionService.GetErrorMessage(context.Exception);
_loggingService.LogError(errorMessage);
context.ExceptionHandled = true;
context.Result = new RedirectResult("~/Home/Error");
}
}
}
其中,ExceptionHandlingFilter 实现了 IExceptionFilter 接口,使用 ILoggingService 和 IExceptionService 处理异常。
ExceptionService.cs 文件内容如下:
using System;
namespace WebApplication.Services
{
public class ExceptionService : IExceptionService
{
public string GetErrorMessage(Exception ex)
{
return ex.Message;
}
}
public interface IExceptionService
{
string GetErrorMessage(Exception ex);
}
}
其中,ExceptionService 实现了 IExceptionService 接口,GetErrorMessage 方法用于获取异常错误信息。
创建 Views/Shared 文件夹,并添加 Error.cshtml 文件。
Error.cshtml 文件内容如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Error Page</title>
</head>
<body>
<h1>发生错误!</h1>
</body>
</html>
该文件用于呈现错误页面。
运行应用程序,并访问 https://localhost:5001/resource/exception 即可看到捕获的异常信息。
添加缓存支持
缓存是提高应用程序性能的重要手段之一。ASP.NET Core 提供了内置的缓存机制,可以方便地实现数据缓存。
接下来,我们将添加缓存支持,并在 Controller 中使用缓存。
步骤如下:
打开 Startup.cs 文件。
在 ConfigureServices 方法中,添加以下代码:
services.AddMemoryCache();
该方法用于注册内存缓存服务。
- 打开 HomeController.cs 文件,修改 Index 方法如下:
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using System.ComponentModel.Design;
private readonly IResourceService _resourceService;
private readonly ILoggingService _loggingService;
private readonly IMemoryCache _memoryCache;
public HomeController(IResourceService resourceService, ILoggingService loggingService, IMemoryCache memoryCache)
{
_resourceService = resourceService;
_loggingService = loggingService;
_memoryCache = memoryCache;
}
public IActionResult Index()
{
string cachedResource = _memoryCache.Get<string>("resource");
if (cachedResource != null)
{
_loggingService.LogInformation("从缓存中获取资源成功:" + cachedResource);
ViewBag.Resource = cachedResource;
} else
{
string resource = _resourceService.GetResource();
_memoryCache.Set("resource", resource, TimeSpan.FromSeconds(10));
_loggingService.LogInformation("获取资源成功:" + resource);
ViewBag.Resource = resource;
}
return View();
}
其中,HomeController 使用依赖注入来获取 IMemoryCache 实例,并在 Index 方法中使用 MemoryCache 缓存 API 数据。
运行应用程序,在控制台查看日志信息,多次访问网站首页,可以发现第一次访问时会从 API 获取数据并缓存,后续访问会从缓存中获取数据,从而提高了性能。
添加身份认证和授权
身份认证和授权是保证应用程序安全的重要手段。ASP.NET Core 提供了内置的身份认证和授权机制,可以方便地实现用户身份验证和权限控制。接下来,我们将添加身份认证和授权支持,并实现登录和注销功能。
步骤如下:
打开 Startup.cs 文件。
在 ConfigureServices 方法中,添加以下代码:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = "/Account/Login";
options.LogoutPath = "/Account/Logout";
});
services.AddAuthorization(options =>
{
options.AddPolicy("AdminPolicy", policy => policy.RequireRole("admin"));
});
其中,AddAuthentication 方法用于注册身份认证服务,使用 CookieAuthenticationDefaults.AuthenticationScheme 方案;AddCookie 方法用于配置 Cookie 身份验证选项,并指定登录和注销路径;AddAuthorization 方法用于注册授权服务,并添加 "AdminPolicy" 策略,要求用户必须属于 "admin" 角色。
创建 Models 和 Services 文件夹,并添加 User.cs 和 UserService.cs 文件。
User.cs 文件内容如下:
namespace WebApplication.Models
{
public class User
{
public string Username { get; set; }
public string Password { get; set; }
public string Role { get; set; }
}
}
其中,User 类用于表示用户信息。
UserService.cs 文件内容如下:
using System.Collections.Generic;
using System.Linq;
namespace WebApplication.Services
{
public class UserService : IUserService
{
private static List<User> _users = new List<User>
{
new User { Username = "admin", Password = "admin", Role = "admin" },
new User { Username = "user", Password = "user", Role = "user" }
};
public User GetUser(string username)
{
return _users.FirstOrDefault(u => u.Username == username);
}
}
public interface IUserService
{
User GetUser(string username);
}
}
其中,UserService 实现了 IUserService 接口,使用静态数据存储用户信息,并实现 GetUser 方法用于通过用户名查找用户。
创建 Controllers 文件夹,并添加 AccountController.cs 文件。
AccountController.cs 文件内容如下:
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Mvc;
using WebApplication.Models;
using WebApplication.Services;
namespace WebApplication.Controllers
{
public class AccountController : Controller
{
private readonly IUserService _userService;
public AccountController(IUserService userService)
{
_userService = userService;
}
[HttpGet]
public IActionResult Login()
{
return View();
}
[HttpPost]
public IActionResult Login(User user)
{
User validUser = _userService.GetUser(user.Username);
if (validUser != null && validUser.Password == user.Password)
{
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
identity.AddClaim(new Claim(ClaimTypes.Name, validUser.Username));
identity.AddClaim(newClaim(ClaimTypes.Role, validUser.Role)); var principal = new ClaimsPrincipal(identity);
HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
return RedirectToAction("Index", "Home");
}
ModelState.AddModelError("", "用户名或密码错误");
return View(user);
}
[HttpGet]
public IActionResult Logout()
{
HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return RedirectToAction("Index", "Home");
}
}
}
其中,AccountController 用于处理用户登录和注销请求。
Login 方法用于显示登录页面;HttpPost 版本的 Login 方法用于处理登录表单提交并验证用户信息。
如果验证通过,则创建 ClaimsIdentity 对象表示用户身份,并使用 CookieAuthenticationDefaults.AuthenticationScheme 方案和 ClaimsPrincipal 对象创建身份验证 Cookie。
Logout 方法用于注销用户,清除身份验证 Cookie。
打开 HomeController.cs 文件,添加 AuthorizeAttribute 属性,使其要求用户登录才能访问:
[Authorize]
public class HomeController : Controller
{
// 略...
}
在 Views 文件夹中,添加 Account 和 Shared 文件夹,分别添加 Login.cshtml、_Layout.cshtml 和 _ValidationScriptsPartial.cshtml 文件。
Login.cshtml 文件内容如下:
@model WebApplication.Models.User
@{
ViewData["Title"] = "用户登录";
}
<h1>@ViewData["Title"]</h1>
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="All"></div>
<div class="form-group">
<label for="username">用户名</label>
<input asp-for="Username" class="form-control" />
<span asp-validation-for="Username"></span>
</div>
<div class="form-group">
<label for="password">密码</label>
<input asp-for="Password" class="form-control" type="password" />
<span asp-validation-for="Password"></span>
</div>
<button type="submit" class="btn btn-primary">登录</button>
</form>
</div>
</div>
其中,Login.cshtml 文件用于显示登录页面。
_Layout.cshtml 文件内容如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>@ViewData["Title"] - WebApplication</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">WebApplication</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">首页</a>
</li>
</ul>
<partial name="_LoginPartial" />
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© 2021 - WebApplication
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
@RenderSection("Scripts", required: false)
</body>
</html>
其中,_Layout.cshtml 文件用于呈现共享布局。
_ValidationScriptsPartial.cshtml 文件内容如下:
<environment include="Development">
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.js"></script>
</environment>
<environment exclude="Development">
<script src="https://cdn.jsdelivr.net/npm/jquery-validation@1.19.3/dist/jquery.validate.min.js"
asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js" asp-fallback-test="window.jQuery && window.jQuery.validator"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery-validation-unobtrusive@3.2.12/dist/jquery.validate.unobtrusive.min.js" asp-fallback-src="~/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.min.js" asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive">
</script>
</environment>
其中,_ValidationScriptsPartial.cshtml 文件用于呈现客户端验证脚本。
在 Views/Shared 文件夹中,修改 _LoginPartial.cshtml 文件内容为以下代码:
@using Microsoft.AspNetCore.Http.Features.Authentication
@if (User.Identity.IsAuthenticated)
{
<ul class="navbar-nav flex-grow-1">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle text-dark" href="#" data-toggle="dropdown">欢迎 @User.Identity.Name!</a>
<div class="dropdown-menu dropdown-menu-right">
@if (User.IsInRole("admin"))
{
<a class="dropdown-item" asp-area="" asp-controller="Admin" asp-action="Index">管理后台</a>
}
<div class="dropdown-divider"></div>
<form method="post" asp-area="" asp-controller="Account" asp-action="Logout">
<button type="submit" class="dropdown-item">注销</button>
</form>
</div>
</li>
</ul>
}
else
{
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Account" asp-action="Login">登录</a>
</li>
</ul>
}
其中,_LoginPartial.cshtml 文件用于呈现登录状态。如果用户已经登录,则显示欢迎信息和注销按钮;否则显示登录链接。
运行应用程序,在浏览器中访问首页,可以看到此时需要进行身份验证。
点击登录链接,输入正确的用户名和密码后,即可登录成功,页面将显示欢迎信息和注销按钮。
在 HomeController 中添加 [Authorize] 属性之后,重新访问首页,此时将会自动跳转到登录页。
注销操作将会清除身份验证 Cookie,使用户退出登录状态。
至此,我们已经完成了 ASP.NET Core Web 应用程序的创建、数据获取、缓存、身份认证和授权等功能的实现。通过本文的学习,您将掌握如何使用 ASP.NET Core 创建 Web 应用程序,并深入了解 ASP.NET Core 中的一些核心概念和特性,包括路由、MVC、依赖注入、缓存、身份认证和授权等。希望这篇文章对您有所帮助,谢谢!