MVC Futures со строгой типизацией RenderAction с областями и повторяющимися именами контроллеров - PullRequest
2 голосов
/ 06 июля 2011

Я пытаюсь использовать Html.RenderAction в строго типизированном виде из библиотеки MVC Futures

У меня есть действие Navigation на моем основном HomeController (area = ""), которое я пытаюсь выполнитьзвонок с моего Site.Master

<% Html.RenderAction<HomeController>(x=>x.Navigation()); %>

Это прекрасно работало до тех пор, пока я не добавил еще один HomeController в мою переносимую область администратора.Затем я обнаружил следующую ошибку:

Найдено несколько типов, соответствующих контроллеру с именем «Home».Это может произойти, если маршрут, обслуживающий этот запрос, не указывает пространства имен для поиска контроллера, соответствующего запросу.В этом случае зарегистрируйте этот маршрут, вызвав перегрузку метода «MapRoute», который принимает параметр «пространства имен».

В запросе «Home» обнаружены следующие подходящие контроллеры: Areas.Admin.Controllers.HomeController Web.Controllers.HomeController

Мне удалось решить эту проблему с помощью следующего не типизированного mvccontrib метода RenderAction.Я бы предпочел, чтобы этот метод не был строго типизирован на странице, есть ли способ заставить методы mvccontrib принимать область, или чтобы они знали, как генерировать область на основе маршрутов или пространства имен указанного контроллера.

<% Html.RenderAction("Navigation", "Home", new { area = "" }); %>

Я уже добавил в свой файл global.asax.cs поддержку нескольких контроллеров с областью по умолчанию, как показано ниже, и я также убедился, что это правильное пространство имен для моих контроллеров.

_routeCollection.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "Web.Controllers" });

Ответы [ 2 ]

2 голосов
/ 08 июля 2011

Видимо, в настоящее время нет поддержки этого в проекте futures, или они изменили его начиная с Futures v1.0.Я использовал рефлектор для дизассемблирования библиотеки фьючерсов, нашел источник для метода RenderAction и изменил его, чтобы проанализировать область вне пространства имен контроллера и добавить ее в RouteValues ​​перед его обработкой.Я предполагаю, что мне, вероятно, придется сделать нечто подобное и для ActionLink, если я хочу, чтобы они вели себя одинаково.

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

public static void RenderAction<TController>(this HtmlHelper helper, Expression<Action<TController>> action) where TController : Controller
{
    var ctrlNamespace = typeof(TController).Namespace;

    int areaStart = ctrlNamespace.IndexOf(".Areas.");
    if (areaStart > -1) 
    {
        ctrlNamespace = ctrlNamespace.Substring(areaStart + 7);
        int areaEnd = ctrlNamespace.IndexOf(".");
        ctrlNamespace = ctrlNamespace.Substring(0, areaEnd);
    }
    else
    {
        ctrlNamespace = String.Empty; //default area
    }

    helper.ViewContext.RouteData.Values.Add("area", ctrlNamespace);

    RouteValueDictionary routeValuesFromExpression = ExpressionHelper.GetRouteValuesFromExpression<TController>(action);
    foreach (KeyValuePair<string, object> pair in helper.ViewContext.RouteData.Values)
    {
        if (!routeValuesFromExpression.ContainsKey(pair.Key))
        {
            routeValuesFromExpression.Add(pair.Key, pair.Value);
        }
    }

    helper.RenderRoute(routeValuesFromExpression);
}
0 голосов
/ 06 июля 2011

Для поддержки нескольких контроллеров в MVC вам необходимо добавить пространство имен в маршрут по умолчанию.

Подробнее см. В этом ответе: Вопрос 2627699

...