是否可以使用相同的路线到许多控制器?

时间:2014-01-31 21:56:21

标签: asp.net asp.net-mvc asp.net-mvc-5

我想为各种控制器创建一个独特的路由来简化URL。我想为控制器定义一个优先级顺序,如下所示:

RouteConfig:

routes.MapRoute("Category", "{*url}", new { controller = "Category", action = "Index" });
routes.MapRoute("Product", "{*url}", new { controller = "Product", action = "Index" });
routes.MapRoute("User", "{*url}", new { controller = "User", action = "Index" });

CategoryController:

public class CategoryController : Controller
{
    public ActionResult Index(string url)
    {
        var categoryManager = new CategoryManager();
        var category = categoryManager.GetByURL(url);

        if (category != null)
        {
            return View(category); 
        }

        // ignore and try next controller
    }
}

ProductController的:

public class ProductController : Controller
{
    public ActionResult Index(string url)
    {
        var productManager = new ProductManager();
        var product= productManager.GetByURL(url);

        if (product!= null)
        {
            return View(product); 
        }

        // ignore and try next controller
    }
}

UserController中:

public class UserController : Controller
{
    public ActionResult Index(string url)
    {
        var userManager = new UserManager();
        var user = userManager.GetByURL(url);

        if (user != null)
        {
            return View(user); 
        }

        // ignore and try next controller
    }
}

示例:

当网址为 / computers

  • CategoryController 找到类别实体并返回正确的视图;

当网址为 / iphone5 时:

  • CategoryController 找不到类别并忽略;
  • ProductController 找到产品实体并返回正确的视图;

当网址为 / charles 时:

  • CategoryController 找不到类别并忽略;
  • ProductController 找不到产品并忽略;
  • UserController 找到用户实体并返回正确的视图;

我不知道怎么做,有人可以帮助我吗?

我疯了吗?

注意:为了更好的组织,我想要一个控制器。

4 个答案:

答案 0 :(得分:1)

据我所知,该功能并未构建在基本路由库中。

您需要创建一个新的自定义Route类,该类继承RouteBase,并在您未能获得匹配时从GetRouteData覆盖返回null。返回null将允许回退到下一个路由处理程序。

示例:

public class CategoryRoute : RouteBase
{
    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        if (we dont find our category)
            return null;
        else
        {
            var routeData = new RouteData(this, new MvcRouteHandler());
            routeData.Values.Add("controller", "Category");
            routeData.Values.Add("action", "Index");
            routeData.Values.Add("url", catUrl);

            return routeData;
        }
    }
}

然后调用Add,而不是调用MapRoute,如下所示:

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

答案 1 :(得分:1)

一种简单但可能不是非常有效且稳健的方法是在控制器中路由到通用操作,您可以在其中确定实际操作。它看起来像这样:

public class CommonController : Controller
{
    public ActionResult GenericUrl(string url)
    {
        if (url is a category)
        {
            return RedirectToAction("Index", "Category", new { categoryId = id });
        }

        if (url is a product)
        {
            return RedirectToAction("Index", "Product", new { productId = id });
        }

        if (url is a user)
        {
            return RedirectToAction("Index", "User", new { userId = id });
        }

        return HttpNotFound();  // Might also be the homepage for example.
    }
}

您只需要定义一条路线:

routes.MapRoute("", "{*url}", new { controller = "Common", action = "GenericUrl"});

这也是在数据库中维护'slug'表的一个选项,您可以在其中查找slug并检索其关联的实体类型,唯一ID和控制器/操作。 nopCommerce使用自定义路由类型实现了此功能。

答案 2 :(得分:0)

从逻辑上讲,这没有多大意义。但是你可以创建一个控制器,并根据你的结构将它部分到不同的文件中,然后让一个Index方法沿着这条线下行,然后返回正确的视图。

// Category.cs
public partial MainController :  

// Product.cs
public partial MainController :

// User.cs
public parital MainController : 

MainController.cs将有一个Index方法,可以根据URL调用每个文件中的方法

public ActionResult Index(string url){
   // Logic for determining which method to call in the specific file here
}

这允许您通过具有单独的文件但只有一个控制器来获得组织边界。但我不认为我会推荐它。

答案 3 :(得分:0)

本文可能会对您有所帮助:

http://blogs.msdn.com/b/webdev/archive/2013/10/17/attribute-routing-in-asp-net-mvc-5.aspx

基本上,您可以创建路由约束,这些规则指定是否应该执行路由。您曾经在路线中设置过这些,但最近它们已更改为属性:

routes.MapRoute(
name: "ProductPage",
url: "{productId}/{productTitle}",
defaults: new { controller = "Products", action = "Show" },
constraints: new { productId = "\\d+" }
);

属性:

[Route("{productId:int}/{productTitle}")]
public ActionResult Show(int productId) { ... }

当然,这不是编写约束的唯一方法。每个版本的MVC都具备这种能力。需要注意的是,使用这些时要小心,不要通过编写查询db的函数来无意中引入性能问题。如果需要(例如,在捕获路由之前测试对象是否存在),则缓存值。

祝你好运!