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: 11435

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

sandeep 8/28/2015 7:03 AM
In response to 7 C# 6.0 Features That Every ASP.NET Developer Should Know About
very good article, i like it........keep writing such quality article in future. thx Mike....

Hassan, MVC Learner 8/28/2015 6:37 AM
In response to Get The Drop On ASP.NET MVC DropDownLists
Great Help, simple, great and patiently explained article !...

Anvesh 8/28/2015 12:39 AM
In response to ASP.NET MVC DropDownLists - Multiple Selection and Enum Support
what if we are taking postback values from FormCollections instead of an array int[] category. How...

Ben 8/27/2015 10:50 PM
In response to Simple File Download Protection with ASP.NET
Is it possible to setup your project to publish files to outside of your root directory? I would to...

Fred 8/26/2015 12:50 AM
In response to WebMatrix Opens Wrong Version Of Visual Studio
I enjoyed many of your tutorials but the problem is none of the tutorials are combined like most be....

Muhammad Ashikuzzaman 8/25/2015 2:48 PM
In response to Managing Checkboxes And Radios In ASP.NET Razor Web Pages
That's a very good tips for razor...

Sergey 8/25/2015 8:32 AM
In response to More Flexible Routing For ASP.NET Web Pages
Hi. How I can set up my site to get urldata from link for default page? site.com/default/1-...

Tony Gray 8/25/2015 6:27 AM
In response to Adding Validation
Hi Mike, Really helpful article and series. Thanks. Small typo in 4th paragraph you have so...

amanda n 8/25/2015 12:38 AM
In response to Solving the Operation Must Use An Updateable Query error
Thank you very much. I'm a uni student and while solving coding problems is usually enjoyable and me...

salman 8/23/2015 9:25 AM
In response to How To Send Email In ASP.NET MVC
thanks ......