我需要提供一个路由机制,其中路由是在运行时从用户帐户创建生成的。例如http://mysite/username/home
。
我认为这可以通过路由完成,但我不知道从哪里开始使用ASP.Net Core。我在网上看到了一些MVC 5的例子,但ASP.Net Core似乎处理的路由有点不同。如何确保在http://mysite/username/news
成为用户自定义目标网页和http://mysite/news
成为网站新闻页面时,网站不会混淆?
答案 0 :(得分:3)
我不确定以下方式是否正确。它适用于我,但你应该为你的场景测试它。
首先创建用户服务以检查用户名:
public interface IUserService
{
bool IsExists(string value);
}
public class UserService : IUserService
{
public bool IsExists(string value)
{
// your implementation
}
}
// register it
services.AddScoped<IUserService, UserService>();
然后为用户名创建路由约束:
public class UserNameRouteConstraint : IRouteConstraint
{
public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
{
// check nulls
object value;
if (values.TryGetValue(routeKey, out value) && value != null)
{
var userService = httpContext.RequestServices.GetService<IUserService>();
return userService.IsExists(Convert.ToString(value));
}
return false;
}
}
// service configuration
services.Configure<RouteOptions>(options =>
options.ConstraintMap.Add("username", typeof(UserNameRouteConstraint)));
最后写路由和控制器:
app.UseMvc(routes =>
{
routes.MapRoute("default",
"{controller}/{action}/{id?}",
new { controller = "Home", action = "Index" },
new { controller = @"^(?!User).*$" }// exclude user controller
);
routes.MapRoute("user",
"{username:username}/{action=Index}",
new { controller = "User" },
new { controller = @"User" }// only work user controller
);
});
public class UserController : Controller
{
public IActionResult Index()
{
//
}
public IActionResult News()
{
//
}
}
public class NewsController : Controller
{
public IActionResult Index()
{
//
}
}
答案 1 :(得分:1)
.net Core 中的路由是一个相当广泛的主题,但我对动态路由的偏好如下!
public class Router : IRouter
{
private readonly IRouter _innerRouter;
IApplicationBuilder b;
public Router(IRouter innerRouter, IApplicationBuilder bb)
{
if (innerRouter == null)
throw new ArgumentNullException("innerRouter");
this._innerRouter = innerRouter;
b = bb;
}
public async Task RouteAsync(RouteContext context)
{
var requestPath = context.HttpContext.Request.Path.Value;
if (!string.IsNullOrEmpty(requestPath) && requestPath[0] == '/')
{
// Trim the leading slash
requestPath = requestPath.Substring(1);
}
if (requestPath.Trim() == String.Empty)
return;
using (var serviceScope = b.ApplicationServices.CreateScope())
{
DomainDbContext dbContext = serviceScope.ServiceProvider.GetRequiredService<DomainDbContext>();
int type = 0;
int id = 0;
Page page = dbContext.Page.Where(_ => _.Url.ToLower().Contains(requestPath.ToLower()) || requestPath.ToLower().Contains(_.Url.ToLower())).FirstOrDefault();
if (page != null)
{
type = 1; //page
id = page.Id;
}
Blog blog = dbContext.Blog.Where(_ => _.Url.ToLower().Contains(requestPath.ToLower()) || requestPath.ToLower().Contains(_.Url.ToLower())).FirstOrDefault();
if (blog != null)
{
type = 2; //blog
id = blog.Id;
}
if (type == 0)
return;
//Invoke MVC controller/action
var oldRouteData = context.RouteData;
var newRouteData = new RouteData(oldRouteData);
newRouteData.Routers.Add(this._innerRouter);
newRouteData.Values["controller"] = "Dynamic";
newRouteData.Values["action"] = "Index";
newRouteData.Values["id"] = type + "," + id;
try
{
context.RouteData = newRouteData;
await this._innerRouter.RouteAsync(context);
}
finally
{
// Restore the original values to prevent polluting the route data.
//if (!context.IsHandled)
//{
// context.RouteData = oldRouteData;
//}
}
}
}
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
VirtualPathData result = null;
var values = context.Values;
var controller = Convert.ToString(values["controller"]);
var action = Convert.ToString(values["action"]);
var id = Convert.ToString(values["id"]);
if ("Item".Equals(controller) && "View".Equals(action))
{
result = new VirtualPathData(this, "abcd?id=" + id);
//context.IsBound = true;
}
// IMPORTANT: Always return null if there is no match.
// This tells .NET routing to check the next route that is registered.
return result;
}
}