Response.RedirectToRoute(RouteData.Values)重定向到Area控制器

Har*_*lyo 9 asp.net-mvc-routing asp.net-mvc-5.2

我正在尝试设置一个BaseController来处理文化作为url的一部分(基于ASP.NET MVC 5国际化).只要禁用我的区域注册,我的实现就可以正常工作.

当我的某个区域被注册时,如果我尝试输入错误/不支持的文化(http:// localhost:52639/zz /),我遇到请求URL的404错误:http:// localhost:52639/fr /测试/发布.

我检查了我的路线是否正确注册.

如果我在禁用区域注册时执行相同操作,则在键入以下URL时基本控制器和路由的行为正确:http:// localhost:52639/zz /我被重定向到http:// localhost:52639/fr /(默认文化).

这些是我的路线:

public static void RegisterRoutes(RouteCollection routes)
    {
        var namespaces = new[]{typeof(PostController).Namespace};

        routes.IgnoreRoute("favicon.ico");
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute("PostToHack", "{culture}/Post/{idAndSlug}", new { culture = "", Controller = "Post", Action = "Show" }, namespaces);
        routes.MapRoute("Post", "{culture}/Post/{id}-{slug}", new { culture = "", Controller = "Post", Action = "Show" }, namespaces);

        routes.MapRoute("TagToHack", "{culture}/Tag/{idAndSlug}", new { culture = "", Controller = "Post", Action = "Tag" }, namespaces);
        routes.MapRoute("Tag", "{culture}/Tag/{id}-{slug}", new { culture = "", Controller = "Post", Action = "Tag" }, namespaces);

        routes.MapRoute("Logout", "{culture}/Logout", new { culture = "", Controller = "Authentication", Action = "Logout" }, namespaces);
        routes.MapRoute("Login", "{culture}/Login", new { culture = "", Controller = "Authentication", Action = "Login" }, namespaces);

        //Error routes
        routes.MapRoute("Error404", "{culture}/errors/404", new { culture = "", Controller = "Errors", Action = "NotFound" }, namespaces);
        routes.MapRoute("Error500", "{culture}/errors/500", new { culture = "", Controller = "Errors", Action = "Error" }, namespaces);

        routes.MapRoute("Home", "{culture}", new { culture = "", Controller = "Post", Action = "Index"},namespaces);

        //Never to be called by user which is why it comes after MapRoute Home so it is always overwritten by it
        routes.MapRoute("Sidebar", "{culture}", new { culture = "", Controller = "Layout", Action = "Sidebar"},namespaces);//This is a "child-only" controller
        routes.MapRoute("NavigationBar", "{culture}", new { culture = "", Controller = "Layout", Action = "NavigationBar"},namespaces);//This is a "child-only" controller
Run Code Online (Sandbox Code Playgroud)

区域路线

 public override void RegisterArea(AreaRegistrationContext context)
    {
        var namespaces = new[] { typeof(PostsController).Namespace };

        context.MapRoute(
            "admin_default",
            "{culture}/admin/{controller}/{action}/{id}",
            new { culture = "", action = "Index", id = UrlParameter.Optional }, namespaces
            );
    }
Run Code Online (Sandbox Code Playgroud)

基础控制器:

 public class BaseController : Controller
{
    protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state)
    {
        var cultureName = RouteData.Values["culture"] as string;

        // Attempt to read the culture cookie from Request
        if (cultureName == null)
            cultureName = (Request.UserLanguages != null) && (Request.UserLanguages.Length > 0)
                ? Request.UserLanguages[0]
                : null; // obtain it from HTTP header AcceptLanguages

        // Validate culture name
        cultureName = CultureHelper.GetImplementedCulture(cultureName); // This is safe


        if (RouteData.Values["culture"] as string != cultureName)
        {
            // Force a valid culture in the URL
            RouteData.Values["culture"] = cultureName.ToLowerInvariant(); // lower case too

            // Redirect user
            Response.RedirectToRoute(RouteData.Values);
        }

        // Modify current thread's cultures            
        Thread.CurrentThread.CurrentCulture = new CultureInfo(cultureName);
        Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;

        return base.BeginExecuteCore(callback, state);
    }
}
Run Code Online (Sandbox Code Playgroud)

Har*_*lyo 0

经过更多挖掘后,我找到了适合我的解决方案。我的问题来自于我注册路线的顺序。我首先注册我的区域的路线:

protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        RouteConfig.RegisterRoutes(RouteTable.Routes);
    }
Run Code Online (Sandbox Code Playgroud)

我颠倒了顺序并确保我仅在以下时间后注册我的区域的路线:

protected void Application_Start()
    {
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        AreaRegistration.RegisterAllAreas();            
    }
Run Code Online (Sandbox Code Playgroud)