Есть ли способ включить идентификатор фрагмента при использовании Asp.Net MVC ActionLink, RedirectToAction и т. Д.?

Я хочу, чтобы некоторые ссылки включали идентификатор фрагмента. Как некоторые из URL-адресов на этом сайте:

Отладка: IE6 + SSL + AJAX + форма сообщения = ошибка 404 # 5626

Есть ли способ сделать это с помощью любого из встроенных методов MVC? Или мне придется использовать собственные помощники HTML?

Ответов (7)

Решение

Мы планируем включить поддержку этого в наш следующий выпуск.

Короткий ответ: нет. В ASP.NET MVC Preview 3 нет первоклассного способа включения привязки в ссылку действия. В отличие от url_for: anchor в Rails, UrlHelper.GenerateUrl (и ActionLink, RedirectToAction и т. Д., Которые его используют) не имеют волшебного имени свойства, которое позволяет вам кодировать привязку.

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

Как ни странно, вы можете просто включить якорь в маршрут и указать значение в хэше параметров:

routes.MapRoute("WithTarget", "{controller}/{action}/{id}#{target}");
...
<%= Html.ActionLink("Home", "Index", new { target = "foo" })%>

Это сгенерирует URL-адрес вида / Home / Index / # foo. К сожалению, это плохо сочетается с параметрами URL-адреса, которые появляются в конце URL-адреса. Таким образом, этот прием работает только в действительно простых обстоятельствах, когда все ваши параметры отображаются как компоненты пути URL.

@ Доминик,

Я почти уверен, что добавление этого в маршрут вызовет проблемы с маршрутизацией.

@ Рики,

Пока MVC не будет поддерживать это, вы можете быть немного более «олдскульными» в отношении того, как вы строите свои маршруты. Например, вы можете конвертировать:

<%= Html.ActionLink("Home", "Index") %>

в:

<a href='<%= Url.Action("Index") %>#2345'>Home</a>

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

Как писал Брэд Уилсон, вы можете создать свою собственную ссылку в своих представлениях, просто объединив строки. Но чтобы добавить имя фрагмента к перенаправлению, сгенерированному с помощью RedirectToAction (или аналогичного), вам понадобится что-то вроде этого:

public class RedirectToRouteResultEx : RedirectToRouteResult {

    public RedirectToRouteResultEx(RouteValueDictionary values)
        : base(values) {
    }

    public RedirectToRouteResultEx(string routeName, RouteValueDictionary values)
        : base(routeName, values) {
    }

    public override void ExecuteResult(ControllerContext context) {
        var destination = new StringBuilder();

        var helper = new UrlHelper(context.RequestContext);
        destination.Append(helper.RouteUrl(RouteName, RouteValues));

        //Add href fragment if set
        if (!string.IsNullOrEmpty(Fragment)) {
            destination.AppendFormat("#{0}", Fragment);
        }

        context.HttpContext.Response.Redirect(destination.ToString(), false);
    }

    public string Fragment { get; set; }
}

public static class RedirectToRouteResultExtensions {
    public static RedirectToRouteResultEx AddFragment(this RedirectToRouteResult result, string fragment) {
        return new RedirectToRouteResultEx(result.RouteName, result.RouteValues) {
            Fragment = fragment
        };
    }
}

А затем в своем контроллере вы должны вызвать:

return RedirectToAction("MyAction", "MyController")
       .AddFragment("fragment-name");

Это должно правильно сгенерировать URL-адрес.

Это решение на стороне клиента, но если у вас есть jquery, вы можете сделать что-то вроде этого.

<script language="javascript" type="text/javascript">
    $(function () {
        $('div.imageHolder > a').each(function () {
            $(this).attr('href', $(this).attr('href') + '#tab-works');
        });
    });
</script>

В MVC3 (и, возможно, раньше я не проверял) вы можете использовать UrlHelper.GenerateUrl, передав параметр фрагмента. Вот вспомогательный метод, который я использую для обертывания функциональности.

public static string Action(this UrlHelper url, string actionName, string controllerName, string fragment, object routeValues)
{
    return UrlHelper.GenerateUrl(
        routeName: null,
        actionName: actionName,
        controllerName: controllerName,
        routeValues: new System.Web.Routing.RouteValueDictionary(routeValues),
        fragment: fragment,
        protocol: null,
        hostName: null,
        routeCollection: url.RouteCollection,
        requestContext: url.RequestContext,
        includeImplicitMvcValues: true /*helps fill in the nulls above*/
    );
}

Идентификаторы фрагментов поддерживаются в MVC 5. См. ActionLink Перегрузки на https://msdn.microsoft.com/en-us/library/dd460522(v=vs.118).aspx и https://msdn.microsoft.com/ en-us / library / dd492938 (v = vs.118) .aspx .