Ссылки T4MVC для SEO

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

http://www.mydomain.com/{fooKey}/{barKey}/{barID}

==> приводит к BarController.Details(barID).

fooKey и barKey добавляются к ссылкам только в целях SEO. (поскольку bar является дочерним элементом foo, и мы хотим представить эту иерархию в URL-адресе)

До сих пор мы использовали

<% =Html.ActionLink(bar.Name, "Details", "Bar", new {barID = bar.ID, fooKey = bar.Foo.Key, barKey = bar.Key}, null)%>

И это привело бы нас к BarController.Details(barID), сохраняя при этом fooKey и barKey в URL-адресе.

Теперь, когда мы начали с T4MVC, мы попытались изменить его на

<% =Html.ActionLink(bar.Name, MVC.Bar.Details(bar.ID), null)%>

Поскольку barKey и fooKey не являются частью подписи действия Details, они больше не отображаются в URL-адресе.

Есть ли способ обойти это без добавления этих параметров в сигнатуру действия?


person Omer Rauchwerger    schedule 11.12.2009    source источник
comment
Как настроена ваша маршрутизация?   -  person PanJanek    schedule 11.12.2009
comment
Соответствующий маршрут настраивается следующим образом: route.Add(new LowercaseRoute(go/{fooKey}/{barKey}/{id}, new RouteValueDictionary(new {controller = Bar, action = Details}), new RouteValueDictionary(new {id = @\d+}), новый MvcRouteHandler())); Нижний регистрПуть отсюда — coderjournal.com/2008/03/force -mvc-route-url-нижний регистр   -  person Omer Rauchwerger    schedule 11.12.2009
comment
(Извините за ужасный отступ)   -  person Omer Rauchwerger    schedule 11.12.2009


Ответы (3)


Аналогичная вещь также появилась на форуме T4MVC (эта тема). Думаю, я продолжу и добавлю поддержку в T4MVC.

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

Вместо этого мы можем использовать гибкий подход, чтобы сделать это доступным везде без особых усилий. Идея состоит в том, что вы напишете:

<%= Html.ActionLink(
    bar.Name,
    MVC.Bar.Details(bar.ID)
        .AddRouteValues(new {fooKey = bar.Foo.Key, barKey = bar.Key}))%>

Или, если вам нужно было добавить только одно значение:

<%= Html.ActionLink(
    bar.Name,
    MVC.Bar.Details(bar.ID)
        .AddRouteValue("fooKey", bar.Foo.Key))%>

Вот как реализован AddRouteValues:

public static ActionResult AddRouteValues(this ActionResult result, object routeValues) {
    return result.AddRouteValues(new RouteValueDictionary(routeValues));
}

public static ActionResult AddRouteValues(this ActionResult result, RouteValueDictionary routeValues) {
    RouteValueDictionary currentRouteValues = result.GetRouteValueDictionary();

    // Add all the extra values
    foreach (var pair in routeValues) {
        currentRouteValues.Add(pair.Key, pair.Value);
    }

    return result;
}

public static ActionResult AddRouteValue(this ActionResult result, string name, object value) {
    RouteValueDictionary routeValues = result.GetRouteValueDictionary();
    routeValues.Add(name, value);
    return result;
}

Было бы здорово, если бы вы попробовали это и дали мне знать, как это работает для вас.

спасибо, Дэвид

person David Ebbo    schedule 13.12.2009
comment
Прекрасно работает и очень элегантное решение. Спасибо, Дэвид! - person Omer Rauchwerger; 14.12.2009

Посмотрите сгенерированный код внутри T4MVC.cs. Существуют вспомогательные расширения html, которые принимают ActionLink. Вам придется написать перегрузку, которая берет другой набор значений маршрута и объединяет их с ActionResult.GetRouteValueDictionary().

    public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, ActionResult result, IDictionary<string, object> htmlAttributes) {
        return htmlHelper.RouteLink(linkText, result.GetRouteValueDictionary(), htmlAttributes);
    }
person John Farrell    schedule 11.12.2009

Спасибо jfar!

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

public static MvcHtmlString ActionLink<T>(this HtmlHelper<T> htmlHelper, string linkText, ActionResult result,
                                              object extraRouteValues, object htmlAttributes)
    {
        RouteValueDictionary completeRouteValues = result.GetRouteValueDictionary();
        RouteValueDictionary extraRouteValueDictionary = new RouteValueDictionary(extraRouteValues);
        foreach (KeyValuePair<string, object> foo in extraRouteValueDictionary)
        {
            completeRouteValues.Add(foo.Key, foo.Value);
        }

        Dictionary<string, object> htmlAttributesDictionary = htmlAttributes != null ? htmlAttributes.GetType().GetProperties().ToDictionary(p => p.Name, p => p.GetValue(htmlAttributes, null)) : null;

        return htmlHelper.RouteLink(linkText, completeRouteValues, htmlAttributesDictionary);
    }
person Omer Rauchwerger    schedule 12.12.2009
comment
вы должны отвечать, используя комментарии, а не новый ответ - person awrigley; 03.04.2012
comment
@Omer Rauchwerger: Если вы решили свою проблему с помощью этого кода на основе ответа jfar, то вам следует принять ответ jfar, и лучшее место для публикации вашего рабочего кода - это редактирование ответа jfar, а не отдельный ответ. - person Vince Bowdren; 16.08.2016