MVC路由中的控制器类别? (在单独的命名空间中重复控制器名称)

时间:2022-10-13 13:19:10

I'm looking for some examples or samples of routing for the following sort of scenario:

我正在寻找以下类型场景的一些示例或路由示例:

The general example of doing things is: {controller}/{action}/{id}

做事的一般示例是:{controller} / {action} / {id}

So in the scenario of doing a product search for a store you'd have:

因此,在对商店进行产品搜索的情况下,您需要:

public class ProductsController: Controller
{
    public ActionResult Search(string id) // id being the search string
    { ... }
}

Say you had a few stores to do this and you wanted that consistently, is there any way to then have: {category}/{controller}/{action}/{id}

假设你有几个商店要做到这一点你想要一贯的,那么有什么方法可以:{category} / {controller} / {action} / {id}

So that you could have a particular search for a particular store, but use a different search method for a different store?

这样您就可以对特定商店进行特定搜索,但对不同的商店使用不同的搜索方法?

(If you required the store name to be a higher priority than the function itself in the url)

(如果您要求商店名称的优先级高于网址中的功能本身)

Or would it come down to:

或者它会归结为:

public class ProductsController: Controller
{
    public ActionResult Search(int category, string id) // id being the search string
    { 
        if(category == 1) return Category1Search();
        if(category == 2) return Category2Search();
        ...
    }
}

It may not be a great example, but basically the idea is to use the same controller name and therefore have a simple URL across a few different scenarios, or are you kind of stuck with requiring unique controller names, and no way to put them in slightly different namespaces/directories?

它可能不是一个很好的例子,但基本上这个想法是使用相同的控制器名称,因此在几个不同的场景中有一个简单的URL,或者你是否有点需要独特的控制器名称,并且无法将它们放入略有不同的命名空间/目录?

Edit to add:

编辑添加:

The other reason I want this is because I might want a url that has the categories, and that certain controllers will only work under certain categories.

我想要这个的另一个原因是因为我可能想要一个具有类别的URL,并且某些控制器只能在某些类别下工作。

IE:

/this/search/items/search+term <-- works

/ this / search / items / search + term < - works

/that/search/items/search+term <-- won't work - because the search controller isn't allowed.

/ that / search / items / search + term < - 不起作用 - 因为不允许使用搜索控制器。

2 个解决方案

#1


4  

I actually found it not even by searching, but by scanning through the ASP .NET forums in this question.

我实际上发现它甚至不是通过搜索,而是通过在这个问题中扫描ASP .NET论坛。

Using this you can have the controllers of the same name under any part of the namespace, so long as you qualify which routes belong to which namespaces (you can have multiple namespaces per routes if you need be!)

使用此命令,您可以在命名空间的任何部分下具有相同名称的控制器,只要您确定哪些路由属于哪些命名空间(如果需要,您可以为每个路由设置多个命名空间!)

But from here, you can put in a directory under your controller, so if your controller was "MyWebShop.Controllers", you'd put a directory of "Shop1" and the namespace would be "MyWebShop.Controllers.Shop1"

但是从这里开始,您可以放入控制器下的目录,因此如果您的控制器是“MyWebShop.Controllers”,您将放置一个“Shop1”目录,命名空间将为“MyWebShop.Controllers.Shop1”

Then this works:

然后这工作:

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

        var shop1namespace = new RouteValueDictionary();
        shop1namespace.Add("namespaces", new HashSet<string>(new string[] 
        { 
            "MyWebShop.Controllers.Shop1"
        }));

        routes.Add("Shop1", new Route("Shop1/{controller}/{action}/{id}", new MvcRouteHandler())
        {
            Defaults = new RouteValueDictionary(new
            {
                action = "Index",
                id = (string)null
            }),
            DataTokens = shop1namespace
        });

        var shop2namespace = new RouteValueDictionary();
        shop2namespace.Add("namespaces", new HashSet<string>(new string[] 
        { 
            "MyWebShop.Controllers.Shop2"
        }));

        routes.Add("Shop2", new Route("Shop2/{controller}/{action}/{id}", new MvcRouteHandler())
        {
            Defaults = new RouteValueDictionary(new
            {
                action = "Index",
                id = (string)null
            }),
            DataTokens = shop2namespace
        });

        var defaultnamespace = new RouteValueDictionary();
        defaultnamespace.Add("namespaces", new HashSet<string>(new string[] 
        { 
            "MyWebShop.Controllers"
        }));

        routes.Add("Default", new Route("{controller}/{action}/{id}", new MvcRouteHandler())
        {
            Defaults = new RouteValueDictionary(new { controller = "Home", action = "Index", id = "" }),
            DataTokens = defaultnamespace            
        });
    }

The only other thing is that it will reference a view still in the base directory, so if you put the view into directories to match, you will have to put the view name in when you return it inside the controller.

唯一的另一件事是它将引用仍在基本目录中的视图,因此如果将视图放入要匹配的目录中,则必须在将其返回到控制器内时将视图名称放入。

#2


1  

The best way to do this without any compromises would be to implement your own ControllerFactory by inheriting off of IControllerFactory. The CreateController method that you will implement handles creating the controller instance to handle the request by the RouteHandler and the ControllerActionInvoker. The convention is to use the name of the controller, when creating it, therefore you will need to override this functionality. This will be where you put your custom logic for creating the controller based on the route since you will have multiple controllers with the same name, but in different folders. Then you will need to register your custom controller factory in the application startup, just like your routes.

在没有任何妥协的情况下执行此操作的最佳方法是通过继承IControllerFactory来实现您自己的ControllerFactory。您将实现的CreateController方法处理创建控制器实例以处理RouteHandler和ControllerActionInvoker的请求。惯例是在创建控件时使用控制器的名称,因此您需要覆盖此功能。这将是您根据路径创建控制器的自定义逻辑的位置,因为您将具有多个具有相同名称但位于不同文件夹中的控制器。然后,您需要在应用程序启动时注册自定义控制器工厂,就像您的路线一样。

Another area you will need to take into consideration is finding your views when creating the controller. If you plan on using the same view for all of them, then you shouldn't have to do anything different than the convention being used. If you plan on organizing your views also, then you will need to create your own ViewLocator also and assign it to the controller when creating it in your controller factory.

您需要考虑的另一个方面是在创建控制器时查找视图。如果您计划对所有这些视图使用相同的视图,那么您不必执行与使用的约定不同的任何操作。如果您还打算组织视图,那么您还需要创建自己的ViewLocator,并在控制器工厂中创建它时将其分配给控制器。

To get an idea of code, there are a few questions I have answered on SO that relate to this question, but this one is different to some degree, because the controller names will be the same. I included links for reference.

为了了解代码,我在SO上回答了一些与此问题相关的问题,但这个问题在某种程度上是不同的,因为控制器名称将是相同的。我包含了链接供参考。

Another route, but may require some compromises will be to use the new AcceptVerbs attribute. Check this question out for more details. I haven't played with this new functionality yet, but it could be another route.

另一条路线,但可能需要一些妥协,将使用新的AcceptVerbs属性。请查看此问题以获取更多详细信息。我还没有玩过这个新功能,但它可能是另一条路线。

#1


4  

I actually found it not even by searching, but by scanning through the ASP .NET forums in this question.

我实际上发现它甚至不是通过搜索,而是通过在这个问题中扫描ASP .NET论坛。

Using this you can have the controllers of the same name under any part of the namespace, so long as you qualify which routes belong to which namespaces (you can have multiple namespaces per routes if you need be!)

使用此命令,您可以在命名空间的任何部分下具有相同名称的控制器,只要您确定哪些路由属于哪些命名空间(如果需要,您可以为每个路由设置多个命名空间!)

But from here, you can put in a directory under your controller, so if your controller was "MyWebShop.Controllers", you'd put a directory of "Shop1" and the namespace would be "MyWebShop.Controllers.Shop1"

但是从这里开始,您可以放入控制器下的目录,因此如果您的控制器是“MyWebShop.Controllers”,您将放置一个“Shop1”目录,命名空间将为“MyWebShop.Controllers.Shop1”

Then this works:

然后这工作:

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

        var shop1namespace = new RouteValueDictionary();
        shop1namespace.Add("namespaces", new HashSet<string>(new string[] 
        { 
            "MyWebShop.Controllers.Shop1"
        }));

        routes.Add("Shop1", new Route("Shop1/{controller}/{action}/{id}", new MvcRouteHandler())
        {
            Defaults = new RouteValueDictionary(new
            {
                action = "Index",
                id = (string)null
            }),
            DataTokens = shop1namespace
        });

        var shop2namespace = new RouteValueDictionary();
        shop2namespace.Add("namespaces", new HashSet<string>(new string[] 
        { 
            "MyWebShop.Controllers.Shop2"
        }));

        routes.Add("Shop2", new Route("Shop2/{controller}/{action}/{id}", new MvcRouteHandler())
        {
            Defaults = new RouteValueDictionary(new
            {
                action = "Index",
                id = (string)null
            }),
            DataTokens = shop2namespace
        });

        var defaultnamespace = new RouteValueDictionary();
        defaultnamespace.Add("namespaces", new HashSet<string>(new string[] 
        { 
            "MyWebShop.Controllers"
        }));

        routes.Add("Default", new Route("{controller}/{action}/{id}", new MvcRouteHandler())
        {
            Defaults = new RouteValueDictionary(new { controller = "Home", action = "Index", id = "" }),
            DataTokens = defaultnamespace            
        });
    }

The only other thing is that it will reference a view still in the base directory, so if you put the view into directories to match, you will have to put the view name in when you return it inside the controller.

唯一的另一件事是它将引用仍在基本目录中的视图,因此如果将视图放入要匹配的目录中,则必须在将其返回到控制器内时将视图名称放入。

#2


1  

The best way to do this without any compromises would be to implement your own ControllerFactory by inheriting off of IControllerFactory. The CreateController method that you will implement handles creating the controller instance to handle the request by the RouteHandler and the ControllerActionInvoker. The convention is to use the name of the controller, when creating it, therefore you will need to override this functionality. This will be where you put your custom logic for creating the controller based on the route since you will have multiple controllers with the same name, but in different folders. Then you will need to register your custom controller factory in the application startup, just like your routes.

在没有任何妥协的情况下执行此操作的最佳方法是通过继承IControllerFactory来实现您自己的ControllerFactory。您将实现的CreateController方法处理创建控制器实例以处理RouteHandler和ControllerActionInvoker的请求。惯例是在创建控件时使用控制器的名称,因此您需要覆盖此功能。这将是您根据路径创建控制器的自定义逻辑的位置,因为您将具有多个具有相同名称但位于不同文件夹中的控制器。然后,您需要在应用程序启动时注册自定义控制器工厂,就像您的路线一样。

Another area you will need to take into consideration is finding your views when creating the controller. If you plan on using the same view for all of them, then you shouldn't have to do anything different than the convention being used. If you plan on organizing your views also, then you will need to create your own ViewLocator also and assign it to the controller when creating it in your controller factory.

您需要考虑的另一个方面是在创建控制器时查找视图。如果您计划对所有这些视图使用相同的视图,那么您不必执行与使用的约定不同的任何操作。如果您还打算组织视图,那么您还需要创建自己的ViewLocator,并在控制器工厂中创建它时将其分配给控制器。

To get an idea of code, there are a few questions I have answered on SO that relate to this question, but this one is different to some degree, because the controller names will be the same. I included links for reference.

为了了解代码,我在SO上回答了一些与此问题相关的问题,但这个问题在某种程度上是不同的,因为控制器名称将是相同的。我包含了链接供参考。

Another route, but may require some compromises will be to use the new AcceptVerbs attribute. Check this question out for more details. I haven't played with this new functionality yet, but it could be another route.

另一条路线,但可能需要一些妥协,将使用新的AcceptVerbs属性。请查看此问题以获取更多详细信息。我还没有玩过这个新功能,但它可能是另一条路线。