ASP.NET MVC 4路由我只是想不通 [英] ASP.NET MVC 4 Routing I just can't figure out

查看:113
本文介绍了ASP.NET MVC 4路由我只是想不通的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我工作在ASP.NET MVC 4一个项目,我在一个位与特定的路由亏损。我的项目有很多定制的路线了。

I'm working on a project in ASP.NET MVC 4 and I'm at a bit of a loss with a particular routing. I have a lot of custom routes already in the project.

我目前做了一堆控制器为站点(公开可见的部分)的前端能够做的事情,比如 abc.com/OurSeoFeatures ,获取路由到 / OurSeoFeatures /指数

I am currently making a bunch of controllers for the frontend of the site (publicly visible part) to be able to do thing like abc.com/OurSeoFeatures that gets routed to /OurSeoFeatures/Index

有没有办法做到这一点,这样上面会路线类似 /前端/ OurSeoFeature 和另一页将路线 /前端/ anotherpage ,也还有我的其他路线是否正确?在我看来,上述将达到默认路由,如果我把类似下面将正好赶上所有的请求,不会让我打别的了。

Is there any way to do this so that the above would route to something like /frontend/OurSeoFeature and another page would route to /frontend/anotherpage and also still have my other routes correctly? It seems to me that the above would hit the default route and if I put something like the following it would just catch all the request and would not let me hit anything else.

        routes.MapRoute(
            name: "ImpossibleRoute",
            url: "{action}/{id}",
            defaults: new { controller = "frontend", id = UrlParameter.Optional }
        );

我是不是坚持让一帮控制器?我真的不想做一个控制器像,把一堆动作那里,我不认为它很pretty。任何想法?

Am I just stuck with making a bunch of controllers? I really don't want to make one controller like page and put a bunch of actions there as I don't think its very pretty. Any Ideas?

推荐答案

为了做你问什么,你只需要添加一个路由约束:

In order to do what you're asking, you simply need to add a route constraint:

routes.MapRoute(
    name: "Frontend",
    url: "frontend/{controller}/{action}/{id}",
    defaults: new { controller = "OurSeoFeature", action = "Index", id = UrlParameter.Optional },
    constraints: new { controller = "OurSeoFeature|Products" }
);

此约束意味着路由只匹配名称控制器 OurSeoFeatureController 的ProductsController 。任何其他控制器将触发缺省路由。但是,这不能处理重定向这些控制器 /前端/...,如果这就是你以后。而是,变得有点更加复杂。

This constraint means the route will only match controllers with the names OurSeoFeatureController or ProductsController. Any other controller will trigger the default route. However, this wouldn't handle redirecting those controllers to /frontend/..., if that's what you're after. Instead, that gets a little more involved.

首先,你需要创建一个类实现 IRouteConstraint ,以供您想重定向到 /前端控制器名字/...。我们需要这个了,究其原因是因为我们需要访问在 ActionFilter ,我们不能这样做,如果我们提供一个正则表达式约束像<$这些名称C $ C>的限制,新的控制器{=OurSeoFeature |产品。因此,约束可能看起来像这样:

Firstly, you'll need to create a class that implements IRouteConstraint, in order to supply the controller names you want to redirect to /frontend/.... The reason we need this now, is because we'll need to access those names in an ActionFilter, and we can't do that if we supply a regex constraint like constraints: new { controller = "OurSeoFeature|Products" above. So, the constraint could look something like this:

public class FrontendControllerConstraint : IRouteConstraint
{
    public FrontendControllerConstraint()
    {
        this.ControllerNames = new List<string> { "OurSeoFeature", "Products" }; 
    }

    public bool Match(HttpContextBase httpContext, Route route,
        string parameterName, RouteValueDictionary values,
        RouteDirection routeDirection)
    {
        string value = values[parameterName].ToString();

        return ControllerNames.Contains(value, StringComparer.OrdinalIgnoreCase);
    }

    public List<string> ControllerNames { get; private set; }
}

接下来,动作过滤器可以是这样的:

Next up, the action filter could look like this:

public class RedirectToFrontendActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var controller = filterContext.RouteData.Values["controller"].ToString();
        var path = filterContext.HttpContext.Request.Url.AbsolutePath;
        var controllersToMatch = new FrontendControllerConstraint().ControllerNames;

        if (controllersToMatch.Contains(controller, StringComparer.OrdinalIgnoreCase)
            && path.IndexOf(pathPrefix, StringComparison.OrdinalIgnoreCase) == -1)
        {
            filterContext.Result =
                new RedirectToRouteResult(routeName, filterContext.RouteData.Values);
        }

        base.OnActionExecuting(filterContext);
    }

    private string routeName = "Frontend";
    private string pathPrefix = "Frontend";
}

现在,我们有那些到位,所有剩下的方法就是连接这一切。首先,约束在一个稍微不同的方式施加:

Now that we have those in place, all that's left is to wire it all up. Firstly, the constraint is applied in a slightly different way:

routes.MapRoute(
    name: "Frontend",
    url: "frontend/{controller}/{action}/{id}",
    defaults: new { controller = "OurSeoFeature", action = "Index", id = UrlParameter.Optional },
    constraints: new { controller = new FrontendControllerConstraint() }
);

最后,您需要将过滤器添加到 FilterConfig.cs

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
    filters.Add(new RedirectToFrontendActionFilter());
}

这里的一个警告,是因为我检查对 Request.Url.AbsolutePath ,你不能在包含单词的路径传递任何前端。所以一定要确保所有的控制器,操作和添加到路径路由值,不包含。原因是,我检查是否存在 /前端/ 的路径,以确保如果他们不匹配的控制器将只重定向到该航线已经在使用它。

One warning here is that because I'm checking against Request.Url.AbsolutePath, you cannot pass anything in the path that contains the word frontend. So make sure all controllers, actions and route values added to the path, do not contain that. The reason is that I'm checking for the existence of /frontend/ in the path, to ensure that the matched controllers will only redirect to that route if they they're not already using it.

有很多附加的东西,你可以与安装程序做的,但我不知道您的要求。因此,你应该把这个code简单地作为骨架上手,并确保测试它,你想要它做的事。

There are a lot of added things you could do with that setup, but I don't know your requirements. As such, you should treat this code simply as a skeleton to get started, making sure to test that it does what you want it to do.

我会放下一切上面有,以防万一有人发现有用的。为了解决你想要做什么,但是,我们需要不同的方法。再次,我们需要一些路由约束,但我看到这个工作的方式是抛在脑后你的想法,使前端的默认路由。像这样:

I'll leave everything above there, just in case someone finds that useful. To address what you'd like to do, however, we need a different approach. Again, we need some route constraints, but the way I see this working is to flip your idea on its head and make the frontend the default route. Like so:

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

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

与以前一样,我申请了一些限制,以获得正确的行为。特别是,对于这个约束

Just as before, I've applied some constraints to get the correct behaviour. In particular, for this constraint:

constraints: new { controller = "Home|Backend" }

如果你有很多的控制器不属于前端的一部分,它可能是一个想法落实 IRouteConstraint 来保持控制器的名字出现的列表。你甚至可以去尽可能派生所有从基本控制器后端控制器,所以你可以抓住所有的人都用在 IRouteConstraint 实施反射。事情是这样的:

if you have a lot of controllers that aren't part of the frontend, it might be an idea to implement IRouteConstraint to keep a list of the controller names there. You could even go as far as deriving all of your backend controllers from a base controller, so you can grab all of them with reflection in the IRouteConstraint implementation. Something like this:

public BackendController : Controller
{
    // 
}

然后:

public AdminController : BackendController
{
    //
}

约束:

public class BackendConstraint : IRouteConstraint
{
    // Get controller names based on types that
    // BackendController
}

这同样的想法也适用于获得 FrontendController 的动作名称为第二约束。你需要小心,这里的唯一的事情是,你不必具有相同的名称在 FrontendController ,因为它会匹配一个动作任何后端控制器错误的路线。

This same idea also applies to getting the action names of FrontendController for the second constraint. The only thing you need to be careful of here is that you don't have any backend controllers which have the same name as an action on your FrontendController, because it will match the wrong route.

这篇关于ASP.NET MVC 4路由我只是想不通的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆