5

I'm using the MVC 3 introduced WebGrid, but can't can't apply my own extension methods when passing a delegate for the format param.

Using:

Grid.Column("MyProperty", "MyProperty", 
format: @<span class="something">@item.MyProperty.MyExtensionMethodForString()</span>)

I got

ERROR: 'string' does not contain a definition for 'MyExtensionMethodForString'

I've tried casting, not to avail

Grid.Column("MyProperty", "MyProperty", 
format: @<span class="something">@((string)(item.MyProperty).MyExtensionMethodForString())</span>)

If I use an standard method, it works:

Grid.Column("MyProperty", "MyProperty", 
format: @<span class="something">@(Utils.MyExtensionMethodForString(item.MyProperty))</span>)

I've also tried to put the extension in the same namespace, with no results.

How can I use my beloved extensions?

Edit: The namespace per se it's not the problem, the namespace where the extension is available for all the views and classes, and I can use it in the same view without problem. The problem is when using it in the delegate.

Eduardo Molteni
  • 38,786
  • 23
  • 141
  • 206

3 Answers3

2

This is not a limitation of the WebGrid or Razor. It's a limitation of the C# dynamic type. You cannot use extension methods on dynamic. The format helper takes a Func<dynamic, object> as an argument, so the item parameter is a dynamic type.

I wrote about this exact issue a couple of years ago.

Mike Brind
  • 28,238
  • 6
  • 56
  • 88
1

This works just fine for me. Static class:

public static class TestExtensions
{
    public static string Foo(this HtmlHelper html, Func<object, HelperResult> func)
    {
        return func(null).ToHtmlString();
    }

    public static string MyStringExtension(this string s)
    {
        return s.ToUpper();
    }
}

Index.cshtml:

@using MvcApplication1.Controllers

@Html.Foo(@<text>@Html.Raw("Hello")</text>)

The page prints out:

Hello

However, this version of the Index.cshtml:

@using MvcApplication1.Controllers

@Html.Foo(@<text>@("Hello".MyStringExtension())</text>)

Prints out your error message:

CS1061: 'string' does not contain a definition for 'MyStringExtension' and no extension method 'MyStringExtension' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)

So I suspect Jon was correct and this is a limitation with Razor. (why it works with HtmlHelper leaves me a bit mystified though)

Kirk Woll
  • 76,112
  • 22
  • 180
  • 195
0

Found this SO question by way of researching why the following line was throwing the same error:

@a.GetAttribute<ActionLabelAttribute>().ActionLabel

Turns out it could easily be corrected by enclosing this line in parenthesis, like so:

@(a.GetAttribute<ActionLabelAttribute>().ActionLabel)

Note: The GetAttribute extension method comes from here.

Community
  • 1
  • 1
Matt Borja
  • 1,509
  • 1
  • 17
  • 38