这个问题的答案其实很简单。我不知道为什么这里的其他用户推荐相当冗长的解决方案,但我认为可以通过在Details API 上添加Route 属性来执行。当有人需要在View 中显示产品列表时,如果他们只显示Product Id 并且通常IEnumberable<Product> 在问题中提出的情况下传递给Index 视图,这是非常不可能和不合逻辑的.因此,可以做到以下几点:
[Route("Products/Details/{Manufacturer=unnamed}/{Category=unnamed}/{ActualProduct=unnamed}/{Model=unnamed}/{URLTrail=unnamed}")]
public IActionResult Details(GUID id) {
return View(FindProduct(id));
}
示例输出:www.MyOnlineShop.com/Products/Details/Microsoft/Surface/SurfacePro/xxxx-xxxx-....
现在,如果缺少其中一些 URL 参数确实无关紧要,但用户可以选择呈现他们喜欢的 URL!。
更新:
在视图内构建 URL 对 SEO 更友好,因为它可以创建合理的链接!
一个更好的例子,在stackoverflow的情况下,这个问题的URL是
http://stackoverflow.com/questions/42472547/mvc-core-routing-for-displaying-detailed-information-in-the-url
在这个例子中,实际的问题 ID 是 42472547 并且尾随部分用于 SEO,以便 Google 可以搜索问题。在此示例中,适用以下路线:
[Route("Questions/{id}/{SEOHint}"]
{id} 部分用于查找问题,而不是 {SEOHint} 部分。
更新的解决方案
我编写了以下属性,可以自定义以实现此功能。
public abstract class URLOptimizerAttributeBase : Attribute, IRouteTemplateProvider, IActionFilter
{
public String Template { get; private set; }
public int? Order { get; set; }
public string Name { get; set; }
public URLOptimizerAttributeBase(String Template) {
this.Template = Template;
}
public abstract Boolean Validate(RouteData routeData);
public abstract RedirectToRouteResult Redirect(RouteValueDictionary routeValueDictionary);
public abstract void OnActionExecuted(ActionExecutedContext context);
public virtual void OnActionExecuting(ActionExecutingContext context)
{
if (!Validate(context.RouteData))
{
context.Result = Redirect(context.RouteData.Values);
}
}
}
下面提供了该属性的实现示例。
public class URLOptimization : URLOptimizerAttributeBase
{
private String SEOHint;
public URLOptimization(string Template) : base(Template)
{
}
public object DbContext { get; private set; }
public override void OnActionExecuted(ActionExecutedContext context)
{
}
public override bool Validate(RouteData routeData)
{
return routeData.Values["SEOHint"].Equals(SEOHint);
}
public override RedirectToRouteResult Redirect(RouteValueDictionary routeValueDictionary)
{
routeValueDictionary["SEOHind"] = SEOHint;
return new RedirectToRouteResult(routeValueDictionary);
}
public override void OnActionExecuting(ActionExecutingContext context)
{
var id = context.RouteData.Values["Id"];
DbContext db = (DbContext)context.HttpContext.RequestServices.GetService(typeof(DbContext));
var product = db.Find<Products>(id);
if (product != null)
{
SEOHint = product.SEOURL;
((Controller)context.Controller).ViewBag.Data = product;
base.OnActionExecuting(context);
}
else {
context.Result = new RedirectResult("Error Page");
}
}
}
使用该属性的示例如下:
[URLOptimization("Products/Details/{Id}/{SEOHint=unnamed}")]
public IActionResult Details(){
return View(ViewBag.Data);
}