路由中的可选参数以paging参数结尾

时间:2012-02-17 09:09:49

标签: asp.net asp.net-mvc routing global-asax

我一直在创建一个包含3个不同视图的博客。 - 概述 - 发布详细信息 - 过滤概述

过滤后的概述基于包含特定标记的博客帖子,为了使网址更漂亮,我希望能够像以下一样添加可选参数:

mydomain.com/blog/<tagname>/<page>
mydomain.com/blog/<tagname1>/<tagname2>/<page>
mydomain.com/blog/<tagname1>/<tagname2>/<tagname3>/<page>

页面参数是半可选的,如果没有,它应该是1.但在大多数情况下它会在那里。 有没有办法以一种很好的方式解决这个问题? 我能想到的唯一方法是在我的全局asax中创建很多行,这让我觉得它有些混乱。

提前致谢DerDee

2 个答案:

答案 0 :(得分:1)

MVC中的必需参数之前不能有可选参数。一种解决方案是将paging参数放在tags参数之前:

mydomain.com/blog/<page>/<tagname>
mydomain.com/blog/<page>/<tagname1>/<tagname2>
mydomain.com/blog/<page>/<tagname1>/<tagname2>/<tagname3>

然后,您可以为路线中的页面参数指定默认值:

MapRoute(null, "blog/{page}/{*tagNames}", 
    new { controller = "Blogs", action = "ByPageAndTags", page = 1 });

答案 1 :(得分:1)

您可以编写自定义路线:

public class BlogRoute : Route
{
    public BlogRoute()
        : base(
            "blog/{*info}", 
            new RouteValueDictionary(new 
            { 
                controller = "blog", 
                action = "index" 
            }),
            new MvcRouteHandler()
        )
    { 
    }

    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        var rd = base.GetRouteData(httpContext);
        if (rd == null)
        {
            return null;
        }

        var info = rd.Values["info"] as string;
        if (string.IsNullOrEmpty(info))
        {
            return rd;
        }

        var parts = info.Split('/');
        if (parts.Length < 1)
        {
            return rd;
        }

        for (int i = 0; i < parts.Length; i++)
        {
            if (i == parts.Length - 1)
            {
                int page;
                if (int.TryParse(parts[i], out page))
                {
                    rd.Values["page"] = page;
                }
            }

            if (!rd.Values.ContainsKey("page"))
            {
                rd.Values[string.Format("tags[{0}]", i)] = parts[i];
            }
        }

        return rd;
    }
}

将在Global.asax注册:

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

    routes.Add("BlogRoute", new BlogRoute());

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

然后你可以有一个BlogController:

public class BlogController : Controller
{
    public ActionResult Index(string[] tags, int? page)
    {
        ...
    }
}