21. 高級路由配置
21.1 自定義路由約束
除了使用默認的路由約束,你還可以創建自定義路由約束。自定義路由約束允許你根據特定的業務邏輯來決定一個路由是否匹配。例如,創建一個只允許特定年份的路由約束:
csharp
public class YearRouteConstraint : IRouteConstraint
{public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection){if (values.TryGetValue(routeKey, out object value)){if (int.TryParse(value.ToString(), out int year)){return year >= 2000 && year <= 2030;}}return false;}
}
然后在路由配置中使用這個自定義約束:
routes.MapRoute(name: "CustomYearRoute",url: "products/{year}",defaults: new { controller = "Product", action = "Index" },constraints: new { year = new YearRouteConstraint() }
);
21.2 區域路由
當應用程序變得復雜時,可以使用區域(Areas)來組織代碼。區域允許你將相關的控制器、視圖和模型分組在一起。創建一個區域的步驟如下:
- 在項目中創建一個?
Areas
?文件夾。 - 在?
Areas
?文件夾下創建一個新的區域文件夾,例如?Admin
。 - 在?
Admin
?文件夾下創建?Controllers
、Views
?和?Models
?文件夾。 - 在?
Admin
?文件夾下創建一個?AdminAreaRegistration.cs
?文件來配置區域路由:
public class AdminAreaRegistration : AreaRegistration
{public override string AreaName{get{return "Admin";}}public override void RegisterArea(AreaRegistrationContext context){context.MapRoute("Admin_default","Admin/{controller}/{action}/{id}",new { action = "Index", id = UrlParameter.Optional });}
}
在?RouteConfig.cs
?中注冊區域:
public class RouteConfig
{public static void RegisterRoutes(RouteCollection routes){routes.IgnoreRoute("{resource}.axd/{*pathInfo}");// 注冊區域AreaRegistration.RegisterAllAreas();routes.MapRoute(name: "Default",url: "{controller}/{action}/{id}",defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });}
}
22. 視圖組件
22.1 視圖組件的概念
視圖組件是一種輕量級的可復用視圖元素,類似于部分視圖,但功能更強大。視圖組件可以包含自己的邏輯和數據訪問代碼,并且可以異步加載。
22.2 創建視圖組件
創建一個視圖組件需要以下步驟:
- 創建一個繼承自?
ViewComponent
?的類,例如:
public class LatestProductsViewComponent : ViewComponent
{private readonly ProductContext _context;public LatestProductsViewComponent(ProductContext context){_context = context;}public async Task<IViewComponentResult> InvokeAsync(){var latestProducts = await _context.Products.OrderByDescending(p => p.CreatedDate).Take(5).ToListAsync();return View(latestProducts);}
}
- 在?
Views/Shared/Components/LatestProducts
?文件夾下創建一個?Default.cshtml
?視圖文件:
@model IEnumerable<YourNamespace.Product><h3>最新產品</h3>
<ul>@foreach (var product in Model){<li>@product.Name</li>}
</ul>
- 在其他視圖中使用視圖組件:
@await Component.InvokeAsync("LatestProducts")
23. 信號量與實時通信
23.1 使用 SignalR 實現實時通信
SignalR 是一個用于在服務器和客戶端之間實現實時通信的庫。可以使用 SignalR 來創建實時聊天、實時通知等功能。
- 安裝?
Microsoft.AspNetCore.SignalR
?包。 - 創建一個繼承自?
Hub
?的類,例如:
public class ChatHub : Hub
{public async Task SendMessage(string user, string message){await Clients.All.SendAsync("ReceiveMessage", user, message);}
}
- 在?
Startup.cs
?中配置 SignalR:
public void ConfigureServices(IServiceCollection services)
{services.AddSignalR();services.AddControllersWithViews();
}public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{// 其他配置...app.UseEndpoints(endpoints =>{endpoints.MapControllerRoute(name: "default",pattern: "{controller=Home}/{action=Index}/{id?}");endpoints.MapHub<ChatHub>("/chatHub");});
}
- 在客戶端使用 JavaScript 連接到 SignalR 服務器:
html
<script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/3.1.1/signalr.min.js"></script>
<script>const connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();connection.on("ReceiveMessage", (user, message) => {const msg = message.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");const encodedMsg = user + " says: " + msg;const li = document.createElement("li");li.textContent = encodedMsg;document.getElementById("messagesList").appendChild(li);});connection.start().catch(err => console.error(err.toString()));document.getElementById("sendButton").addEventListener("click", event => {const user = document.getElementById("userInput").value;const message = document.getElementById("messageInput").value;connection.invoke("SendMessage", user, message).catch(err => console.error(err.toString()));event.preventDefault();});
</script>
24. 日志記錄與監控
24.1 日志記錄
在?ASP.NET?MVC 中,可以使用?Microsoft.Extensions.Logging
?進行日志記錄。在?Startup.cs
?中配置日志記錄:
public void ConfigureServices(IServiceCollection services)
{services.AddLogging(loggingBuilder =>{loggingBuilder.AddConsole();loggingBuilder.AddDebug();});services.AddControllersWithViews();
}
在控制器中使用日志記錄:
private readonly ILogger<ProductController> _logger;public ProductController(ILogger<ProductController> logger)
{_logger = logger;
}public ActionResult Index()
{_logger.LogInformation("訪問產品列表頁面");return View();
}
24.2 監控
可以使用 Application Insights 來監控應用程序的性能和健康狀況。在?Startup.cs
?中配置 Application Insights:
public void ConfigureServices(IServiceCollection services)
{services.AddApplicationInsightsTelemetry(Configuration["APPINSIGHTS_INSTRUMENTATIONKEY"]);services.AddControllersWithViews();
}
Application Insights 可以收集應用程序的請求數據、異常信息、性能指標等,幫助你快速發現和解決問題。
25. 微服務架構與 MVC
25.1 微服務架構概述
微服務架構是一種將應用程序拆分為多個小型、自治服務的架構模式。每個微服務都可以獨立開發、部署和擴展。
25.2 在 MVC 中集成微服務
可以將 MVC 應用程序拆分為多個微服務,每個微服務負責一個特定的業務功能。例如,將產品管理、訂單管理、用戶管理等功能拆分為獨立的微服務。可以使用 RESTful API 來實現微服務之間的通信。
// 產品微服務的控制器
[ApiController]
[Route("api/[controller]")]
public class ProductController : ControllerBase
{private readonly ProductContext _context;public ProductController(ProductContext context){_context = context;}[HttpGet]public async Task<ActionResult<IEnumerable<Product>>> GetProducts(){return await _context.Products.ToListAsync();}
}
在其他微服務中調用產品微服務的 API:
using System.Net.Http;
using System.Threading.Tasks;public class ProductService
{private readonly HttpClient _httpClient;public ProductService(HttpClient httpClient){_httpClient = httpClient;}public async Task<IEnumerable<Product>> GetAllProducts(){var response = await _httpClient.GetAsync("http://product-service/api/product");response.EnsureSuccessStatusCode();return await response.Content.ReadAsAsync<IEnumerable<Product>>();}
}
通過以上這些高級內容的學習,你可以進一步提升自己在?ASP.NET?MVC 開發方面的技能,應對更復雜的業務場景和項目需求。