Scott Hanselman

Spring Speaking Rollup 2010: Recent Talks and Upcoming Talks at Microsoft WebCamps

April 9, '10 Comments [13] Posted in ASP.NET | ASP.NET Ajax | ASP.NET MVC | Channel9 | Microsoft | Programming | Speaking | Windows Client | WPF
Sponsored By

DevDays and TechDays

I've been travelling some, and I have a few more trips at Microsoft WebCamps before I take a much needed break and stop travelling until 2011.

I went to Munich, Cairo, and Dubai a few weeks back and presented on ASP.NET MVC (both Beginner and Advanced), .NET 4 in general, Making Your Blog Suck Less, and Information Overload. I presented at Mix 10 on Web Development and Security with Phil Haack.

Last week I was in Belgium and The Netherlands and gave some talks as well.

I thought it would be nice to put all my recent talks in one place. So, here's some video recordings of some of my recent talks. I hope you enjoy watching them as much as I did giving them.

ASP.NET MVC 2: Basics/Introduction

Join Scott Hanselman as he explains ASP.NET MVC from File -> New Project. We’ll dig into the details and try to put MVC into perspective. Is WebForms going away? What’s better about MVC vs. WebForms? How does MVC sit on top of ASP.NET and how was it written? We’ll play with call stacks, and avoid PowerPoint slides! This is an introduction to ASP.NET, but it’s not a “basic” session. We assume you have some web development concepts or perhaps you’re a professional ASP.NET WebForms developers who is just starting out with ASP.NET MVC.

ASP.NET MVC 2: Basics

Lap Around .NET 4

In this session, Scott Hanselman gives a deep and broad tour of the .NET 4 release, with a focus on making your development experience easier. See lots of demos (and very few slides) showcasing the key new features in the .NET Framework 4 including MEF, improvements in ASP.NET, threading, multi-core and parallel extensions, additions to the base classes, changes and additions to the CLR and DLR, what's new for the languages (Visual Basic and C#), and of course, what's new in Windows Presentation Foundation and System.Web. Come and see how all these new features and capabilities improve your overall .NET experience!

image 

Information Overload and Managing the Flow: Effectiveness and Efficiency

This talk is/was a mashup of the various techniques that I try to apply in my everyday life. There's a little GTD, a little Covey, a little Pomodoro, a little Jon Udell, a little 43 Folders, a little Merlin Mann, a little Gina Trapani, and a little Hanselman. I also show some of the tools I used to manage the flow of information in my life. I hope you enjoy it. I'm  pretty happy with the way it turned out, given that I was freaking out about it for a week.

image

Trip Montage - If this is Tuesday, this must be Cairo.

This isn't a talk as it's a "trip montage." I went to Munich, Cairo and Dubai. I presented in three keynotes and did a total of 10 sessions. I crossed 12 time zones and missed my kids. I talked to/with/at about 3000 people. 
I took some video while I was travelling with my Creative Vado HD and slapped it into Windows Live Movie Maker just now. Here's my trip montage. You could call this either "The Glamorous Life of a Technical Speaker" or "If this is Tuesday, this must be Cairo" or "Scott needs to learn to say No."

Web Deployment Made Awesome: If you're using XCopy, you're doing it wrong.

If you typically deploy your web applications using Windows Explorer and Aero Snap, please stop. Come see a practical session on the new deployment goodness in Microsoft Visual Studio 2010 and .NET Framework 4. We dig into Web Deploy (a.k.a. MSDeploy) and deployment from within Visual Studio 2010. Is deployment a chore? I say, nay, nay. Let's learn how to package up web apps, deploy them, their settings and component parts easily. We start with the basics and ramp it up quickly, exploring custom database providers and advanced techniques.

    WEB DEPLOYMENT MADE AWESOME: IF YOU'RE USING XCOPY, YOU'RE DOING IT WRONG

    The Haaha Show: Microsoft ASP.NET MVC Security With Haack and Hanselman

    Join Phil Haack and Scott Hanselman for this dynamic and unusual security session. The HaaHa brothers take turns implementing features on an ASP.NET MVC website. Scott writes a feature, and Phil exploits it and hacks into the system. We analyze and discuss the exploits live on stage and then close them one by one. Learn about XSS, CSRF, JSON Hijacking and more. Is *your* site safe from the Haack?

    THE HAAHA SHOW: MICROSOFT ASP.NET MVC SECURITY WITH HAACK AND HANSELMAN 

    Beyond File | New Company: From Cheesy Sample To Social Platform

    The web has changed and there's a new way of thinking about your applications. You can't just write some HTML and CSS anymore and expect to be the next Twitter. Hear how to make your site socially relevant in the new decade (the '10s?) This session includes everything from Microsoft ASP.NET MVC2, to Windows Communication Foundation (WCF) and OData, JSON services and blog flair, microformats, and leverage ASP.NET and Microsoft Silverlight to create rich user experiences. Let's stop messing around and start changing the world. Or at least giving Nerds a place to eat dinner.

    BEYOND FILE | NEW COMPANY: FROM CHEESY SAMPLE TO SOCIAL PLATFORM

    ASP.NET MVC 2: Ninjas Still on Fire Black Belt Tips

    Having the customer on your back to deliver features on time and under budget with tight deadlines can make you feel like you’re being chased by ninjas on fire. Join Scott Hanselman and he’ll walk through lots of tips and tricks to get the most out of the ASP.NET MVC 2 framework and deliver work quickly and with style. Come see ASP.NET MVC 2’s better productivity features as we make the most of several key features.

    image

    Also, next month I'll be in Beijing, Shanghai and Sydney speaking at a different kind of event, the Microsoft Web Camps. These are not 1 hour presentations where we talk at you, but two days of technical content and labs. It's slower paced and deeper than a conference presentation. There will be WebCamps all over the world:

    Toronto May 07-08 Moscow May 19-19
    Beijing May 21-22 Shanghai May 24-25
    Mountain View May 27-28 Sydney May 28-29
    Singapore June 04-05 London June 04-05
    Munich June 07-08 Chicago June 11-12
    Redmond, WA June 18-19 New York June 25-26

    Hope to see you there.

    Webcamps China

    Enjoy.

    About Scott

    Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

    facebook twitter subscribe
    About   Newsletter
    Sponsored By
    Hosting By
    Dedicated Windows Server Hosting by SherWeb

    Video Trip Report: If this is Tuesday, this must be Cairo

    March 6, '10 Comments [11] Posted in ASP.NET | ASP.NET Ajax | ASP.NET MVC | Channel9 | Screencasts | Speaking | TechEd | Windows Client
    Sponsored By

    image

    This last week over a 7 day period, I went to Munich, Cairo and Dubai. I presented in three keynotes and did a total of 10 sessions. I crossed 12 time zones and missed my kids. I talked to/with/at about 3000 people.

    I'm utterly shattered.

    I took some video while I was travelling with my Creative Vado HD and slapped it into Windows Live Movie Maker just now. Here's my trip montage.

    You could call this either "The Glamourous Life of a Technical Speaker" or "If this is Tuesday, this must be Cairo" or "Scott needs to learn to say No."

    It was great fun, I spoke at VSOne in Munich. I talked about .NET 4 and ASP.NET MVC. We also had a nice Nerd Dinnner. Then I headed over to Cairo Code Camp and the turnout was HUGE. Something like 700-800 folks showed up at the German University in Cairo. I also recorded a great podcast on Women in Technology in the Muslim World. Then I headed to Dubai for TechEd Middle East where I presented in three sessions and did the keynote demo for Soma. It's always a challenge for me to travel because of my diabetes, particularly because of the time zones but also sitting for 16 hours at a time in a plane and eating plane food is a problematic. However, I must say that everyone on this trip was incredibly kind and accommodating.

    If you have the chance to go to Munich, Cairo, and/or Dubai, I highly recommend it. The people, the places and the technologists are all top-notch.

    Enjoy.

    P.S. Thanks to http://blog.bloggingitloud.com/ for the guerilla footage of the TechEdME Keynote.

    About Scott

    Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

    facebook twitter subscribe
    About   Newsletter
    Sponsored By
    Hosting By
    Dedicated Windows Server Hosting by SherWeb

    Put Missing Kids on your 404 Page - Entirely Client-Side Solution with YQL, jQuery, and MSAjax

    February 25, '10 Comments [51] Posted in ASP.NET | ASP.NET Ajax | Open Source
    Sponsored By

    image I noticed a post over at a blog called "The other side of the moon" where the author suggests that we put pictures and details of missing children on on 404 pages. It's a simple and brilliant idea. Millions of 404s are delivered every day. We are reporting on missing pages, but not on missing children. He includes a simple PHP solution. I set out to create an ASP.NET solution, but then realized that a server-side solution wasn't really necessary.

    Could I do it all on the client side? This way anyone could add this feature to their site, regardless of their server-side choice. This could make the solution much more palatable to folks who may not be into .NET.

    Here's what I came up with. You can see it in action if you request a file that doesn't exist from my site, like http://www.hanselman.com/foo.aspx.

    The file is called missingkids404.html and it's just static html. You will need to configure your webserver to serve this page when it needs to serve a 404. For me, as I do run ASP.NET and IIS, I needed to add this to my web.config in the System.Web section:

    <customErrors mode="On"> 
    <error statusCode="404" redirect="/missingkids404.html" />
    </customErrors>

    The file, in its entirety, is this:

    <html>
    <head>
    <title>Missing Kids 404</title>
    <style type="text/css">
    .sys-template { display:none; }
    .missingkid { clear:both; }
    </style>
    <script src="http://ajax.microsoft.com/ajax/beta/0911/Start.js" type="text/javascript"></script>
    </head>
    <body>
    <script type="text/javascript">
    Sys.require([Sys.components.dataView, Sys.scripts.jQuery], function() {
    $("#missingkids").dataView();

    var statecode = "ZZ";
    var dataurl = "http://query.yahooapis.com/v1/public/yql?q=SELECT%20*%20From%20xml%0D%0A%20Where%20url%3D'http%3A%2F%2Fwww.missingkidsmap.com%2Fread.php%3Fstate%3D" + statecode + "'%0D%0A&format=json&callback=?";
    var data = $.getJSON(dataurl, function(results){
    Sys.get("$missingkids").set_data(results.query.results.locations.location);
    }
    );
    });

    function getSrc(url) {
    var lastIndex = url.lastIndexOf('=');
    return url.substring(lastIndex+1);
    }
    </script>

    <p>
    <strong>Sorry, the page you're trying to find is missing.</strong>
    </p>
    <p>
    We may not be able to find the page, but perhaps you could help find one of these missing children:
    </p>

    <div id="missingkids" class="sys-template">
    <div class="missingkid">
    <img sys:width="60" sys:align="left" sys:src="{binding medpic, convert=getSrc}" />
    <strong>{{firstname + " " + lastname}}</strong>, Age: {{age}} from
    {{city}}, {{st}}</br>
    Contact: {{policeadd}} at {{policenum}}<br/>
    <br/>
    </div>
    </div>
    </body>
    </html>

    I'm using the standard {{token}} syntax as well as one custom syntax with a convert=callback so I can pre-process the data. The source data feed includes an unfortunate chunk of html, rather than a direct link to a picture. I need to strip everything after the last equals sign (=) in order to get the image src URL. That method is called getSrc, and the binding looks like:

    <img sys:width="60" sys:align="left" sys:src="{binding medpic, convert=getSrc}" />

    If this is useful, the next step is to add geolocation. You can look at http://www.hanselman.com/missingkids404geo.html for the beginnings of a geo-location aware one. The open issue right now is that the missing kids feed works only in the US, Canada and the UK. I would need to figure out now to determine the two-letter STATE code from the geolocation API, which doesn't provide codes in that way. Worst case scenario, I'd have a lookup table of state names to abbreviations.

    Enjoy! Thoughts?

    About Scott

    Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

    facebook twitter subscribe
    About   Newsletter
    Sponsored By
    Hosting By
    Dedicated Windows Server Hosting by SherWeb

    2010 Survey Results: What .NET Framework features do you use?

    January 14, '10 Comments [37] Posted in ASP.NET | ASP.NET Ajax | ASP.NET Dynamic Data | ASP.NET MVC | Learning .NET | Programming | Web Services | Windows Client | WPF
    Sponsored By

    In October of 2008 I took an informal survey on Twitter. I wanted to get an idea of what features of the .NET Framework people were using.

    Also, here's the disclaimer. I did this on a whim, it's not scientific, so the margin of error is +/-101%. That said, the results feel intuitively right to me, personally.

    I put the poll out again last week, adding only Silverlight to the end as an option. I realize I could have added many other subsystems and choices, but I felt it would have made this new poll too different from the original. There's certainly many ways that it could be improved as a survey, but it's best to think of it more as a "which direction is the wind blowing" question, than a survey per se.

    I also didn't push/promote this survey very hard, so it got only about 1250 responses, vs. the nearly 5000 from last year, but I've kept the same color and attempted to keep the scale so one could extrapolate trends visually.

    Hanselman Blog Informal .NET Subsystem Survey CHART - Updated 2010 

    Here's the original survey:

    Hanselman Blog Informal .NET Subsystem Survey CHART - 2008

    It's also worth noting that 'NHibernate' was written into the "other" option 24 times. The poll was taken with TwtPoll.

    Here's my conclusions.

    • WinForms remains popular but WPF is closing the gap.
    • ASP.NET MVC is nearly as popular as ASP.NET WebForms. Remember, however, that my readership 'skews Alpha' so might be more likely to be using MVC.
    • ADO.NET Data Services is starting to get some of the appreciation it deserves, but the existence of ADO Datasets persists.
    • Lots of folks use Silverlight, in this example set, even more than WPF.

    What are your conclusions and analysis?

    About Scott

    Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

    facebook twitter subscribe
    About   Newsletter
    Sponsored By
    Hosting By
    Dedicated Windows Server Hosting by SherWeb

    The Weekly Source Code 47 - ASP.NET 3.5 Dynamic Data: FilterRepeaters and Dynamic Linq Query Generation

    January 13, '10 Comments [5] Posted in ASP.NET | ASP.NET Ajax | ASP.NET Dynamic Data | ASP.NET MVC | Source Code
    Sponsored By

    First, let me start this post by thanking Tatham Oddie. He helped my buddy John Batdorf and I debug our issue remotely from Australia. He's patient, kind, opinionated and Tatham's got a darn fine blog that you should subscribe to now. I also found great inspiration from Stephen Naughton's excellent blog. He's continually pushing ASP.NET and Dynamic Data to do fun things and I was able to use 95% of his auto-complete code as I found it. And finally Marcin Dobosz's blog is where I started, taking his Dynamic Data sample Filter Repeaters and ending up at the Dynamic Data Futures samples.

    Technical Disclaimer: This is me just messing about with the .NET 3.5 SP1 Dynamic Data samples as this non-profit wanted .NET 3.5. The Filters I'm messing with here are from the VS2008 SP1 Dynamic Data Futures from May of 2009 but are included out of the box and are much cooler in .NET 4 in Visual Studio 2010 Beta 2. Some method names and base classes have changed, but the idea is effectively the same. If you're using .NET 4 you'll notice you'll get the ~/DynamicData/Filters folder when you do File | New Project and a new QueryableFilterRepeater rather than an AdvancedFilterRepeater, and like that. In my 3.5 project I included the DynamicDataExtensions Project in my solution, while in .NET 4 all this functionality is in System.Web.DynamicData itself. I'll update this project and blog a sample when .NET 4 is closer to release.

    Ok, the story is that John and I are doing some volunteer work and updating a local non-profit's website on the side in our copious spare time. They have simple needs, on the front end they want a nice simple autocomplete textbox and maybe a filter drop down or two. This'll send the user to a results page with a non-editable paged grid and a dynamically generated image for printing. On the backend, they want a few more dropdowns for admins and then a nice editable grid for searching, paging, etc.

    We each thought this would be a fun opportunity to see if could put it together in a night and learn more about ASP.NET Web Forms and Dynamic Data at the same time. It's all very meta, so we decided we'd be meta also. (Remember, that means effectively "solution non-specific." We'd like to be able to use whatever things we create for ASP.NET Dynamic Data in other projects.)

    Meta Meta

    When creating a site with ASP.NET Dynamic Data, the pages you create are templates - they are kinds of pages - rather than instances of pages themselves. So, I create a List.aspx, and it's not specific to (in my case) Brick objects. It's for listing any kind of object I want to in my solution.

    Here's a simplified example of my list.aspx in my Dynamic Data solution. The things we care about are that it has a:

    • LinqDataSource
    • GridView
    • AdvancedFilterRepeater - Again, this was the name it had in the 3.5 Dynamic Data Futures. It's an extension of the standard Filter Repeater that comes with ASP.NET. It has a DelegatingFilter in its ItemTemplate.

    And that's it.

    <ContentTemplate>
    <asp:ValidationSummary ID="ValidationSummary1" runat="server" EnableClientScript="true"
    HeaderText="List of validation errors" />
    <asp:DynamicValidator runat="server" ID="GridViewValidator" ControlToValidate="GridView1" Display="None" />

    <asp:AdvancedFilterRepeater id="AdvancedFilterRepeater" runat="server">
    <HeaderTemplate>
    <table>
    </HeaderTemplate>
    <ItemTemplate>
    <tr>
    <td valign="top"><%# Eval("DisplayName") %>:</td>
    <td><asp:DelegatingFilter runat="server" ID="DynamicFilter" OnSelectionChanged="OnFilterSelectedIndexChanged" />
    </tr>
    </ItemTemplate>
    <FooterTemplate>
    </table>
    </FooterTemplate>
    </asp:AdvancedFilterRepeater>

    <asp:GridView ID="GridView1" runat="server" DataSourceID="GridDataSource"
    AllowPaging="True" AllowSorting="True" CssClass="gridview">
    <Columns>
    <asp:TemplateField>
    <ItemTemplate>
    <asp:HyperLink ID="DetailsHyperLink" runat="server"
    NavigateUrl='<%# table.GetActionPath(PageAction.Details, GetDataItem()) %>'
    Text="Details" />
    </ItemTemplate>
    </asp:TemplateField>
    </Columns>

    <PagerStyle CssClass="footer"/>
    <PagerTemplate>
    <asp:GridViewPager runat="server" />
    </PagerTemplate>
    <EmptyDataTemplate>
    There are currently no items in this table.
    </EmptyDataTemplate>
    </asp:GridView>

    <asp:LinqDataSource ID="GridDataSource" runat="server" EnableDelete="false" EnableInsert="false" EnableUpdate="false">
    <WhereParameters>
    <asp:DynamicControlParameter ControlID="AdvancedFilterRepeater" />
    </WhereParameters>
    </asp:LinqDataSource>

    <br />
    </ContentTemplate>

    The AdvancedFilter repeater is what's cool and it's what Marcin blogged about and that ended up in the samples. Stephen Naughton has since extended the FilterRepeater even more with his wonderful "Dynamic Data Futures" series.

    The FilterRepeater is a special Repeater control that binds to a collection of columns (properties) in an table (list<object>) and make dynamically make controls that will allow filtering.

    For example, here's my Brick object model (actually the "buddy metadata class" of my Brick object. It's a mirror of what's in the database:

    [MetadataType(typeof(Brick_MD))]
    public partial class Brick
    {
    public class Brick_MD
    {
    [Filter(FilterControl = "AutoComplete")]
    public object Name { get; set; }

    [Filter(FilterControl = "Integer", AuthenticatedOnly = true)]
    public object Square { get; set; }

    [Filter(FilterControl = "Integer")]
    public object Year { get; set; }

    public object Side { get; set; }

    public object Row { get; set; }

    public object BrickNum { get; set; }

    public object Order { get; set; }
    }

    }

    imageNotice the Filter attributes. I've extended it with a property called AuthenticatedOnly for properties that only authenticated users (non-anonymous) can see filters for. I've also said that one property/column needs an AutoComplete style filter (without being specific about the implementation) and two others need Integer style (again, implementation non-specific metadata. Could be combo, slider, whatever.)

    ASP.NET Dynamic Data uses a special folder by convention called DynamicData with sub-folder like FieldTemplates for specific kinds of fields (Integer, DateTime, Person, etc) and PageTemplate for specific pages (List, Edit, Details, etc.)

    The FilterRepeater sample extends this concept with a ~/DynamicData/Filters folder. This is set in the GetFilterControl method inside the FilterFactor if you want to see where the actual mention of the 'Filters' directory exists in the code. The point is that there's a string on my meta-model that says "AutoComplete" and that maps by convention to the ~/DynamicData/Filters/AutoComplete.ascx control, just as "Integer" maps to Integer.ascx, etc.

    This is all Integer.ascx is, for example:

    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="Integer.ascx.cs" Inherits="AdvancedFilterRepeaterSite.Integer_Filter" %>

    <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="true" EnableViewState="false">
    <asp:ListItem Text="All" Value="" />
    </asp:DropDownList>

    It's just a dropdown list. When the FilterRepeater is checking out the columns/properties on the Brick_MD object, it's saying, "oh, I to put a Integer.ascx here" and it'll feed it the data it needs. All these controls like the Integer one derive from FilterUserControlBase and just have to override the properties or methods for the behavior they want to change.

    All this is pretty straight forward, and you can do really cool stuff with it.

    Dynamically Generating Generically Specific LINQ Queries

    However, things got hairy when we noticed that the DropDownList being created didn't have the values sorted ahead of time. This made weird dropdowns with the integers in whatever order they were in the database already.

    You would think you'd want some code like this behind your Integer Filter Control:

    protected void Page_Init(object sender, EventArgs e) {
    var items = Column.Table.GetQuery();

    //magic psuedo code here
    var result = items.Select(row => row.Property).Distinct.OrderBy(colvalue => colvalue)

    foreach (var item in result) {
    if (item != null) DropDownList1.Items.Add(item.ToString());
    }
    }

    Notice the "magic" part. That's the LINQ query we wish we could call, but remember that I don't want to make a query against a specific table and a specific column. If I did, this wouldn't be the Integer Filter Control, it'd be the Year Filter Control or the Month Filter Control. It'd be specific, not generic.

    We need to dynamically create a LINQ query. But just like you don't want to just make dynamic SQL by concatenating strings, the same applies for LINQ. Instead we will use the System.Linq.Expressions.Expression base class to creating a tree that represents our LINQ query. Another metaphor/example would be using XmlDocuments and the DOM to make XML rather than making it with a bunch of strings.

    We want effectively, this query, made specific. Each time this Integer Filter Control is run it'll be specific to the column (and even the type, arguably, could be something other than integer) we're currently making a control for.

    Items.Select(row => row.Property).Distinct.OrderBy(colvalue => colvalue)

    We need the building blocks for this query, starting with whatever "row" is.

    // row
    var entityParam = Expression.Parameter(Column.Table.EntityType, "row");

    Because we are a FilterUserControlBase, we can ask Dynamic Data for the typeof(row) which is in Column.Table.EntityType. We'll be using the types and info that DynamicData provides to create this query.

    Next we get the Property of row by passing in (building on) the entityParam we just made. Now "columnLambda" is of type LambdaExpression.

    // row => row.Property
    var columnLambda = Expression.Lambda(Expression.Property(entityParam, Column.EntityTypeProperty), entityParam);

    Next the Select. Here we are dynamically generating a LINQ function call. This is LINQ's idea of Reflection, effectively. The Type[] are the params. Remember what the Select call looks like: Select<TSource, TResult>(IEnumerable<TSource>, Func<TSource, TResult>) and we're giving it just those things it wants.

    // Items.Select(row => row.Property)
    var selectCall = Expression.Call(typeof(Queryable), "Select", new Type[] { items.ElementType, columnLambda.Body.Type }, items.Expression, columnLambda);

    Now we add just Distinct to the previous call. Look at the comment. See how we are building on the previous selectCall expression?

    // Items.Select(row => row.Property).Distinct
    var distinctCall = Expression.Call(typeof(Queryable), "Distinct", new Type[] { Column.EntityTypeProperty.PropertyType }, selectCall);

    Here's what Tatham saved our bacon. I got turned around and he broke up my crazy one-liner into clearer code. Eilon Lipton helped me get this straight as well.

    In the first expression, the "sortValue" string doesn't matter. It just has to be something so we can make a lambda that is x=>x.

    In the second, we call the standard LINQ OrderBy and give it the (x=>x), or in this example the year=>year, so really,
    Items.Select(brick => brick.Property).Distinct.OrderBy(year => year)

    // colvalue => colvalue
    var sortParam = Expression.Parameter(Column.EntityTypeProperty.PropertyType, "sortValue");
    var columnResultLambda = Expression.Lambda(sortParam, sortParam);
    // Items.Select(row => row.Property).Distinct.OrderBy(colvalue => colvalue)
    var ordercall = Expression.Call(typeof(Queryable), "OrderBy",
    new Type[] { Column.EntityTypeProperty.PropertyType, columnResultLambda.Body.Type },
    distinctCall, columnResultLambda);

    Then we actually CALL the query and fill the dropdown list so here's the whole thing:

    protected void Page_Init(object sender, EventArgs e) {
    var items = Column.Table.GetQuery();
    var entityParam = Expression.Parameter(Column.Table.EntityType, "row");

    // row => row.Property
    var columnLambda = Expression.Lambda(Expression.Property(entityParam, Column.EntityTypeProperty), entityParam);

    // Items.Select(row => row.Property)
    var selectCall = Expression.Call(typeof(Queryable), "Select", new Type[] { items.ElementType, columnLambda.Body.Type }, items.Expression, columnLambda);

    // Items.Select(row => row.Property).Distinct
    var distinctCall = Expression.Call(typeof(Queryable), "Distinct", new Type[] { Column.EntityTypeProperty.PropertyType }, selectCall);


    // colvalue => colvalue
    var sortParam = Expression.Parameter(Column.EntityTypeProperty.PropertyType, "sortValue");
    var columnResultLambda = Expression.Lambda(sortParam, sortParam);

    // Items.Select(row => row.Property).Distinct.OrderBy(colvalue => colvalue)
    var ordercall = Expression.Call(typeof(Queryable), "OrderBy",
    new Type[] { Column.EntityTypeProperty.PropertyType, columnResultLambda.Body.Type },
    distinctCall, columnResultLambda);

    var result = items.Provider.CreateQuery(ordercall);

    foreach (var item in result) {
    if (item != null) DropDownList1.Items.Add(item.ToString());
    }
    }

    So what?

    Conclusion

    image Now I can add [Filter(FilterControl = "Integer")] to any meta-model in any of my ASP.NET Dynamic Data sites and automatically get a nice simple set of Filters, driven completely by attribute with their implementation both separate from my logic and completely generic to my tables.

    For a complete working sample, go check out the VS2008 SP1 Dynamic Data Futures from May of 2009. I modified (barely) the Integer.acsx.cs to add the OrderBy which was flummoxing me. I needed to break it all down to figure out those few lines.

    I also modified the FilterAttribute to add the AuthenticatedOnly attribute like [Filter(FilterControl = "Integer", AuthenticatedOnly = true)] :

    using System;

    namespace Microsoft.Web.DynamicData.Extensions {
    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple=false)]
    public sealed class FilterAttribute : Attribute {

    public FilterAttribute() {
    Order = Int32.MaxValue;
    Enabled = true;
    }

    public string FilterControl { get; set; }

    // Lower values take precedence before greater values
    public int Order { get; set; }

    public bool Enabled { get; set; }

    public bool AuthenticatedOnly { get; set; }
    }
    }

    ...and the AdvancedFilterRepeater to act on that new property:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.DynamicData;
    using System.Web.UI.WebControls;
    using System.Web;

    namespace Microsoft.Web.DynamicData.Extensions {
    public class AdvancedFilterRepeater : FilterRepeater {

    protected override IEnumerable<MetaColumn> GetFilteredColumns() {
    // sort the filters by their filter order as specified in FilterAttribute.
    return Table.Columns.Where(c => IsFilterableColumn(c)).OrderBy(column => column, new FilterOrderComparer());
    }

    protected bool IsFilterableColumn(MetaColumn column) {
    if (column.IsCustomProperty) return false;

    var filterAttribute = column.Attributes.OfType<FilterAttribute>().FirstOrDefault();
    if (filterAttribute != null)
    {
    if (filterAttribute.AuthenticatedOnly == true && (HttpContext.Current.User == null || HttpContext.Current.User.Identity.IsAuthenticated == false)) return false;

    return filterAttribute.Enabled;
    }

    if (column is MetaForeignKeyColumn) return true;

    if (column.ColumnType == typeof(bool)) return true;

    return false;
    }

    private class FilterOrderComparer : IComparer<MetaColumn> {
    public int Compare(MetaColumn x, MetaColumn y) {
    return GetWeight(x) - GetWeight(y);
    }

    private int GetWeight(MetaColumn column) {
    var filterAttribute = column.Attributes.OfType<FilterAttribute>().FirstOrDefault();
    return filterAttribute != null ? filterAttribute.Order : Int32.MaxValue;
    }
    }

    }
    }

    Disclaimer: I did this in .NET 3.5 SP1. I'm still learning this deeper stuff myself, and I'd say that while this meta-LINQ stuff is powerful, it's too complex to generate dynamic LINQ. Remember also that this post is on the outer outer edge of what you'd want to do. It's not representative of a typical ASP.NET Dynamic Data experience, or a typical LINQ experience. However, it is nice to know that the whole thing is incredibly extensible just that if I want to go this deep, I can. I'll go talk to that team and see what they've got planned for the future! If we've missed something, leave it in the comments or email me and I'll update this post. I'll find out both what has been improved for ASP.NET Dynamic Data 4 and for C# 4.

    Related Links

    Good ASP.NET WebForms Resources and Blogs

    Webforms Q&A

    About Scott

    Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

    facebook twitter subscribe
    About   Newsletter
    Sponsored By
    Hosting By
    Dedicated Windows Server Hosting by SherWeb
    Previous Page Page 3 of 4 in the ASP.NET Ajax category Next Page

    Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.