Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use MVC 3 @Html.ActionLink inside c# code

I want to call the @Html.ActionLink method inside a c# function to return a string with a link on it.

Something like this:

string a = "Email is locked, click " + @Html.ActionLink("here to unlock.", "unlock") ;
like image 299
roncansan Avatar asked Nov 30 '11 18:11

roncansan


People also ask

What is HTML ActionLink in MVC?

Html. ActionLink creates a hyperlink on a view page and the user clicks it to navigate to a new URL. It does not link to a view directly, rather it links to a controller's action.

How do I pass model value through ActionLink?

Where RegLookup is a get ActionResult method in the vehicle controller which goes away and finds the model/make/colour information based on the registration field passed through to it. The Make/Model/Colour information is retrieved from a separate database.


2 Answers

Assuming that you want to accomplish this in your controller, there are several hoops to jump through. You must instantiate a ViewDataDictionary and a TempDataDictionary. Then you need to take the ControllerContext and create an IView. Finally, you are ready to create your HtmlHelper using all of these elements (plus your RouteCollection).

Once you have done all of this, you can use LinkExtensions.ActionLink to create your custom link. In your view, you will need to use @Html.Raw() to display your links, to prevent them from being HTML encoded. Here is the necessary code:

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();

Having shown all of this, I will caution you that it is a much better idea to do this in your view. Add the error and other information to your ViewModel, then code your view to create the link. If this is needed across multiple views, create an HtmlHelper to do the link creation.

UPDATE

To address one.beat.consumer, my initial answer was an example of what is possible. If the developer needs to reuse this technique, the complexity can be hidden in a static helper, like so:

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;
    }
}

Then, in a controller, it is used like so:

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

or like so:

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

While it is easier to use Url.Action, this now extends into a powerful tool to generate any mark-up within a controller using all of the HtmlHelpers (with full Intellisense).

Possibilities of use include generating mark-up using models and Editor templates for emails, pdf generation, on-line document delivery, etc.

like image 153
counsellorben Avatar answered Sep 18 '22 13:09

counsellorben


You could create an HtmlHelper extension method:

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

or if you mean to generate this link outside of the scope of an aspx page you'll need to create a reference to an HtmlHelper and then generate. I do this in a UrlUtility static class (I know, people hate static classes and the word Utility, but try to focus). Overload as necessary:

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);
}

Then you can write the following from wherever your heart desires:

string a = "Email is locked, click " + UrlUtility.ActionLink("here to unlock.", "unlock", "controller");
like image 23
hunter Avatar answered Sep 22 '22 13:09

hunter