ASP.NET MVC `Html.ActionLink` между" Областями " - PullRequest
47 голосов
/ 25 марта 2011

Я добавил новую область в свой проект MVC3 и пытаюсь связать страницу _Layout с новой областью.Я добавил область с именем «Admin», в которой есть контроллер «Meets».

Я использовал дизайнер Visual Studio для добавления области, чтобы у нее был правильный класс регистрации области и т. Д., А файл global.asax былрегистрация всех областей.

Однако, когда я использую следующие 2 ссылки действия на странице в корне, я сталкиваюсь с несколькими проблемами:

@Html.ActionLink("Admin", "Index", "Meets", new { area = "Admin" }, null)
@Html.ActionLink("Admin", "Index", "Meets", new { area = "" }, null)

При нажатии на обе ссылки, яПереносится на контроллер Meets в области администрирования, где приложение затем выдает ошибку, говоря, что не может найти страницу индекса (даже если страница индекса присутствует в папке представлений в подкаталоге Area.

Href для 1-й ссылки выглядит так:

http://localhost/BCC/Meets?area=Admin

И Href для 2-й ссылки выглядит так:

http://localhost/BCC/Meets

Также, если я нажму на ссылку, которую я ожидаю создать:

http://localhost/BCC/Admin/Meets

Я просто получаю ресурс, не могу найти ошибку. Все очень сбивает с толку! Я надеюсь, что кто-то может помочь...

Ответы [ 6 ]

72 голосов
/ 25 марта 2011

Странно, действительно. Шаги, которые отлично работали для меня:

  1. Создание нового приложения ASP.NET MVC 3 с использованием шаблона Visual Studio по умолчанию
  2. Добавьте область с именем Admin с помощью дизайнера Visual Studio, щелкнув правой кнопкой мыши проект
  3. Добавить новый контроллер в ~/Areas/Admin/Controllers/MeetsController:

    public class MeetsController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    }
    
  4. Добавить соответствующий вид ~/Areas/Admin/Views/Meets/Index.cshtml

  5. В макете (~/Views/Shared/_Layout.cshtml) добавить ссылки:

    @Html.ActionLink("Admin", "Index", "Meets", new { area = "Admin" }, null)
    @Html.ActionLink("Admin", "Index", "Meets", new { area = "" }, null)
    
  6. Запустите приложение.

Визуализированный HTML для якорей:

<a href="/Admin/Meets">Admin</a>
<a href="/Meets">Admin</a>

Как и ожидалось, первая ссылка работает, а вторая - нет.

Так в чем же разница с вашей настройкой?

30 голосов
/ 21 января 2012

Другой вариант заключается в использовании RouteLink () вместо ActionLink (), который вообще обходит регистрации области:

Версия ActionLink:

Html.ActionLink("Log Off", "LogOff", "Account", new { area = "" }, null)

Версия RouteLink:

Html.RouteLink("Log Off", "Default", 
    new { action = "LogOff", controller = "Account" })

Вторым параметром является «Имя маршрута», которое зарегистрировано в Global.asax.cs и в различных подклассах «AreaRegistration».Чтобы использовать 'RouteLink' для связи между различными областями, вам нужно только указать правильное имя маршрута.

В следующем примере показано, как создать три ссылки на разные области из общей части, которая работает правильно независимо отв какой области я нахожусь (если есть):

@Html.RouteLink("Blog", "Blog_default", 
    new { action = "Index", controller = "Article" })
<br/>
@Html.RouteLink("Downloads", "Download_default", 
    new { action = "Index", controller = "Download" })
<br/>
@Html.RouteLink("About", "Default", 
    new { action = "Index", controller = "About" })

Удачного кодирования!

7 голосов
/ 25 марта 2011

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

В файле global.asax в моем приложении BCC была странная строка кода, которая необъяснимым образом появилась:

        public static void RegisterRoutes(RouteCollection routes)
        {
            // Problem here
            routes.Clear();

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

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

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }

Как вы можете видеть, где находится мой комментарий, в тот или иной момент я поместил вызов route.Clear () в начале RegisterRoutes, что означало, что после регистрации областей в Application_Start я сразу же очищал Я только что зарегистрировался.

Спасибо за помощь ... это в конечном итоге привело к моему спасению!

3 голосов
/ 25 марта 2011

Убедитесь, что ваш AdminAreaRegistration класс выглядит следующим образом:

public class AdminAreaRegistration : AreaRegistration
{
    public override string AreaName
    {
        get
        {
            return "Admin";
        }
    }

    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute(
            "Admin_default",
            "Admin/{controller}/{action}/{id}",
            new { action = "Index", id = UrlParameter.Optional }
        );
    }
}

и что у вас это есть в Global.asax.cs:

protected void Application_Start()
{
    ... // ViewEngine Registration
    AreaRegistration.RegisterAllAreas();
    ... // Other route registration
}
2 голосов
/ 10 сентября 2011

Я решил эту проблему, выполнив следующее.

В моем Global.asax.cs у меня есть

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" });
    }

    protected void Application_Start()
    {
        //Initialise IoC
        IoC.Initialise();

        AreaRegistration.RegisterAllAreas();
        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    }

В моем PublicAreaRegistration.cs (Public Area), у меня есть

public class PublicAreaRegistration : AreaRegistration
{
    public override string AreaName
    {
        get
        {
            return "Public";
        }
    }

    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute("Root", "", new { controller = "Home", action = "Index" });

        context.MapRoute(
            "Public_default",
            "Public/{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            , new[] { "<Project Namespace here>.Areas.Public.Controllers" }
        );
    }
}

В моем AuthAreaRegistration.cs (Область для ограниченного доступа) у меня есть

public class AuthAreaRegistration : AreaRegistration
{
    public override string AreaName
    {
        get
        {
            return "Auth";
        }
    }

    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute(
            "Auth_default",
            "Auth/{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

И, наконец, мои ссылки на моих * .cshtml страницах будут выглядеть как

1) @ Html.ActionLink («Log Off», «LogOff», new {area = «Public», controller = «Home»})

или

2) @ Html.ActionLink ("Область администратора", "Индекс", новый {area = "Auth", controller = "Home"})

Надеюсь, это сэкономит кому-то часы исследований! Кстати, я говорю о MVC3 здесь.

Kwex.

1 голос
/ 07 мая 2013

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

...