.Net 3.x
Controllers
public partial class BlogController : BasePublicController
{
public async Task<IActionResult> BlogPost(string id)
{
var model = new BlogPostModel();
PrepareBlogPostModel(model, blogPost, true);
return View(model);
}
}
route
step 1: default route
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
//
}
Step 2:vist
https://www.iaspnetcore.com/blog/blogpost/5a2400a791d3091f94bfce98
Change Url
Step 3: Add
endpointRouteBuilder.MapControllerRoute("BlogPost", "{SeName}", new { controller = "Blog", action = "BlogPost" });
Step 4:Create Url
view
<div class="post-head">
<a class="post-title" href="@Url.RouteUrl("BlogPost", new {SeName = item.SeName})">@item.Title</a>
</div>
output
<a href="/nginx-errorcould-not-build-optimal-proxy_headers_hash-you-should-increase-either-proxy_headers_hash_max_size-512-or-proxy_headers_hash_bucket_size-64-ignoring-proxy_headers_hash_bucket_size" class="button-2 btn btn-primary read-more">details</a>
Create RouteProvider class and Register it
Step 5: Create RouteProvider class
public class RouteProvider : IRouter
{
private readonly IRouter target;
private ILogger _logger;
public RouteProvider(IRouter target)
{
this.target = target;
}
public async Task RouteAsync(RouteContext context)
{
//example http://www.iaspnetcore.com/about
string domain = context.HttpContext.Request.Host.Host;//获取当前请求域名
var requestPath = context.HttpContext.Request.Path.Value; //here requestPath="/about"
if (!string.IsNullOrEmpty(requestPath) && requestPath[0] == '/')
{
// Trim the leading slash
requestPath = requestPath.Substring(1); //here requestPath="about"
}
if (requestPath == "/About")
{
var oldRouteData = context.RouteData;
var newRouteData = new RouteData(oldRouteData);
newRouteData.Routers.Add(target);
newRouteData.Values["controller"] = "Article";
newRouteData.Values["action"] = "Detail";
newRouteData.Values["id"] = "586faeaf0141bf20236530f0";
context.RouteData = newRouteData;
await target.RouteAsync(context);
return;
}
//改变路由值
context.RouteData = currentRouteData;
await target.RouteAsync(context);
}
}
Step 6:Register
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseMvc(routes =>
{
//自定义路由处理
routes.Routes.Add(new RouteProvider(routes.DefaultHandler));
});
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpointRouteBuilder.MapControllerRoute("BlogPost", "{SeName}", new { controller = "Blog", action = "BlogPost" });
});
//
}
vist
https://www.iaspnetcore.com/about-us
Get url from Database
UrlRecord Collection in Database
/* 1 createdAt:2020/10/18 下午9:20:33*/
{
"_id" : ObjectId("5f8c4121f3819901ee0d9187"),
"GenericAttributes" : [ ],
"EntityId" : ObjectId("5f8c4121f3819901ee0d9182"),
"EntityName" : "BlogPost",
"Slug" : "nopcommerce-4x-blog-url",
"IsActive" : true,
"LanguageId" : ObjectId("5cf6adc550f62850c08d1153")
},
/* 2 createdAt:2020/10/18 上午12:46:07*/
{
"_id" : ObjectId("5f8b1fcff3819901eefd891e"),
"GenericAttributes" : [ ],
"EntityId" : ObjectId("5e5af49123303e01ed61d104"),
"EntityName" : "BlogPost",
"Slug" : "nginx-errorerror-unicodedecodeerror-utf-8-codec-cant-decode-byte-0xb2-in-position-3494-invalid-start-byte-lets-encrypt",
"IsActive" : true,
"LanguageId" : ObjectId("5cf6adc550f62850c08d1153")
},
public class RouteProvider : IRouter
{
private readonly IRouter target;
private ILogger _logger;
public RouteProvider(IRouter target)
{
this.target = target;
}
public async Task RouteAsync(RouteContext context)
{
//example http://www.iaspnetcore.com/about
string domain = context.HttpContext.Request.Host.Host;//获取当前请求域名
var requestPath = context.HttpContext.Request.Path.Value; //here requestPath="/about"
if (!string.IsNullOrEmpty(requestPath) && requestPath[0] == '/')
{
// Trim the leading slash
requestPath = requestPath.Substring(1); //here requestPath="about"
}
var slug = requestPath as string;
var urlRecordService = EngineContext.ServiceProvider.GetRequiredService<IUrlRecordService>();
//从集合中找记录
var urlRecord = urlRecordService.GetBySlugCached(slug);
#if DEBUG
_logger = _logger ?? context.HttpContext.RequestServices.GetService<ILogger<RouteProvider>>();
_logger.LogInformation($"{DateTime.Now} Nop.Web.Framework.Mvc.Routes.RouteProvider:{domain} {slug} ");
#endif
//no URL record found
if (urlRecord == null)
{
#if DEBUG
// _logger.LogInformation($"Nop.Web.Framework.Mvc.Routes.RouteProvider:urlRecord not found ");
#endif
return;
}
if (requestPath == "/About")
{
var oldRouteData = context.RouteData;
var newRouteData = new RouteData(oldRouteData);
newRouteData.Routers.Add(target);
newRouteData.Values["controller"] = "Article";
newRouteData.Values["action"] = "Detail";
newRouteData.Values["id"] = "586faeaf0141bf20236530f0";
context.RouteData = newRouteData;
await target.RouteAsync(context);
return;
}
//since we are here, all is ok with the slug, so process URL
var currentRouteData = new RouteData(context.RouteData);
switch (urlRecord.EntityName.ToLowerInvariant())
{
case "product":
currentRouteData.Values["controller"] = "Product";
currentRouteData.Values["action"] = "ProductDetails";
currentRouteData.Values["productid"] = urlRecord.EntityId;
currentRouteData.Values["SeName"] = urlRecord.Slug;
break;
case "producttag":
currentRouteData.Values["controller"] = "Catalog";
currentRouteData.Values["action"] = "ProductsByTag";
currentRouteData.Values["productTagId"] = urlRecord.EntityId;
currentRouteData.Values["SeName"] = urlRecord.Slug;
break;
case "category":
currentRouteData.Values["controller"] = "Catalog";
currentRouteData.Values["action"] = "Category";
currentRouteData.Values["categoryid"] = urlRecord.EntityId;
currentRouteData.Values["SeName"] = urlRecord.Slug;
break;
case "manufacturer":
currentRouteData.Values["controller"] = "Catalog";
currentRouteData.Values["action"] = "Manufacturer";
currentRouteData.Values["manufacturerid"] = urlRecord.EntityId;
currentRouteData.Values["SeName"] = urlRecord.Slug;
break;
case "vendor":
currentRouteData.Values["controller"] = "Catalog";
currentRouteData.Values["action"] = "Vendor";
currentRouteData.Values["vendorid"] = urlRecord.EntityId;
currentRouteData.Values["SeName"] = urlRecord.Slug;
break;
case "newsitem":
currentRouteData.Values["controller"] = "News";
currentRouteData.Values["action"] = "NewsItem";
currentRouteData.Values["newsItemId"] = urlRecord.EntityId;
currentRouteData.Values["SeName"] = urlRecord.Slug;
break;
case "blogpost":
currentRouteData.Values["controller"] = "Blog";
currentRouteData.Values["action"] = "BlogPost";
currentRouteData.Values["blogPostId"] = urlRecord.EntityId;
currentRouteData.Values["SeName"] = urlRecord.Slug;
break;
case "topic":
currentRouteData.Values["controller"] = "Topic";
currentRouteData.Values["action"] = "TopicDetails";
currentRouteData.Values["id"] = urlRecord.EntityId;
currentRouteData.Values["SeName"] = urlRecord.Slug;
break;
default:
//no record found, thus generate an event this way developers could insert their own types
//EngineContext.Current.Resolve<IEventPublisher>()
// ?.Publish(new CustomUrlRecordEntityNameRequestedEvent(currentRouteData, urlRecord));
break;
}
//改变路由值
context.RouteData = currentRouteData;
await target.RouteAsync(context);
}
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
return null;
}
}