MVC核心:用于在URL中显示详细信息的路由

时间:2017-02-26 18:39:23

标签: asp.net asp.net-mvc asp.net-core-mvc asp.net-routing

想象一下用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)中实现这一目标? (给出我提供的示例控制器)

1 个答案:

答案 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);
}