3

I'm having a problem with the MVC3 MusicStore tutorial. It defines an HtmlHelper with a Truncate method. The helper looks like this:

using System.Web.Mvc;

namespace MusicStore.Helpers
{
    public class HtmlHelpers
    {
        public static string Truncate(this HtmlHelper helper, string input, int length)
        {
            if (input.Length <= length)
            {
                return input;
            }
            else
            {
                return input.Substring(0, length) + "...";
            }
        }
    }
}

In the view, I import it using @using MusicStore.Helpers, and then try to use it with <td>@Html.Truncate(item.Title, 25) </td>

However the compiler tells me no such method (Truncate) exists, and seems to be looking for Truncate on IEnumerable[MvcMusicStore.Models.Album] (which is my model) rather than on my HtmlHelpers class.

(NB the square brackets above are really angled brackets in my code, couldnt escape them)

Can anyone tell me what I'm doing wrong please?

3 Answers 3

9

Extension methods should be declared in a static class:

public static class HtmlHelpers
{
    public static string Truncate(
        this HtmlHelper helper, 
        string input, 
        int length
    )
    {
        if (input.Length <= length)
        {
            return input;
        }
        return input.Substring(0, length) + "...";
    }
}

and then in your view make sure you have referenced the namespace containing the static class with the extension method:

@using System.Web.Mvc
...
<td>@Html.Truncate(item.Title, 25)</td>

or if you want the helper to be available in all Razor views without the need of adding a using directive you could add the corresponding namespace to the namespaces section of ~/Views/web.config file:

<system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="Namespace.Containig.Static.Class.With.Custom.Helpers" />
      </namespaces>
    </pages>
</system.web.webPages.razor>
Sign up to request clarification or add additional context in comments.

9 Comments

+1, and Side note - i've seen uses of IHtmlString in MVC3 for HTML Helpers. Should we be using that in MVC3? I'm not sure what other classes implement this interface. Or is it for unit testing (mocking) that we do this?
@RPM1984, yes you could use IHtmlString as return type. It would be more correct. And it's not for unit testing as here it is as return type so we don't care about mocking it, it's just about good practices to use the class/interface which is higher in the hierarchy.
Don't return IHtmlString. That's not HTML, and must be escaped.
@SLaks - clarification please?
@Slaks, that's true, in this case returning string would be better. I will update my answer.
|
0

Extension methods must be defined in a static class. So change you code to:

public static class HtmlHelpers
{
    public static string Truncate(this HtmlHelper helper, string input, int length)
    {
        if (input.Length <= length)
        {
            return input;
        }
        else
        {
            return input.Substring(0, length) + "...";
        }
    }
}

Also, @Darin Dimitrov brings up a good point - you should really retrun an instance of MvcHtmlString.

On a related note, you can import namespaces into your views through the web.config - I'd recommend doing that so you don't have to remember to do it in every page.

4 Comments

Ahh, thanks to you both (very quick too!). The complete solution in the tutorial seems a bit broken then. First, I forgot to make my class static (oops) and also changing it to return an MvcHtmlString helped too. The number of args is correct though, although I have to admit I dont quite understand the args syntax (this HtmlHelper helper) since I don't need to specify that when I actually use it in my View but I guess it's something the framework passes in automatically?
Exactly... it's called an "Extension Method" - see here msdn.microsoft.com/en-us/library/bb383977.aspx & en.wikipedia.org/wiki/Extension_method
Don't return IHtmlString. That's not HTML, and must be escaped.
Blimey lots of replies now! Thanks for all these tips everyone, have bookmarked this question as I think I'll be referring to it as I progress!
0

You may also want to consider adding the namespace to your web.config. I know I use my helpers on multiple pages. Remembering to add using on every view is a pain.

<system.web>
  <pages>
    <namespaces>
      <add namespace="MusicStore.Helpers"/>
    </namespaces>
  </pages>
</system.web>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.