Why You Can't Use Extension Methods With A WebGrid

An interesting question came up recently on the ASP.NET forums. In it, the questioner was attempting to use my Chop() extension method to limit the number of characters in a WebGrid column but it wouldn't work. At first, I was a little stumped, so I tried it myself and got an error message:

'string' does not contain a definition for 'Chop'

 

Huh? The code looked fine:

        grid.Column(
            columnName : "Description",
            format: @<text>@item.Description.Chop(20)</text>
            )

..and the extension method was placed in a class called Extensions within App_Code, so it should have worked, surely? Then I studied the error message a little more closely, and saw this:

Exception Details: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'string' does not contain a definition for 'Chop'

The exception was being thrown by the RuntimeBinder, not the Compiler.

The argument that the WebGridColumn's Format parameter takes is a delegate: Func<dynamic,object>. What this means is that you have to pass in a dynamic type, and then something is done to it before it is returned as an object. A dynamic expression is resolved at runtime. The compiler doesn't know what it is.

When you try to use an extension method, the Compiler will check the type you are trying to use it on to see if such a method exists. If it doesn't. it will check any base classes that the type derives from to see if they contain a formal method with the right name. If that test fails, the Compiler will busy itself looking at any referenced static class which contains a static method with a first argument (the this part of an extension method) of the same type that the method is invoked on. In the case of the Chop method, that would a string. With dynamic variables, that reference isn't passed as part of the "Payload" to the RuntimeBinder, so it cannot find the extension method in your App_Code folder. And that, in the shell of a nut, is why you cannot use extension methods on a dynamic.

Great, so what can you do? Well, the extension method is still a static method on a class, so you can call it like this:

        grid.Column(
            columnName : "Description",
            format: @<text>@Extensions.Chop(item.Description, 20)</text>
            )

Note that this issue doesn't just affect items from a query which are passed to the format method in a WebGrid - it affects all the results you get from a database query because the Database.Query method returns an IEnumerable<dynamic>. That means that you cannot simply apply an extension method in this context either:

@foreach(var item in data){
    @item.Description.Chop(30)<br />
}

One thing you can do in the above example (outside of a WebGrid) is to convert the dynamic return to a strongly typed one. You can use Jeremy Skinners Strongly Type helper for WebMatrix.Data for this (http://www.jeremyskinner.co.uk/2011/01/24/strongly-typed-data-access-with-webmatrix-data/).

If you have problems trying to use extension methods within the WebGridColumn's format argument, or anywhere else on the dynamic return from a method, hopefully you know what to do now. But this example also goes to show that it pays to read exception messages carefully.

 

Date Posted:
Last Updated:
Posted by:
Total Views to date: 11079

2 Comments

- Alistair

Hi Mike, after hitting my head with Use Extension Methods With A WebGrid, i found this article, i tried your suggestion but i keep getting the error below, any ideas?

CS1738: Named argument specifications must appear after all fixed arguments have been specified

- Amir

Thanks mate!

Recent Comments

Borut Spanovic 5/29/2015 11:28 AM
In response to Using ASP.NET Identity with Razor Web Pages
From this great tutorial is past a lot of time. I wonder is something change for WebMatrix - is it...

Ansuya 5/29/2015 8:24 AM
In response to Displaying Google Analytics Data in ASP.NET
Above code is not working....

Joseph Casey 5/28/2015 7:51 PM
In response to ASP.NET MVC 5 with EF 6 - Working With Files
Can you explain or provide a resource as to what is happening here? public enum FileType { =...

cesar 5/28/2015 4:56 PM
In response to Scheduled Tasks In ASP.NET With Quartz.Net
When the application pool recycle then the quartz scheduler is also destroyed, how do we keep it are...

Steve 5/28/2015 4:44 PM
In response to MVC 5 with EF 6 in Visual Basic - Reading Related Data
On this page under the section "Disable lazy loading before serialization" , the "Advanced Scenarios...

Manie Verster 5/28/2015 9:39 AM
In response to MVC 5 with EF 6 in Visual Basic - Implementing Inheritance
Sorry Mike but on my project when run it does not show the hire date and/or enrollment date. I the I...

Joseph Casey 5/27/2015 3:17 PM
In response to ASP.NET MVC 5 with EF 6 - Working With Files
Probably should have read the title. Couldn't use it with Visual Studios 2013. =[...

jean 5/27/2015 8:41 AM
In response to iTextSharp - Drawing shapes and Graphics
hey Mike, I read your arcticle about drawing on PDF with ITextSharp, it was really interesting !...

Alexandros L 5/26/2015 10:50 PM
In response to Entity Framework 6 Recipe - Hierarchical Data Management
You are a live saver.. thank you so much......

saurabh rao 5/26/2015 1:03 PM
In response to ASP.NET MVC 5 with EF 6 - Working With Files
Hey Mike ! Great article ...the code worked flawlessly for me. Didn't have any issues executing it ....