Как использовать MVC 3 @ Html.ActionLink внутри кода c # - PullRequest
15 голосов
/ 30 ноября 2011

Я хочу вызвать метод @ Html.ActionLink внутри функции ac #, чтобы вернуть строку со ссылкой на нее.

Примерно так:

string a = "Email is locked, click " + @Html.ActionLink("here to unlock.", "unlock") ;

Ответы [ 5 ]

8 голосов
/ 30 ноября 2011

Предполагая, что вы хотите выполнить это в своем контроллере, есть несколько прыжков, через которые можно прыгать.Вы должны создать экземпляры ViewDataDictionary и TempDataDictionary.Затем вам нужно взять ControllerContext и создать IView.Наконец, вы готовы создать свой HtmlHelper, используя все эти элементы (плюс ваш RouteCollection).

Как только вы все это сделали, вы можете использовать LinkExtensions.ActionLink для создания своей пользовательской ссылки.По вашему мнению, вам нужно будет использовать @Html.Raw() для отображения ваших ссылок, чтобы предотвратить их кодирование в HTML.Вот необходимый код:

var vdd = new ViewDataDictionary();
var tdd = new TempDataDictionary();
var controllerContext = this.ControllerContext;
var view = new RazorView(controllerContext, "/", "/", false, null);
var html = new HtmlHelper(new ViewContext(controllerContext, view, vdd, tdd, new StringWriter()),
     new ViewDataContainer(vdd), RouteTable.Routes);
var a = "Email is locked, click " + LinkExtensions.ActionLink(html, "here to unlock.", "unlock", "controller").ToString();

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

ОБНОВЛЕНИЕ

Чтобы обратиться к one.beat.consumer, мой первоначальный ответ был примеромо том, что возможно.Если разработчику необходимо повторно использовать эту технику, сложность может быть скрыта в статическом помощнике, например:

public static class ControllerHtml
{
    // this class from internal TemplateHelpers class in System.Web.Mvc namespace
    private class ViewDataContainer : IViewDataContainer
    {
        public ViewDataContainer(ViewDataDictionary viewData)
        {
            ViewData = viewData;
        }

        public ViewDataDictionary ViewData { get; set; }
    }

    private static HtmlHelper htmlHelper;

    public static HtmlHelper Html(Controller controller)
    {
        if (htmlHelper == null)
        {
            var vdd = new ViewDataDictionary();
            var tdd = new TempDataDictionary();
            var controllerContext = controller.ControllerContext;
            var view = new RazorView(controllerContext, "/", "/", false, null);
            htmlHelper = new HtmlHelper(new ViewContext(controllerContext, view, vdd, tdd, new StringWriter()),
                 new ViewDataContainer(vdd), RouteTable.Routes);
        }
        return htmlHelper;
    }

    public static HtmlHelper Html(Controller controller, object model)
    {
        if (htmlHelper == null || htmlHelper.ViewData.Model == null || !htmlHelper.ViewData.Model.Equals(model))
        {
            var vdd = new ViewDataDictionary();
            vdd.Model = model;
            var tdd = new TempDataDictionary();
            var controllerContext = controller.ControllerContext;
            var view = new RazorView(controllerContext, "/", "/", false, null);
            htmlHelper = new HtmlHelper(new ViewContext(controllerContext, view, vdd, tdd, new StringWriter()),
                 new ViewDataContainer(vdd), RouteTable.Routes);
        }
        return htmlHelper;
    }
}

Затем в контроллере он используется примерно так:

var a = "Email is locked, click " + 
    ControllerHtml.Html(this).ActionLink("here to unlock.", "unlock", "controller").ToString();

или что-то вроде этого:

var model = new MyModel();
var text = ControllerHtml.Html(this, model).EditorForModel();

Хотя использовать Url.Action проще, теперь он превращается в мощный инструмент для генерации любой разметки в контроллере с использованием всех HtmlHelpers (с полным Intellisense).

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

6 голосов
/ 30 ноября 2011

Вы можете создать метод расширения HtmlHelper:

public static string GetUnlockText(this HtmlHelper helper)
{
    string a = "Email is locked, click " + helper.ActionLink("here to unlock.", "unlock");
    return a;
}

или если вы хотите сгенерировать эту ссылку вне области страницы aspx, вам нужно создать ссылку на HtmlHelper, а затем сгенерировать. Я делаю это в UrlUtility статическом классе (я знаю, что люди ненавидят статические классы и слово Utility, но пытаются сосредоточиться). Перегрузка при необходимости:

public static string ActionLink(string linkText, string actionName, string controllerName)
{
    var httpContext = new HttpContextWrapper(System.Web.HttpContext.Current);
    var requestContext = new RequestContext(httpContext, new RouteData());
    var urlHelper = new UrlHelper(requestContext);

    return urlHelper.ActionLink(linkText, actionName, controllerName, null);
}

Тогда вы можете написать следующее, где пожелает ваше сердце:

string a = "Email is locked, click " + UrlUtility.ActionLink("here to unlock.", "unlock", "controller");
5 голосов
/ 30 ноября 2011

В этих других ответах есть пара плохих вещей ...

Ответ Акулы требует от вас перенести пространство имен LinkExtensions в C #, что не является неправильным, но нежелательным для меня.

Идея Хантера о создании помощника лучше, но все же написание вспомогательной функции для одного URL громоздко. Вы можете написать помощника, который поможет вам построить строки, которые принимают параметры, или вы можете просто сделать это по старинке:

var link = "Email is... click, <a href=\"" + Url.Action("action") + "\"> to unlock.</a>";

@ counsellorben

я не вижу причин для сложности; пользователь хочет только отобразить маршрутизацию Action в жесткую строку, содержащую тег привязки. Более того, ActionLink () в жестко написанной каскадной строке ничего не покупает и заставляет разработчика использовать LinkExtensions, предназначенные для представлений.

Если пользователь твердо намерен использовать ActionLink () или ему не нужно (по какой-то причине) вычислять эту строку в конструкторе, это лучше сделать в представлении.

Я все еще готов и рекомендую ответы, которые предоставил tvanfosson.

4 голосов
/ 30 ноября 2011

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

string a = "Email is locked, click <a href=\""
              + Url.Action( "unlock" )
              + "\">here to unlock.</a>";
1 голос
/ 30 ноября 2011

Может быть попробовать это:

string a = "Email is locked, click " + System.Web.Mvc.Html.LinkExtensions.ActionLink("here to unlock.", "unlock");
...