在 Razor 页面的 Url 中添加没有可见标识符的静态路由
Add static Routes without visible Identifiers in Url in Razor Pages
我们想将网站从 Asp.Net Webforms 迁移到 Asp.Net Core Webapplication (Razor Pages)。我们现在有了没有可见标识符的可读 Urls(为了可读性、SEO 和防止在可能的数据库迁移后更改 Urls...)。
为此,我在启动时在 Global.Asax 中动态生成了路由:
RouteTable.Routes.MapPageRoute("myroute1",
"banana/",
"~/content.aspx", false, new RouteValueDictionary { { "id", "4711" }, , { "otherid", "4812" }
RouteTable.Routes.MapPageRoute("myroute2",
"apple/",
"~/content.aspx", false, new RouteValueDictionary { { "id", "4913" }, , { "otherid", "5014" }
这样用户可以这样调用 content.aspx:
https://example.com/banana
https://example.com/apple
在 content.aspx 中,我从 RouteValues 中获得了映射的“id”和“otherid”。
我如何在 Razor Pages 中实现这一点?
现在我有一个“Content.cshtml”,我需要访问 id 和 otherid。我在顶部添加了这个:
@page "/content/{id:int}/{otherid:int}/{title:string}"
以上代码允许 mit 像这样调用 Urls:
https://example.com/content/4711/4812/banana // still have the ids in it and prefix "content"
是否可以在启动时使用固定参数添加所有路由?我还没有找到类似的东西。
问候
cpt.oneeye
要获得静态 url,您可以将路由放在启动 class 中。例如:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default1",
pattern: "{controller=Home}/{action=Index}/{id?}"
);
});
在这种情况下,您可以根据需要定义端点。比如你的路由,你可以这样写:
endpoints.MapControllerRoute(
name: "default",
pattern: "{content}/{id?}/{id?}/{banana}"
);
或者您可以使用可用于每个控制器的 Attribute Routing
。 read more about that in
对不起我的英语
感谢这个帖子,我找到了解决方案:
可在此处找到另一个完整示例:
https://github.com/dotnet/AspNetCore.Docs/issues/12997
根据我在顶部的示例,您首先制作自己的 DynamicRouteValueTransformer(请参阅命名空间 Microsoft.AspNetCore.Mvc.Routing):
public class NavigationTransformer : DynamicRouteValueTransformer
{
private readonly MyDatabaseContext _repository;
public NavigationTransformer(MyDatabaseContext repository)
{
_repository = repository;
}
public override async ValueTask<RouteValueDictionary> TransformAsync(HttpContext httpContext, RouteValueDictionary values)
{
// all requests which are incoming and fit a specific pattern will go through this method
var slug = values["slug"] as string;
// just get your needed info according to the "slug"
// in my case i have to map according to NavigationNodes that are stored in the Database
var myNavigationNode = _repository.NavigationNodes.FirstOrDefault(nn => nn.Name == slug);
if (node == null)
{
// User will get a 404
return null;
}
// set Path to Page according to Type (or whatever fits your logic)
string pagename = "";
if(node.Type == "ContentPage")
{
pagename = "/Content" // Pages/Content.cshtml
}
else if(node.Type == "ContactForm")
{
pagename = "/Contact" // Pages/Contact.cshtml
}
else
{
pagename = "/Someotherpage"
}
// return all RouteValues you need on your Page
return new RouteValueDictionary()
{
{ "page", pagename },
{ "id", node.Id },
{ "otherid", node.OtherId }
};
}
}
在 Startup.ConfigureServices() 中注册新服务:
services.AddScoped<NavigationTransformer>();
在 Startup.Configure() 中,您将 NavigationTransformer 添加到端点:
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapDynamicPageRoute<NavigationTransformer>("{slug}"); // just "slug" so that every request will be handled by NavigationTransformer, you can also add a prefix-folder
});
现在,当您像下面这样调用 url 时,您将通过 Transformer 并且可以即时重新路由:
https://example.com/banana
https://example.com/apple
请注意现有页面的路由更强大。所以如果我们有一个 Apple.cshtml 第二个 Url 仍然会被路由到 Apple.cshtml 而不是 Content.cshtml
我们想将网站从 Asp.Net Webforms 迁移到 Asp.Net Core Webapplication (Razor Pages)。我们现在有了没有可见标识符的可读 Urls(为了可读性、SEO 和防止在可能的数据库迁移后更改 Urls...)。
为此,我在启动时在 Global.Asax 中动态生成了路由:
RouteTable.Routes.MapPageRoute("myroute1",
"banana/",
"~/content.aspx", false, new RouteValueDictionary { { "id", "4711" }, , { "otherid", "4812" }
RouteTable.Routes.MapPageRoute("myroute2",
"apple/",
"~/content.aspx", false, new RouteValueDictionary { { "id", "4913" }, , { "otherid", "5014" }
这样用户可以这样调用 content.aspx:
https://example.com/banana
https://example.com/apple
在 content.aspx 中,我从 RouteValues 中获得了映射的“id”和“otherid”。
我如何在 Razor Pages 中实现这一点?
现在我有一个“Content.cshtml”,我需要访问 id 和 otherid。我在顶部添加了这个:
@page "/content/{id:int}/{otherid:int}/{title:string}"
以上代码允许 mit 像这样调用 Urls:
https://example.com/content/4711/4812/banana // still have the ids in it and prefix "content"
是否可以在启动时使用固定参数添加所有路由?我还没有找到类似的东西。
问候 cpt.oneeye
要获得静态 url,您可以将路由放在启动 class 中。例如:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default1",
pattern: "{controller=Home}/{action=Index}/{id?}"
);
});
在这种情况下,您可以根据需要定义端点。比如你的路由,你可以这样写:
endpoints.MapControllerRoute(
name: "default",
pattern: "{content}/{id?}/{id?}/{banana}"
);
或者您可以使用可用于每个控制器的 Attribute Routing
。 read more about that in
对不起我的英语
感谢这个帖子,我找到了解决方案:
可在此处找到另一个完整示例:
https://github.com/dotnet/AspNetCore.Docs/issues/12997
根据我在顶部的示例,您首先制作自己的 DynamicRouteValueTransformer(请参阅命名空间 Microsoft.AspNetCore.Mvc.Routing):
public class NavigationTransformer : DynamicRouteValueTransformer
{
private readonly MyDatabaseContext _repository;
public NavigationTransformer(MyDatabaseContext repository)
{
_repository = repository;
}
public override async ValueTask<RouteValueDictionary> TransformAsync(HttpContext httpContext, RouteValueDictionary values)
{
// all requests which are incoming and fit a specific pattern will go through this method
var slug = values["slug"] as string;
// just get your needed info according to the "slug"
// in my case i have to map according to NavigationNodes that are stored in the Database
var myNavigationNode = _repository.NavigationNodes.FirstOrDefault(nn => nn.Name == slug);
if (node == null)
{
// User will get a 404
return null;
}
// set Path to Page according to Type (or whatever fits your logic)
string pagename = "";
if(node.Type == "ContentPage")
{
pagename = "/Content" // Pages/Content.cshtml
}
else if(node.Type == "ContactForm")
{
pagename = "/Contact" // Pages/Contact.cshtml
}
else
{
pagename = "/Someotherpage"
}
// return all RouteValues you need on your Page
return new RouteValueDictionary()
{
{ "page", pagename },
{ "id", node.Id },
{ "otherid", node.OtherId }
};
}
}
在 Startup.ConfigureServices() 中注册新服务:
services.AddScoped<NavigationTransformer>();
在 Startup.Configure() 中,您将 NavigationTransformer 添加到端点:
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapDynamicPageRoute<NavigationTransformer>("{slug}"); // just "slug" so that every request will be handled by NavigationTransformer, you can also add a prefix-folder
});
现在,当您像下面这样调用 url 时,您将通过 Transformer 并且可以即时重新路由:
https://example.com/banana
https://example.com/apple
请注意现有页面的路由更强大。所以如果我们有一个 Apple.cshtml 第二个 Url 仍然会被路由到 Apple.cshtml 而不是 Content.cshtml