Question

I'm working on a multi-language ASP.NET MVC site, and I need some help setting the language in the main action from a partial view.

My default route is declared as:

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

In my _Layout.cshtml, I've declared a partial reference as:

@Html.Partial("_LanguagePartial")

This Partial invokes an Action in the Language Controller:

@Html.Action("Index","Language")

This controller action just pumps the released languages to the view:

public class LanguageController : BaseController
{
    //
    // GET: /Language/
    public PartialViewResult Index()
    {
        List<Language> languages = new List<Language>();
        foreach (Language language in Global.Data.Languages.Values)
        {
            if (language.IsReleased)
                languages.Add(language);
        }
        return PartialView(languages);
    }

    public ActionResult SelectLanguage(string code)
    {
        //I tried to change the route value here, but this only affects the route to this action
        var routeDataDict = HttpContext.Request.RequestContext.RouteData.Values;
        routeDataDict["language"] = code;
        return RedirectToRoute(routeDataDict);
    }
}

The actual view that is shown in the partial, looks like this:

<div class="float-center">
<table><tr>
@foreach (var language in Model) {
    <td>
    <a href="@Url.Action("SelectLanguage", new { code = language.CultureCode })">
        <!--The css for the correct sprite is generated by language.Icon.ToString()
            The result will look like "background: url("/Images/Icons.png") -0px -100px; display: block; width: 32px; height: 20px; text-indent: -9999px;"-->
        <img alt="" src="" style="@Url.Content(@language.Icon.ToString());border=1" />
    </a>
    </td>
}
</tr></table>

Now this partial is rendered in every page of the site, like it should, but when I'm for example on mydomain/en/SomeController/SomeAction and I click on let's say the German icon, it should take me to mydomain/de/SomeController/SomeAction.

Off course the action and controller are not fixed.

Any ideas on how I can perform such an action? Maybe I've implemented the partial wrong and I'll be able to access the route if I implement it differently.

EDIT: With the help of meilke's answer, I've made following edit to the Language controller:

public ActionResult SelectLanguage(string code)
    {
        string url = ReplaceLanguageCode(Request.UrlReferrer.ToString(), code);
        return Redirect(url);
    }

    private string ReplaceLanguageCode(string url, string code)
    {
        Language language = GetLanguage(url);
        if (language == null)
        {
            //No Language is set in the url e.g. http://mydomain/
            string domain = Request.Url.AbsoluteUri.ToString().Replace(Request.Url.PathAndQuery, "");
            return url.Replace(domain, domain + "/" + code);
        }
        else
            //A Language was already set in the url e.g. http://mydomain/en/
            return url.Replace("/" + language.CultureCode + "/", "/" + code + "/");
    }

    private Language GetLanguage(string url)
    {
        //Loop the apps languages to see if one is set in the url
        foreach (Language language in Global.Data.Languages.Values)
        {
            if (url.ToLower().Contains("/" + language.CultureCode + "/"))
                return language;
        }
        return null;
    }

The SetLanguage action is changed to use the UrlReferrer as stated by meilke's answer. I also added ReplaceLanguageCode to create the new url and GetLanguage to get the language if the original url contains one.

Was it helpful?

Solution

Have a general controller which is regardless of the current action or current controller and place the SelectLanguage in there. Then make use of Request.UrlReferrer (more information) to get you back to where you came from (now using the correct language):

public ActionResult SelectLanguage(string code)
{
  // set language here

  return Redirect(Request.UrlReferrer.ToString());    
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top