views:

130

answers:

2

I've created an Html extension method in Helper class, but I can not get it to work. I've implemented it as seen on different tutorials.

My MenuItemHelper static class:

public static string MenuItem(this HtmlHelper helper, string linkText, string actionName, string controllerName)
    {
        var currentControllerName = (string)helper.ViewContext.RouteData.Values["controller"];
        var currentActionName = (string)helper.ViewContext.RouteData.Values["action"];

        var sb = new StringBuilder();

        if (currentControllerName.Equals(controllerName, StringComparison.CurrentCultureIgnoreCase) && currentActionName.Equals(actionName, StringComparison.CurrentCultureIgnoreCase))
            sb.Append("<li class=\"selected\">");
        else
            sb.Append("<li>");

        sb.Append(helper.ActionLink(linkText, actionName, controllerName));
        sb.Append("</li>");
        return sb.ToString();
    }

import namespace

<%@ Import Namespace="MYAPP.Web.App.Helpers" %>

Implementation on my master.page

<%= Html.MenuItem("TEST LINK", "About", "Site") %> 

The error message I get:

Method not found: 'System.String System.Web.Mvc.Html.LinkExtensions.ActionLink(System.Web.Mvc.HtmlHelper, System.String, System.String, System.String)

EDIT: Seem like the problem is the application name. the folder is called MYAPP-MVC.Web, but in the classes it translates to MYAPP_MVC.Web

I just tried it on a fresh application and it works

A: 

You need to make the extension method available to the page/viewpage. You can do this for the individual page by adding a directive to the top of it

<%@ Import namespace="Namespace.Where.Your.HtmlHelper.Extension.Is.Defined" %>

or you can make it available to all pages by adding it to the

<pages> 
    <namespaces>
        <add namespace="Namespace.Where.Your.HtmlHelper.Extension.Is.Defined" />
    </namespaces>
</pages>

section in web.config.

EDIT:

The problem might be to do with the fact that HtmlHelper.ActionLink() returns an MvcHtmlString and not a string. I think you should call ToString() on it when calling append with the StringBuilder. As has been pointed out, ideally you ought to be returning MvcHtmlString so that others can use your extension method with the <%: ... %> syntax and not have the output encoded again.

Russ Cam
You mean the namespace? if so that is already done, i do the imports.
Dejan.S
And you get intellisense that indicates your extension method is found and can be used?
Russ Cam
Yep but I think I found the problem, check my edit.. thanks for reply Russ
Dejan.S
But if I'm not wrong Russ the <%: is explicit 4.0 thing?
Dejan.S
yes, you're right :) For any data that is potentially coming from the user though, you should be encoding it to mitigate injection attacks. It doesn't look as though that's necessary in this particular case, but it is a good practice to get into.
Russ Cam
+4  A: 

Try rewriting your helper in a more ASP.NET MVCish 2.0 style. Also don't forget to add using System.Web.Mvc.Html inside your helper namespace so that you have access to the ActionLink method:

namespace MYAPP.Web.App.Helpers
{
    using System.Web.Mvc;
    using System.Web.Mvc.Html;

    public static class HtmlExtensions
    {
        public static MvcHtmlString MenuItem(this HtmlHelper helper, string linkText, string actionName, string controllerName)
        {
            var currentControllerName = (string)helper.ViewContext.RouteData.Values["controller"];
            var currentActionName = (string)helper.ViewContext.RouteData.Values["action"];

            var li = new TagBuilder("li");
            if (string.Equals(currentControllerName, controllerName, StringComparison.CurrentCultureIgnoreCase) &&
                string.Equals(currentActionName, actionName, StringComparison.CurrentCultureIgnoreCase))
            {
                li.AddCssClass("selected");
            }

            li.InnerHtml = helper.ActionLink(linkText, actionName, controllerName).ToHtmlString();
            return MvcHtmlString.Create(li.ToString());
        }
    }
}

If this doesn't work you are definitely having some version problems with the System.Web.Mvc assembly being used.

Darin Dimitrov
+1 - good points about using the `TagBuilder` and returning `MvcHtmlString`. The OP should be using the new encoding syntax to `<%: ... %>`
Russ Cam
Good thing about the Tagbuilder, I will use that instead. Thanks Darin@ Russ, I'm on 3.5 not 4.0
Dejan.S
@ Darin is the MvcHtmlString 4.0 only?
Dejan.S
No, it's not .NET 4.0 only, it's ASP.NET MVC 2.0.
Darin Dimitrov
@Darin Yeah but <%: ... %> is .NET 4 only
BritishDeveloper
@Yes, but the question was is `MvcHtmlString` .NET 4.0 only and the answer is no. And why not be ready for it when it comes :-)
Darin Dimitrov