ASP.NET Core 入门指南(菜鸡随笔)

发布时间 2023-04-18 21:04:27作者: 白日梦想家_zery

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 应用程序。

步骤如下:

  1. 打开 Visual Studio。
  2. 选择“创建新项目”。
  3. 在“创建新项目”对话框中,选择“ASP.NET Core Web 应用程序”模板。
  4. 输入项目名称和位置,然后单击“创建”按钮。
  5. 在“新建 ASP.NET Core Web 应用程序”对话框中,选择“Web 应用程序”模板。
  6. 选择“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();

该方法用于注册内存缓存服务。

  1. 打开 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">
            &copy; 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、依赖注入、缓存、身份认证和授权等。希望这篇文章对您有所帮助,谢谢!