ASP.NET Core 2自定义IRouter依赖注入与路由实现咨询
Hey there! Let's break down how to get your custom IRouteCustom set up with dependency injection and complete the implementation in ASP.NET Core 2.x.
1. Dependency Injection Configuration
First, we need to register your custom router and its dependencies in Startup.cs. Here's how to do it:
Step 1: Register Services in ConfigureServices
public void ConfigureServices(IServiceCollection services) { // Register your IUnitOfWork implementation (adjust to match your actual class) services.AddScoped<IUnitOfWork, YourUnitOfWorkImpl>(); // Register your custom RouteCustom, injecting the default MVC route handler, memory cache, and unit of work services.AddSingleton<IRouteCustom>(provider => new RouteCustom( provider.GetRequiredService<MvcRouteHandler>(), provider.GetRequiredService<IMemoryCache>(), provider.GetRequiredService<IUnitOfWork>() ) ); // Standard MVC setup services.AddMvc(); }
Step 2: Replace Default Route in Configure
Next, swap out the default routing system with your custom router in the MVC pipeline:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { // Add your standard middleware (like error pages, static files) here first app.UseMvc(routes => { // Clear any default routes if needed, then add your custom router routes.Routes.Clear(); routes.Routes.Add(app.ApplicationServices.GetRequiredService<IRouteCustom>()); }); }
2. Completing the RouteCustom Implementation
Now let's fill in the missing parts of your RouteCustom class, focusing on the core IRouter methods you need to implement:
public class RouteCustom : IRouteCustom { private readonly IRouter _innerRouter; private readonly IMemoryCache _memoryCache; private readonly IUnitOfWork _unitOfWork; private const string _routeCacheKeyPrefix = "CustomRoute_"; public RouteCustom(IRouter innerRouter, IMemoryCache memoryCache, IUnitOfWork unitOfWork) { _innerRouter = innerRouter ?? throw new ArgumentNullException(nameof(innerRouter)); _memoryCache = memoryCache ?? throw new ArgumentNullException(nameof(memoryCache)); _unitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork)); } public async Task RouteAsync(RouteContext context) { var requestPath = context.HttpContext.Request.Path.Value.TrimStart('/'); // Check cache first for performance if (!_memoryCache.TryGetValue(_routeCacheKeyPrefix + requestPath, out RouteMapping routeMapping)) { // Fetch the route mapping from your database via UnitOfWork routeMapping = await _unitOfWork.RouteMappings.GetByRequestPathAsync(requestPath); if (routeMapping != null) { // Cache the result to avoid repeated database hits (adjust expiry as needed) _memoryCache.Set(_routeCacheKeyPrefix + requestPath, routeMapping, TimeSpan.FromHours(1)); } } // If we found a valid mapping, update the route data to point to the target controller/action if (routeMapping != null) { context.RouteData.Values["controller"] = routeMapping.TargetControllerName; context.RouteData.Values["action"] = routeMapping.TargetActionName; // Add any additional route parameters here if your mappings include them // context.RouteData.Values["id"] = routeMapping.TargetId; } // Pass control to the inner router (the default MVC handler) to process the updated route data await _innerRouter.RouteAsync(context); } public VirtualPathData GetVirtualPath(VirtualPathContext context) { // This method handles reverse routing (e.g., generating URLs with Url.Action) // If you need to map controller/action back to a custom path, implement that logic here // For now, we'll delegate to the inner router to maintain default behavior return _innerRouter.GetVirtualPath(context); } } // Example RouteMapping entity that matches your database schema public class RouteMapping { public string RequestPath { get; set; } public string TargetControllerName { get; set; } public string TargetActionName { get; set; } // Add other properties as needed (e.g., route parameters, tenant IDs) }
3. Important Things to Keep in Mind
- Cache Invalidation: When you update route mappings in the database, make sure to clear the corresponding cache entry to avoid serving stale data. For example, after updating a
RouteMapping, call_memoryCache.Remove(_routeCacheKeyPrefix + updatedMapping.RequestPath). - Fallback Behavior: If no matching route is found in the database, the inner router will fall back to standard MVC routing rules, so your existing controllers/actions will still work as expected.
- Error Handling: Wrap your database calls in try/catch blocks to handle potential connection issues gracefully, preventing routing failures from crashing the app.
- Route Order: Ensure your custom router is added to the
routes.Routescollection before any other routes if you want it to take priority. If you need to mix custom and standard routes, adjust the order accordingly.
内容的提问来源于stack exchange,提问作者John Mathison
相关产品推荐
相关产品推荐

