W projekcie ASP MVC 3 chcę włączyć przełączanie języków.

Trasowanie definiuje się w następujący sposób:

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

        routes.MapRoute(
             "DefaultWithLanguage", // Route name
             "{language}/{controller}/{id}/{slug}", // URL with parameters
             new { language = "en", controller = "Front", action = "Details", id = UrlParameter.Optional, slug = UrlParameter.Optional } // Parameter defaults                 
         );

        routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );

Próba przełączenia języków (w _Layout.cshtml) działa tak:

<li>@Html.ActionLink("Spanish", ViewContext.RouteData.Values["action"].ToString(), ViewContext.RouteData.Values["controller"].ToString(), new { language = "es" })</li>    

Zamiast uzyskiwać adres URL podobny do poniższego (po wybraniu języka hiszpańskiego)

.../es/ControllerName/ActionName

Dostaję to:

.../ControllerName/ActionName?Length=11

Jeśli ustawię ActionLink na następujący (zwróć uwagę na ostatni parametr zerowy):

<li>@Html.ActionLink("Spanish", ViewContext.RouteData.Values["action"].ToString(), ViewContext.RouteData.Values["controller"].ToString(), new { language = "es" }, null)</li>

Rozumiem:

 .../ControllerName/ActionName?language=es

Czego mi brakuje? Z góry dziękuję!

1
Savvas Sopiadis 19 luty 2012, 13:28

2 odpowiedzi

Najlepsza odpowiedź

Wystąpiły pewne problemy z rejestracją Twoich tras DefaultWithLanguage rejestracją tras. Nie pozwala na określenie {action}. Oznacza to, że ta trasa będzie pasować tylko do akcji Details (ponieważ określiłeś ją w wartościach domyślnych). Innym problemem jest to, że ustawiłeś parametr {id} jako opcjonalny. Ale to niemożliwe. Tylko ostatni parametr trasy może być opcjonalny. W Twoim przypadku następuje po nim parametr {slug}.

Tak więc jedna możliwość jest następująca:

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

    routes.MapRoute(
        "DefaultWithLanguage",
        "{language}/{controller}/{action}/{id}",
        new 
        { 
            language = "en", 
            controller = "Front", 
            action = "Details", 
            id = UrlParameter.Optional 
        }
    );
}

I wtedy:

@Html.ActionLink(
    "Spanish", 
    ViewContext.RouteData.GetRequiredString("action"), 
    ViewContext.RouteData.GetRequiredString("controller"),
    new { language = "es" },
    null
)

Jeśli chcesz dodać parametr {slug}, Twój {id} nie może być już opcjonalny:

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

    routes.MapRoute(
        "DefaultWithLanguage",
        "{language}/{controller}/{action}/{id}/{slug}",
        new 
        { 
            language = "en", 
            controller = "Front", 
            action = "Details", 
            slug = UrlParameter.Optional 
        }
    );
}

I wtedy:

@Html.ActionLink(
    "Spanish", 
    ViewContext.RouteData.GetRequiredString("action"), 
    ViewContext.RouteData.GetRequiredString("controller"),
    new { 
        language = "es", 
        id = ViewContext.RouteData.GetRequiredString("id") 
    },
    null
)
1
Darin Dimitrov 19 luty 2012, 14:06

To jest kontynuacja odpowiedzi Darina.

Chcę mieć takie trasy:

.../en/ControllerName/Id
.../en/ControllerName/Id/Slug
.../en/ControllerName

Ta ostatnia trasa powoduje problem (patrz odpowiedź Darina). „Hakowanie”, aby nadal uzyskiwać te trasy, polega na zdefiniowaniu również innej trasy (druga nazwana DefaultWithLanguageWithoutId) :

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

            routes.MapRoute(
                 "DefaultWithLanguage", // Route name
                 "{language}/{controller}/{id}/{slug}", // URL with parameters
                 new { language = "en", controller = "Front", action = "Details", id = UrlParameter.Optional, slug = UrlParameter.Optional } // Parameter defaults                                                   
             );

            routes.MapRoute(
                "DefaultWithLanguageWithoutId", // Route name
                "{language}/{controller}", // URL with parameters
                new { language = "en", controller = "Front", action = "Details"} // Parameter defaults                 

            );

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );
        }

Powoduje to dostosowanie kodu na stronie wzorcowej do następującego

    <li>@Html.ActionLink("Deutsch", ViewContext.RouteData.Values["action"].ToString()
, ViewContext.RouteData.Values["controller"].ToString(), new { language = "de"
, id = ViewContext.RouteData.Values["id"]!=null ? ViewContext.RouteData.Values["id"].ToString():null }, null)</li>
    <li>@Html.ActionLink("English", ViewContext.RouteData.Values["action"].ToString()
, ViewContext.RouteData.Values["controller"].ToString(), new { language = "en"
, id = ViewContext.RouteData.Values["id"] != null ? ViewContext.RouteData.Values["id"].ToString() : null }, null)</li>  

Działa idealnie!

Jedyną „wadą” jest to, że w widoku jest zaangażowany jakiś kod (chciałbym tego uniknąć), ale myślę, że warto, ponieważ jest to bardzo proste!

0
Savvas Sopiadis 20 luty 2012, 13:55