使用Slug的C#Mvc通用路线

时间:2016-05-12 16:54:22

标签: c# asp.net-mvc routes slug

我试图创建一个使用slugs的通用路由,但我总是遇到错误

我的想法是,而不是 www.site.com/controller/action ,我会在网址中找到友好的 www.site.com/ {slug}

e.g。 www.site.com/Home/Open 将改为 www.site.com/open-your-company

错误

  

服务器错误' /'应用程序无法找到资源

Global.asax 我有

public static void RegisterRoutes(RouteCollection routes)
{
    //routes.Clear();
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute("DefaultSlug", "{slug}", new { controller = "Home", action = "Open", slug = "" });
    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new
        {
            area = "",
            controller = "Home",
            action = "Index",
            id = UrlParameter.Optional,
            slug = ""
        }
    );
}

在我的一个cshtml中,我有以下链接(即使在评论时,仍然存在相同的错误)。

@Html.ActionLink("Open your company", "DefaultSlug", new { controller = "Home", action = "Open", slug = "open-your-company" })

编辑:HomeController

public ActionResult Open() { 
    return View(new HomeModel()); 
}

2 个答案:

答案 0 :(得分:0)

在Global.asax中,slug不能为空,如果为空,则网址不会转到默认路由

public static void RegisterRoutes(RouteCollection routes)
{
    //routes.Clear();
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "DefaultSlug",
        url: "{slug}",
        defaults: new { controller = "Home", action = "Open" },
        constraints: new{ slug=".+"});

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new
        {
            area = "",
            controller = "Home",
            action = "Index",
            id = UrlParameter.Optional
        }
    );
}

并更新HomeController

public ActionResult Open(string slug) {
    HomeModel model = contentRepository.GetBySlug(slug);

    return View(model); 
}

测试路线链接......

@Html.RouteLink("Open your company", routeName: "DefaultSlug", routeValues: new { controller = "Home", action = "Open", slug = "open-your-company" })

和行动链接......

@Html.ActionLink("Open your company", "Open", routeValues: new { controller = "Home", action = "Open", slug = "open-your-company" })

都产生......

http://localhost:35979/open-your-company

答案 1 :(得分:0)

这是我完成类似任务所采取的步骤。这取决于模型上的自定义Slug字段以匹配路径。

  1. 设置您的控制器,例如控制器\ PagesController.cs:

    public class PagesController : Controller
    {
        // Regular ID-based routing
        [Route("pages/{id}")]
        public ActionResult Detail(int? id)
        {
            if(id == null)
            {
                return new HttpNotFoundResult();
            }
    
            var model = myContext.Pages.Single(x => x.Id == id);
            if(model == null)
            {
                return new HttpNotFoundResult();
            }
            ViewBag.Title = model.Title;
            return View(model);
        }
    
        // Slug-based routing - reuse View from above controller.
        public ActionResult DetailSlug (string slug)
        {
            var model = MyDbContext.Pages.SingleOrDefault(x => x.Slug == slug);
            if(model == null)
            {
                return new HttpNotFoundResult();
            }
            ViewBag.Title = model.Title;
            return View("Detail", model);
        }
    }
    
  2. 在App_Start \ RouteConfig.cs中设置路由

    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            // Existing route register code
    
            // Custom route - top priority
            routes.MapRoute(
                    name: "PageSlug", 
                    url: "{slug}", 
                    defaults: new { controller = "Pages", action = "DetailSlug" },
                    constraints: new {
                        slug = ".+", // Passthru for no slug (goes to home page)
                        slugMatch = new PageSlugMatch() // Custom constraint
                    }
                );
            }
    
            // Default MVC route setup & other custom routes
        }
    }
    
  3. 自定义IRouteConstraint实现,例如的Utils \ RouteConstraints.cs

    public class PageSlugMatch : IRouteConstraint
    {
        private readonly MyDbContext MyDbContext = new MyDbContext();
    
        public bool Match(
            HttpContextBase httpContext,
            Route route,
            string parameterName,
            RouteValueDictionary values,
            RouteDirection routeDirection
        )
        {
            var routeSlug = values.ContainsKey("slug") ? (string)values["slug"] : "";
            bool slugMatch = false;
            if (!string.IsNullOrEmpty(routeSlug))
            {
                slugMatch = MyDbContext.Pages.Where(x => x.Slug == routeSlug).Any();
            }
            return slugMatch;
        }
    }