Реализуйте расширение HtmlHelper, которое использует систему маршрутизации - PullRequest
0 голосов
/ 07 сентября 2018

Я пытаюсь реализовать свое собственное расширение для HtmlHelper, которое будет выводить ссылку аналогично ActionLink.

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

Мое приложение сосредоточено вокруг организаций. Один пользователь может создать организацию, а организация может иметь несколько местоположений. Основное действие происходит в текущем местоположении. Я считаю, что организация является арендатором в моем приложении, и идентификатор организации отправляется через URL.

Вот конфигурация маршрута для вышеупомянутого:

routes.MapRoute(
    name: "Tenant",
    url: "Tenants/{tenantId}/{action}",
    defaults: new
    {
        controller = "Organizations",
        action = "Dashboard",
        id = UrlParameter.Optional
    }
);

routes.MapRoute(
    name: "TenantLocation",
    url: "Tenants/{tenantId}/Locations/{locationId}/{controller}/{action}/{id}",
    defaults: new
    {
        controller = "Dashboard",
        action = "Index",
        id = UrlParameter.Optional
    }
);

Для маршрута "Арендатор" контроллером всегда являются Организации. Эта часть приложения заботится об административных действиях в отношении организации в целом. Здесь контекст содержит идентификатор арендатора.

Для маршрута "TenantLocation" контекст перемещается внутри местоположения, поэтому контекст содержит идентификатор арендатора и идентификатор местоположения.

Теперь я хотел бы создать два метода расширения для HtmlHelper с именами TenantActionLink и TenantLocationActionLink для генерации таких ссылок, как:

/Tenants/150/Dashboard

или

/Tenants/150/Locations/300/Team/Edit/1000

Часть "/ Tenants / 150 / Locations / 300 /" может рассматриваться как префикс, добавляемый к URL-адресу, при этом идентификаторы извлекаются с помощью ActionFilterAttribute и сохраняются как свойства в классе BaseController.

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

Какой-нибудь совет, как справиться с этим? Я использую ASP.NET MVC 5 и .NET Framework 4.6.1

Спасибо.


Обновление, чтобы ответить на вопросы Стивена Мюке :

Что вы пробовали до сих пор?

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

public static MvcHtmlString TenantLocationActionLink(this HtmlHelper helper,
    int tenandId,
    int locationId,
    string linkText,
    string actionName,
    string controllerName,
    object htmlAttributes = null)
{
    var url = $"/Tenants/{tenandId}/Locations/{locationId}/{controllerName}/{actionName}";

    var tagBuilder = new TagBuilder("a");
    tagBuilder.InnerHtml = linkText;
    tagBuilder.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    tagBuilder.MergeAttribute("href", url);

    return new MvcHtmlString(tagBuilder.ToString(TagRenderMode.Normal));
}

а какие у вас проблемы?

Я не могу понять, как обрабатывать значения маршрута. Моя реализация каким-то образом отстранена от более гибкой реализации ActionLink, тем более что она не учитывает значения маршрута. Как мне справиться с ситуациями, когда конфигурация моего маршрута станет более сложной?

И что вы ожидаете, что ваш метод расширения сделает это встроенный ActionLink () или RouteLink () нет?

Предварительно добавьте идентификаторы арендатора и местоположения, как описано выше. Как я могу использовать ActionLink () или RouteLink () для достижения этой цели?

1 Ответ

0 голосов
/ 07 сентября 2018

Уже есть метод расширения RouteLink(), который вы можете использовать для этого. Вы передаете ему текст ссылки и имя определения маршрута, а также объект (или RouteValueDictionary) для параметров, и он сгенерирует правильный атрибут href. В вашем случае для Tenant маршрута

@Html.RouteLink("...", "Tenant", new { tenantId = 150, action = "Dashboard" })

генерирует .../Tenants/150/Dashboard,

и для TenantLocation

@Html.RouteLink("...", "TenantLocation", new { tenantId = 150, locationId = 300, controller = "Team", action = "Edit", id = 1000 })

генерирует ../Tenants/150/Locations/300/Team/Edit/1000

...