Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I use my extension method in a delegate in the Razor WebGrid

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.

like image 218
Eduardo Molteni Avatar asked Oct 22 '22 14:10

Eduardo Molteni


2 Answers

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.

like image 93
Mike Brind Avatar answered Oct 24 '22 04:10

Mike Brind


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)

like image 41
Kirk Woll Avatar answered Oct 24 '22 04:10

Kirk Woll