想象一下用ASP.Net MVC编写的在线商店,我有一个用于显示产品和产品细节的控制器。给出以下代码
public class ProductsController : Controller {
public IActionResult Index(){
return View(ProductList);
}
public IActionResult Details(String id){
return View(FindProduct(id));
}
}
在查找产品时,网络浏览器地址栏中显示的网址与此类似:www.onlineshop.com/Products/Details?id=1234
。
我一直在研究搜索引擎优化,我一直在想,如果我将网址重新路由到更详细的网址会更好:
www.onlineshop.com/Products/Sony/Gaming/PlayStation/PS4Model12345
如何在ASP.Net MVC(Core)中实现这一目标? (给出我提供的示例控制器)
答案 0 :(得分:1)
这个问题的答案实际上非常简单。我不知道为什么其他用户在这里推荐了相当冗长的解决方案,但在我看来,可以通过在Route
API上添加Details
属性来实现。当有人需要在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,这无关紧要!
<强>更新强>
在视图中构建网址更具SEO性,因为它可以创建合理的链接!
更好的示例,在stackoverflow的情况下,此问题的URL是
http://stackoverflow.com/questions/42472547/mvc-core-routing-for-displaying-detailed-information-in-the-url
在此示例中,实际问题ID为42472547
,尾随部分用于搜索引擎优化,以便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);
}