Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Разработка под ASP.NET > ASP.NET MVC 3 - ссылки в частичном представлении


Автор: korob2001 20.5.2015, 13:52
Всем привет!

Столкнулся с такой проблемой. На сайте нужно сделать меню переключения с одного языка на другой. Сделал частичное представление:
Код

<ul id="lang-menu">
    <li>
        <div style="background-image: url(/Content/icons/flags/@{@Model.CurrentLanguage.Code}.png)">@Model.CurrentLanguage.Name</div>
        <ul>
            @foreach (ERider.Domain.Entities.Language lang in Model.Languages)
            {
                <li>@Html.ActionLink(lang.Name, null, null, new { lang = lang.Code }, new { style="background-image: url(/Content/icons/flags/" + lang.Code + ".png)" })</li>
            }
        </ul>
    </li>
</ul>

Подключаю его в мастер странице:
Код

@Html.Action("LangMenu", "Master")

Меню выводится, но ссылки указывают на контроллер Master и его действие LangMenu. Вот код этого действия:
Код

[ChildActionOnly]
public ActionResult LangMenu(string controller, string action, string lang)
{
     Language current = langRepository.GetLanguageByCode(lang);
     LangMenuViewModel model = new LangMenuViewModel()
     {
          CurrentLanguage = current,
          DefaultLanguage = langRepository.DefaultLanguage,
          Languages = langRepository.Languages.Where(p => !p.Code.Equals(current.Code)),
          ControllerName = controller,
          ActionName = action
      };
     return View(model);
}

Вобщем мне нужно узнать текущий контроллер и действие, но не частичного представления и не мастер страницы, а именно той страницы где пользователь выбрал другой язык, что бы после смены языка он остался на той же странице.

Заранее благодарен за любую информацию.

Автор: Cheloveck 20.5.2015, 17:49
Укажи в параметрах имя контроллера и экшена вместо null.

Код

@Html.ActionLink(lang.Name, "ACTION_NAME", "CONTROLLER_NAME", new { lang = lang.Code }, new { style="background-image: url(/Content/icons/flags/" + lang.Code + ".png)" })


Добавлено через 2 минуты и 54 секунды
https://msdn.microsoft.com/en-us/library/dd504972%28v=vs.118%29.aspx

Автор: korob2001 20.5.2015, 20:00
Меню расположено в мастер странице, т.е. язык можно выбрать с любой страницы. Думаю не логично будет перебрасывать пользователя на главную, либо какую-то другую страницу, если он просто решил поменять язык.
Мне нужно как-то определить текущий контроллер и действие, если я указываю null, то определяется контроллер и действие частичного представления. [ChildActionOnly].

Например пользователь зашёл на главную страницу сайта:
Код

/Home/Index


Меню для выбора языка должны содержать такие ссылки:
Код

/En/Home/Index
/Fr/Home/Index
/De/Home/Index
/Ru/Home/Index


Если он например зашёл на страницу:
Код

/Product/List


Меню выбора языка должно содержать такие ссылки:
Код

/En/Product/List
/Fr/Product/List
/De/Product/List
/Ru/Product/List

Думаю понятно, что жёстко вписать имя контроллера и действия не получится, так как в каждом View ссылки будут меняться. Мне нужно как-то передать по цепочке View -> MasterPage -> PartialView  текущий контроллер и действие.

Автор: Cheloveck 20.5.2015, 20:23
Вообще, с такими линками тяжело будет жить. На каждый чих кастомные решения придётся писать. Я бы посоветовал передавать язык в query string
Код

/Product/List?lang=de


Хотя, если такой вот раут как следует замапить, то получится то, что надо

Код

routes.MapRouteWithPageName(
    "product-list",
    null,
    "{lang}/{controller}/{action}",
     new { controller = "Product", action = "List", lang = UrlParameter.Optional }
 );


Не уверен, что это заработает, негде проверить.

Автор: korob2001 21.5.2015, 11:18
Ну с роутами вроде проблем нет. Не могу сгенерировать правильную ссылку. Насколько я понимаю, мне нужно каким-то образом передать из мастер страницы, имя текущего контроллера и экшена, в метод:
Код

[ChildActionOnly] 
public ActionResult LangMenu(string controller, string action, string lang) 

     Language current = langRepository.GetLanguageByCode(lang); 
     LangMenuViewModel model = new LangMenuViewModel() 
     { 
          CurrentLanguage = current, 
          DefaultLanguage = langRepository.DefaultLanguage, 
          Languages = langRepository.Languages.Where(p => !p.Code.Equals(current.Code)), 
          ControllerName = controller, 
          ActionName = action 
      }; 
     return View(model); 


Т.е. вызов дочернего представления, в мастер странице, должен выглядеть как-то так:
Код

@Html.Action("LangMenu", "Master", Url.GetController(), Url.GetAction());

Автор: Cheloveck 21.5.2015, 11:22
Код

string controllerName = ViewContext.RouteData.GetRequiredString("controller");
string actionName = ViewContext.RouteData.GetRequiredString("action");

Автор: korob2001 21.5.2015, 11:24
Да и сигнатура метода должна измениться на примерно такую:
Код

[ChildActionOnly]  
public ActionResult LangMenu(string controller, string action, string parrentController, string parrentAction) {

Автор: Cheloveck 21.5.2015, 11:31
Я бы просто добавил во все экшн-методы параметр lang и таскал бы его по всем вьюхам. Тогда все экшены будут примерно такого вида

Код

ActionResult Details(Guid id, string lang) {
    var model = entityFacade.GetModelForLang(id, lang); // Здесь будут дёргаться локализованные данные
    return View(model); 
}


Добавлено через 1 минуту и 13 секунд
Соответсвенно из меню будет зваться тот же экшн-метод, что отрендерил текущую вьюху, только с другим lang. А потом запихнёшь этот lang во все линки и формы.

Автор: korob2001 21.5.2015, 14:39
Цитата

Я бы просто добавил во все экшн-методы параметр lang и таскал бы его по всем вьюхам. Тогда все экшены будут примерно такого вида

да язык, будет сохраняться в куках, по сути это меню нужно будет только для того, что бы перезаписать куки.

Добавил 2 строки в начале метода:
Код

[ChildActionOnly]
        public ActionResult LangMenu(string controller, string action, string lang)
        {
            if (controller == "Master") controller = "";
            if (action == "LangMenu") action = "";
            
            Language current = langRepository.GetLanguageByCode(lang);
            LangMenuViewModel model = new LangMenuViewModel()
            {
                CurrentLanguage = current,
                DefaultLanguage = langRepository.DefaultLanguage,
                Languages = langRepository.Languages.Where(p => !p.Code.Equals(current.Code)),
                ControllerName = controller,
                ActionName = action
            };
            return View(model);
        }

и всё заработало.  smile 

Cheloveck ОГРОМНОЕ СПАСИБО ЗА ПОМОЩЬ

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)