ASP.NET MVC 入门指南四

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 文件夹下创建 ControllersViewsModels 文件夹。

  • 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>

    最新产品

      @foreach (var product in Model) {
    • @product.Name
    • }
  • 在其他视图中使用视图组件:

    @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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
        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 开发方面的技能,应对更复杂的业务场景和项目需求。

相关推荐
全栈师3 分钟前
C#中分组循环的做法
开发语言·c#
FAREWELL000756 分钟前
C#进阶学习(十六)C#中的迭代器
开发语言·学习·c#·迭代器模式·迭代器
DXM05211 小时前
牟乃夏《ArcGIS Engine地理信息系统开发教程》学习笔记3-地图基本操作与实战案例
开发语言·笔记·学习·arcgis·c#·ae·arcgis engine
csdn_aspnet4 小时前
C# 如何验证磁盘路径,如:D:\\m\aa.txt
c#
CHQIUU6 小时前
跨语言哈希一致性:C# 与 Java 的 MD5 之战?
java·c#·哈希算法
技术拾荒者7 小时前
c#加密证件号的中间部分,改为*号
c#
weixin_423995007 小时前
unity 读取csv
unity·c#
绿龙术士8 小时前
C#核心知识
c#·.net
wkj0018 小时前
java 和 C#操作数据库对比
java·数据库·c#