C# 在IRouter实现ASP.NET核心MVC上获得404
我正在尝试实现我自己的动态路由器,我的计划是从我的数据库中提取路由并创建一组动态登录页,我的问题是,在设置context.routedData到我的新路由数据后,我得到了404 我只想在每次找到路由时重定向到我的LandingPageController和索引IActionResultC# 在IRouter实现ASP.NET核心MVC上获得404,c#,asp.net-core,asp.net-mvc-routing,asp.net-core-mvc,C#,Asp.net Core,Asp.net Mvc Routing,Asp.net Core Mvc,我正在尝试实现我自己的动态路由器,我的计划是从我的数据库中提取路由并创建一组动态登录页,我的问题是,在设置context.routedData到我的新路由数据后,我得到了404 我只想在每次找到路由时重定向到我的LandingPageController和索引IActionResult using System.Threading.Tasks; using Microsoft.AspNetCore.Routing; using System.Collections.Generic; using
using System.Threading.Tasks;
using Microsoft.AspNetCore.Routing;
using System.Collections.Generic;
using System.Linq;
namespace Myproject.Web.Main.Config
{
public class LandingPageRouter : IRouter
{
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
return null;
}
public Task RouteAsync(RouteContext context)
{
var requestPath = context.HttpContext.Request.Path.Value;
if (!string.IsNullOrEmpty(requestPath) && requestPath[0] == '/')
{
requestPath = requestPath.Substring(1);
}
var pagefound = GetPages().Any(x => x == requestPath);
if (pagefound)
{
//TODO: Handle querystrings
var routeData = new RouteData();
routeData.Values["controller"] = "LandingPage";
routeData.Values["action"] = "Index";
context.RouteData = routeData;
}
return Task.FromResult(0);
}
private IEnumerable<string> GetPages()
{
//TODO: pull from database
return new List<string> { "page-url-title", "another-dynamic-url" };
}
}
}
使用System.Threading.Tasks;
使用Microsoft.AspNetCore.Routing;
使用System.Collections.Generic;
使用System.Linq;
命名空间Myproject.Web.Main.Config
{
公共类着陆页面路由器:IRouter
{
公共VirtualPathData GetVirtualPath(VirtualPathContext上下文)
{
返回null;
}
公共任务RouteSync(RouteContext上下文)
{
var requestPath=context.HttpContext.Request.Path.Value;
如果(!string.IsNullOrEmpty(requestPath)&&requestPath[0]=='/'))
{
requestPath=requestPath.Substring(1);
}
var pagefound=GetPages().Any(x=>x==requestPath);
如果(找到页面)
{
//TODO:处理查询字符串
var routeData=新routeData();
路由数据值[“控制器”]=“着陆页面”;
路由数据值[“操作”]=“索引”;
context.RouteData=RouteData;
}
返回Task.FromResult(0);
}
私有IEnumerable GetPages()
{
//TODO:从数据库中提取
返回新列表{“页面url标题”,“另一个动态url”};
}
}
}
我看了这个,但它似乎过时了,上下文中的一些属性在RC2中甚至不存在了
我遗漏了什么?这似乎不是最好的解决方案,但从我的测试来看,它应该可以满足您的需求
我将默认的MVC
IRouter
注入您的LandingPageRouter
。然后,更新路由数据后,只需调用默认路由器并在上下文中传递:
public class LandingPageRouter : IRouter
{
private readonly IRouter _router;
public LandingPageRouter(IRouter router)
{
_router = router;
}
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
return null;
}
public Task RouteAsync(RouteContext context)
{
var requestPath = context.HttpContext.Request.Path.Value;
if (!string.IsNullOrEmpty(requestPath) && requestPath[0] == '/')
{
requestPath = requestPath.Substring(1);
}
var pagefound = GetPages().Any(x => x == requestPath);
if (pagefound)
{
//TODO: Handle querystrings
var routeData = new RouteData();
routeData.Values["controller"] = "LandingPage";
routeData.Values["action"] = "Index";
context.RouteData = routeData;
return _router.RouteAsync(context);
}
return Task.FromResult(0);
}
private IEnumerable<string> GetPages()
{
//TODO: pull from database
return new List<string> { "page-url-title", "another-dynamic-url" };
}
}
这似乎不是最好的解决方案,但从我的测试来看,它应该能满足您的需求
我将默认的MVC
IRouter
注入您的LandingPageRouter
。然后,更新路由数据后,只需调用默认路由器并在上下文中传递:
public class LandingPageRouter : IRouter
{
private readonly IRouter _router;
public LandingPageRouter(IRouter router)
{
_router = router;
}
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
return null;
}
public Task RouteAsync(RouteContext context)
{
var requestPath = context.HttpContext.Request.Path.Value;
if (!string.IsNullOrEmpty(requestPath) && requestPath[0] == '/')
{
requestPath = requestPath.Substring(1);
}
var pagefound = GetPages().Any(x => x == requestPath);
if (pagefound)
{
//TODO: Handle querystrings
var routeData = new RouteData();
routeData.Values["controller"] = "LandingPage";
routeData.Values["action"] = "Index";
context.RouteData = routeData;
return _router.RouteAsync(context);
}
return Task.FromResult(0);
}
private IEnumerable<string> GetPages()
{
//TODO: pull from database
return new List<string> { "page-url-title", "another-dynamic-url" };
}
}
基于这个和@sock方法,我传递了route builder,它将同时传递路由器上下文
public LandingPageRouter(IRouteBuilder routeBuilder)
{
_routeBuilder = routeBuilder;
}
public Task RouteAsync(RouteContext context)
{
var requestPath = context.HttpContext.Request.Path.Value;
if (!string.IsNullOrEmpty(requestPath) && requestPath[0] == '/')
{
requestPath = requestPath.Substring(1);
}
var pagefound = GetPages().SingleOrDefault(x => x.Name == requestPath);
if (pagefound!=null)
{
//TODO: Handle querystrings
var routeData = new RouteData();
routeData.Values["controller"] = "LandingPage";
routeData.Values["action"] = "Index";
routeData.Values["id"] = pagefound.Id;
context.RouteData = routeData;
return _routeBuilder.DefaultHandler.RouteAsync(context);
}
return Task.FromResult(0);
}
在startup.cs中路由配置
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.Routes.Add(new LandingPageRouter(routes));
}
基于这个和@sock方法,我传递了route builder,它将同时传递路由器上下文
public LandingPageRouter(IRouteBuilder routeBuilder)
{
_routeBuilder = routeBuilder;
}
public Task RouteAsync(RouteContext context)
{
var requestPath = context.HttpContext.Request.Path.Value;
if (!string.IsNullOrEmpty(requestPath) && requestPath[0] == '/')
{
requestPath = requestPath.Substring(1);
}
var pagefound = GetPages().SingleOrDefault(x => x.Name == requestPath);
if (pagefound!=null)
{
//TODO: Handle querystrings
var routeData = new RouteData();
routeData.Values["controller"] = "LandingPage";
routeData.Values["action"] = "Index";
routeData.Values["id"] = pagefound.Id;
context.RouteData = routeData;
return _routeBuilder.DefaultHandler.RouteAsync(context);
}
return Task.FromResult(0);
}
在startup.cs中路由配置
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.Routes.Add(new LandingPageRouter(routes));
}
请停止使用术语MVC6。当/如果旧版MVC的新版本发布时,您只会传播混乱!以前的“ASP.NET 5 MVC6”现在被命名为“ASP.NET Core MVC 1.0”,以明确它不是ASP.NET MVC5的下一个版本,而是从头编写的一个全新框架。另外,正确的标记是
asp.net核心mvc
!看起来是个有趣的场景…你能提供更多的信息吗?因此,如果像/articles/cavaliers win nba title
这样的请求传入,您希望映射到/articles/10
url,该url由articles
控制器处理,并接收文章id10
,并且在生成链接时,您希望映射以另一种方式发生……对吗?@KiranChalla我希望要在根级别(如mydomain.com/name-of-the-article)和内部配置路由并将这些路由映射到我的登录页控制器,它可以是-article@Tseng是的,我知道这是一个全新的版本,它被重命名为核心MVC,我只是用这个名字,因为以前的问题都是这样写的,所以我的错,我会在下一个问题中试着记住它,谢谢你的提醒,不要再使用MVC6这个词了。当/如果旧版MVC的新版本发布时,您只会传播混乱!以前的“ASP.NET 5 MVC6”现在被命名为“ASP.NET Core MVC 1.0”,以明确它不是ASP.NET MVC5的下一个版本,而是从头编写的一个全新框架。另外,正确的标记是asp.net核心mvc
!看起来是个有趣的场景…你能提供更多的信息吗?因此,如果像/articles/cavaliers win nba title
这样的请求传入,您希望映射到/articles/10
url,该url由articles
控制器处理,并接收文章id10
,并且在生成链接时,您希望映射以另一种方式发生……对吗?@KiranChalla我希望要在根级别(如mydomain.com/name-of-the-article)和内部配置路由并将这些路由映射到我的登录页控制器,它可以是-article@Tseng是的,我知道这是一个全新的版本,它被重命名为核心MVC,我只是用这个名字,因为以前的问题都是这样写的,所以我的错,我会在我的下一个问题中试着记住它,谢谢你的提醒,我最终得到了与你提出的类似的方法,你的答案肯定会帮助我指出正确的道路!谢谢,我最终采用了与你所提出的类似的方法,你的答案肯定会帮助我指出正确的道路!很高兴这能起作用,看起来您链接的答案也直接传入了DefaultHandler
,而不是您的答案中的IRouteBuilder
——我想知道它们之间的差异意味着什么。也许只是一个告诉不问和偏好的问题?这是我自己在Github上的后期复制,基本上,我实现了IRouterBuiler,因为“routes”(如app.UseMvc中的表达式)实现了IRoutebuilder,我觉得将其作为参数传递更“自然”,但由于缺乏文档,这只是我的观点