Category Archives: ASP.NET MVC

Test-Drive ASP.NET MVC Review

A few years back I started dallying with test-driven development, but I never fully committed to the practice. This wasn’t because I didn’t believe in the value of TDD; it was more a matter of not completely understanding how to incorporate “test first” into my everyday development. Back in my web forms days, I could point fingers at the framework for my ignorance and laziness. After all, web forms weren’t exactly designed for testability so who could blame me for not embracing TDD in those conditions, right? But when I switched to ASP.NET MVC and quickly found myself fresh out of excuses and it became instantly clear that it was time to get my head around red-green-refactor once and for all or I would regretfully miss out on one of the biggest selling points the new framework had to offer.

Test-Drive ASP.NET MVC

I have previously written about how I learned ASP.NET MVC. It was primarily hands on learning but I did read a couple of ASP.NET MVC books along the way. The books I read dedicated a chapter or two to TDD and they certainly addressed the benefits of TDD and how MVC was designed with testability in mind, but TDD was merely an afterthought compared to, well, teaching one how to code the model, view and controller. This approach made some sense, and I learned a bunch about MVC from those books, but when it came to TDD the books were just a teaser and an opportunity missed.  But then I got lucky – Jonathan McCracken contacted me and asked if I’d review his book, Test-Drive ASP.NET MVC, and it was just what I needed to get over the TDD hump.

As the title suggests, Test-Drive ASP.NET MVC takes a different approach to learning MVC as it focuses on testing right from the very start. McCracken wastes no time and swiftly familiarizes us with the framework by building out a trivial Quote-O-Matic application and then dedicates the better part of his book to testing first – first by explaining TDD and then coding a full-featured Getting Organized application inspired by David Allen’s popular book, Getting Things Done. If you are a learn-by-example kind of coder (like me), you will instantly appreciate and enjoy McCracken’s style – its fast-moving, pragmatic and focused on only the most relevant information required to get you going with ASP.NET MVC and TDD.

The book continues with the test-first theme but McCracken moves away from the sample application and incorporates other practical skills like persisting models with NHibernate, leveraging Inversion of Control with the IControllerFactory and building a RESTful web service. What I most appreciated about this section was McCracken’s use of and praise for open source libraries like Rhino Mocks, SQLite and StructureMap (to name just a few) and productivity tools like ReSharper, Web Platform Installer and ASP.NET SQL Server Setup Wizard.  McCracken’s emphasis on real world, pragmatic development was clearly demonstrated in every tool choice, straight-forward code block and developer tip. Whether one is already familiar with the tools/tips or not, McCracken’s thought process is easily understood and appreciated.

The final section of the book walks the reader through security and deployment – everything from error handling and logging with ELMAH, to ASP.NET Health Monitoring, to using MSBuild with automated builds, to the deployment  of ASP.NET MVC to various web environments. These chapters, like those prior, offer enough information and explanation to simply help you get the job done. 

Do I believe Test-Drive ASP.NET MVC will turn you into an expert MVC developer overnight?  Well, no.  I don’t think any book can make that claim.  If that were possible, I think book list prices would skyrocket!  That said, Test-Drive ASP.NET MVC provides a solid foundation and a unique (and dare I say necessary) approach to learning ASP.NET MVC.  Along the way McCracken shares loads of very practical software development tips and references numerous tools and libraries. The bottom line is it’s a great ASP.NET MVC primer – if you’re new to ASP.NET MVC it’s just what you need to get started. 

Do I believe Test-Drive ASP.NET MVC will give you everything you need to start employing TDD in your everyday development?  Well, I used to think that learning TDD required a lot of practice and, if you’re lucky enough, the guidance of a mentor or coach.  I used to think that one couldn’t learn TDD from a book alone. Well, I’m still no pro, but I’m testing first now and Jonathan McCracken and his book, Test-Drive ASP.NET MVC, played a big part in making this happen.  If you are an MVC developer and a TDD newb, Test-Drive ASP.NET MVC is just the book for you.

Professional ASP.NET MVC 2 Review

What’s up with Ben? All he’s been writing about lately is Ruby, Ruby, Ruby. Doesn’t he work with ASP.NET MVC anymore? Let me assure you that I do – just about every single day and it’s been for quite a while now. Sure, I have been spending time learning Ruby but I’m also constantly developing my primary craft, ASP.NET MVC with C#. So, inspired by yesterday’s virtual MvcConf, I’m going to get back to what I do every day and share a bit about learning ASP.NET MVC with you.

Professional ASP.NET MVC 2 by Scott Hanselman: Book CoverI have told this story before but early in my career, when I wanted to learn a new technology, I’d sit on the floor in the bookstore aisle and work my way through each of the available books on a given subject.  Put in enough time in a bookstore and you can learn just about anything. I used to really enjoy this time but over the years my habits have certainly changed.  Whereas books used to be the only place I could find solutions to my problems, now they may be the very last place I look. Case in point, it wasn’t until I had worked with the ASP.NET MVC 1.0 Framework for more than a year, and I had a few projects and a couple of major deployments under my belt, did I finally read through Steven Sanderson’s Pro ASP.NET MVC Framework. With so many resources at my fingertips (podcasts, screen casts, blogs, stackoverflow, open source projects, www.asp.net) I was able to get up to speed with ASP.NET MVC without reading a single book.  So, I didn’t until late into the game.  

This past April, the day after the RTM release became available, I upgraded my primary MVC project to MVC 2.  Now, a few months later, there are a handful of MVC 2 books on the shelves of those said bookstores and I now offer you a review of Professional ASP.NET MVC 2.  You may know that I have given a lot of praise to Sanderson’s first book so why did I choose Professional ASP.NET MVC 2 over the second edition of Sanderson’s book? Well, the NerdDinner chapter (a.k.a the free bits) of Professional ASP.NET MVC 1.0 offered me a really great MVC primer but I never got around to buying the book.  Not only has the guilt weighed on me a bit, it’s also been quite the cliffhanger.  Having now read through the second edition of Professional ASP.NET MVC 2, I now know that everything worked out for Guthrie, Hanselman, Haack, Conery but I’ve been worried.  (Sorry if I just spoiled the ending for you.)  Anything else?  Yes. Full disclosure, a copy of Professional ASP.NET MVC 2 kind of fell in my lap as Jon gave me a copy on my birthday. He didn’t know it was my big day but it was.  And this leads us into the first thing you’ll undoubtedly notice about the book – there is one more author, Jon Galloway, and the four foreheads on the book cover have been replaced by a blurry bobsled.  Welcome change all around, I think.

As you may have guessed, Professional ASP.NET MVC 2 begins with a new and improved NerdDinner walkthrough. With the book’s first release, I coded up the application from scratch as I followed along, step by step, with the tutorial. I even uncovered and fixed a couple of bugs, but don’t tell.  This new NerdDinner tutorial does a fine job of working in a number features which were introduced with MVC 2.  That’s stuff like HTML Encoding Code Blocks, Strongly Typed HTML Helpers, Templated Helpers, and Client-Side Validation.  There are other new features, and we’ll get to those. If you can get through the tutorial and understand what MVC has to offer, congratulations, you now know enough to be dangerous. But should you stop there? Does the NerdDinner sample application provide you everything you need to become a full-fledged MVC developer?  You might think so, but nope, not even close.  Thus, there’s a lot more book to give you the rest of the scoop.  Think of the NerdDinner sample as the appetizer which whets your appetite, leaving you craving for the main course.  Sorry, I couldn’t help myself…

With that, onto the rest of the book review:

Chapter 2 shares the history of the MVC design pattern and runs through other popular MVC web frameworks you may have seen running in the wild. This chapter also brings attention to the “how” and “why” ASP.NET MVC came into existence. Chapter 3 builds on these same points and explores ASP.NET MVC basics like separation of concerns, maintainability and testability and how ASP.NET MVC relates to both WebForms and ASP.NET as a whole.  You might be thinking, “That’s great but is this going to make me a better MVC developer?”  I was tempted to say that these two chapters aren’t required reading unless you are a complete MVC newbie, but the truth is there’s always value in learning about the background of a technology, pattern, language or framework in order to better understand and master it.  And knowing this information will separate those passionate about MVC from those who merely code against MVC.  So, yes, these chapters will make you a better developer.

Chapter 4 digs into routing and sheds light on a number of sophisticated scenarios. If you have a good handle on routing from your work with MVC 1, you will acknowledge the chapter as being well-written but nothing new is going to jump off the page at you.  However, if you are new to  MVC, you need a strong understanding of outgoing and incoming routes, route patterns and how possible gotchas like Overflow Parameters work and this book does a wonderful job explaining these concepts.  And don’t forget that routing is now exposed in the ASP.NET libraries to be used in WebForms too.  You know, just in case MVC isn’t your cup of tea.

Chapter 5 and 6 dive into controllers and views, respectively.  If you’re new to MVC, the authors walk you through everything you’ll need to know about the C and V in MVC.  For those focusing on the MVC 2 bits, there’s a very nice overview of how requests are handled on the server along with an explanation of how to benefit from the new Asynchronous Controller Actions.  You may have picked up a lot about what views have to offer from the NerdDinner tutorial already but you’d be surprised what else you’ll pick up from this detailed chapter.  Again, for those honing in on MVC 2, give special attention to the new Html.Action and Html.RenderAction helper methods.  Final note on views – I commend the authors for including a rundown of the most popular alternative view engines.  Pretty classy.  On aside, since we’re talking about the V and the C, there isn’t a chapter dedicated to the M, models.  The NerdDinner walkthrough may have sufficiently covered this topic, but the topic was otherwise absent.

Chapter 7 is focused on Ajax, partials and jQuery.  This section is somewhat like a cookbook with lots of recipes.  It’s a little different than the rest of the book as it offers more code examples than written explanation of what the AJAX and jQuery libraries bring to the MVC 2 table. Having worked with MVC for a while now, it’s apparent from Day 1 of development that one needs to have their Ajax and Javascript/jQuery hat on if they want to work with effectively with the framework.  Thankfully Chapter 7 offers a surfeit of practical examples.  Be sure to bookmark this section because you’ll be referring back to it when you need a ratings or autocomplete textbox implementation.

Chapter 8 shows us how one can use Filters to add behavior to action methods.  For the MVC neophytes, filters are powerful.  Soak this chapter in.  For the MVC veterans, be on the look out for the RequireHttps action filter which was introduced with MVC 2. 

Chapter 9 speaks to securing our MVC applications.  I agree with the authors – this should be required reading.  This chapter uses case studies, quotes, short stories, humor, scare tactics, anything and everything to get important points across to the reader.  Listen, security is important.  If you’re a WebForms convert, read carefully as MVC doesn’t hold your hand quite as much as the WebForms world does when it comes to securing your application.  And give thanks to the authors for their willingness to talk about security concerns throughout the book as well dedicate an entire chapter to this topic.  This chapter also includes number of additional reading references which might be worth your time.

Chapter 10 and 11 are dedicated to TDD, unit testing and testable design patterns. The book provides a nice introduction into these topics and solid foundation on how to get started with these design/testing techniques.  Professional ASP.NET MVC 2 includes more than 50 pages of TDD/testing instruction.  Truly, one of the greatest benefits of ASP.NET MVC is testability and if you are new to testing, this book will be a wonderful jumping off point for you.

I’m a bad person. I didn’t read Chapter 12, Best of Both Worlds: Web Forms and MVC Together. I skimmed through it but that’s it.  Obviously there’s demand for this information or it wouldn’t be included in the book but mixing WebForms and MVC doesn’t pertain to me right now. Maybe I’m being shortsighted but I’d like to keep these worlds separate for now. If there comes a time and I need to migrate a WebForms app to MVC, I’ll be sure to come back to this chapter.  For now, it remains unread. Sorry.

Remember how the NerdDinner tutorial sample showed off a number of the new ASP.NET MVC 2 features?  Well, it didn’t catch them all.  That’s where Chapter 13 comes in – offering a roll up of everything new to MVC.  You may actually want to read this chapter first just to become acquainted with the new bits.  That way you can be sure to pick up on the callouts elsewhere in the book.  A couple of important notes – you will find details about Areas in Chapter 13 which you won’t find in any other section. Also there’s an important note about breaking changes with JsonResult when upgrading from MVC 1 to 2.  The change is web vulnerability related and don’t say I didn’t warn you.

A few additional notes about the book which I couldn’t find a good place for elsewhere:

  • Comments from the ASP.NET Product Team are inserted throughout the book. These tips and additional info were my favorite part of the book.  It’s kind of like VH1’s “Behind the Music” to me
  • My only real concern with the NerdDinner tutorial is the emphasis placed on the Entity Framework (EF).  When the original tutorial was published, I encouraged everyone on my team to work through the sample application before diving into their first MVC project.  One of my colleagues was so impressed with MVC that they presented what they learned to the rest of the team.  Guess the name of the presentation. It was “An Overview of the .NET MVC Entity Framework.”  Yikes! In the individual’s defense, they had no prior experience with the .NET stack and frankly the Professional ASP.NET MVC book does drive home the concept of building out one’s model with EF.  There is quick mention of other ORMs which can be used with ASP.NET MVC, but guess which path someone new to .NET will follow?  I don’t feel the use of the Entity Framework is inappropriate in the NerdDinner sample, but I do think it is important to stress (yes, a little more) that EF is not part of the MVC framework and maybe even offer hints as to how one might hook in another ORM if they so choose. This said, I suppose I have the same issue with the references to ASP.NET Forms Authentication, ASP.NET Membership and Role Management APIs, not to mention the Visual Studio Unit Test framework.  [Disclaimer: I am using EF4 and the ASP.NET Membership stuff on my primary project and I think they are both the bees knees.]
  • If you are turning to MVC in hopes to never hear or read about WebForms again, you’re kind of out of luck because Professional ASP.NET MVC offers lots of WebForms commentary.  If you are only interested in MVC, this constant reminder of  WebForms might be a little distracting.
  • In the NerdDinner sample, data-type validation was implemented using DataAnnotations.  DataAnnotations are fine, but I would have liked to read more about validating true business rules (e.g. ensuring passwords are strong, validating a shipping date doesn’t fall on a weekend or holiday, or guaranteeing a submitted email address is unique). Managing this type of validation can be complicated and this topic was glossed over entirely.
  • Your Professional ASP.NET MVC 2 purchase comes with two weeks of TekPub access. You may wish to factor this in when your calculating the true purchase price.

As I alluded to earlier, you may be tempted to read through the NerdDinner tutorial and then go off and code up a storm. Don’t do it! The rest of the book has so much to offer – especially to someone brand new to ASP.NET MVC.  Really, soak up what’s provided in all of the chapters.  And as I climb onto my soapbox, please remember that sample applications like NerdDinner demonstrate basic and generalized implementations in order to highlight new features and ensure focus is firmly set on teaching and learning specific information.  If you wish to really understand ASP.NET MVC 2 development, work through the NerdDinner tutorial, read Professional ASP.NET MVC 2 cover to cover, write lots of your own code, read lots of other people’s code, come up with your own ideas and keep learning from the many other resources which are readily available to you.  I recommend Professional ASP.NET MVC 2 – it’ll get you off to a great start.

Limit Expand/Collapse of jQuery Treeview Folder to Image Click Only

The jQuery Treeview Plugin is a lightweight and flexible transformation of an unordered list into an expandable and collapsible tree. It supports both location and imagecookie based persistence and it’s completely skinnable through CSS. I’ve been using the plugin for a while now. Though the author, Jörn Zaefferer, states it has some shortcoming and it no longer maintained, I haven’t run into any issues on Windows or Mac on various browsers and I recommend you give it a try.  Though there are alternative treeview plugins out there, I haven’t found one better than the jQuery Treeview Plugin. 

By default, the node hitarea includes the expand/collapse icon, the folder icon AND the associated folder text. But let’s say you want to toggle the folder’s open/closed state only if one clicks on the expand/collapse or folder icon.  Well, you’re out of luck unless you’re ready to alter the source itself. 

Here are the steps as explained in responded to a recent stackoverflow.com question:

You’ll need to update the treeview javascript code itself. For Treeview 1.4, comment out the following lines (66-68):

this.filter(":has(>ul):not(:has(>a))").find(">span").click(function(event) {
    toggler.apply($(this).next());
}).add( $("a", this) ).hoverClass();

This will ensure expand/collapse only occurs on the +/- click. The expand all and collapse all feature will continue to work as well, if applicable.

Better yet, you provide a new argument when defining the tree and only if the condition is satisfied do you override the default functionality. For example,

if (settings.expandMode != 'simple'){
    this.filter(":has(>ul):not(:has(>a))").find(">span").click(function(event) {
        toggler.apply($(this).next());
    }).add( $("a", this) ).hoverClass();
}

And your treeview definition might look like this:

$("#tree").treeview({
    animated: "fast",
    persist: "cookie",
    collapsed: true,
    control: "#treecontrol",
    expandMode: "simple" // custom - only toggles per the +/- icon     
})

Hopefully you get the idea and I hope this helps.

Web Deployment Projects and WebConfigReplacementFiles for Custom Sections

I have previously explained how to properly configure your web deployment projects to replace web.config sections.  The example I used was pretty standard – swap out connection strings to support the specific deployment environment.  It worked great, right?  Well, today this technique complete fell short for me as I was dealing with a custom section. 

We recently introduced NServiceBus message sending into our ASP.NET MVC 2 web application.  It’s working so well I can hardly believe it.  Anyway, we put a two configSections in place for the NServiceBus:

  1. <configSections>
  2.   <section name="MsmqTransportConfig"
  3.     type="NServiceBus.Config.MsmqTransportConfig, NServiceBus.Core"></section>
  4.   <section name="UnicastBusConfig"
  5.     type="NServiceBus.Config.UnicastBusConfig, NServiceBus.Core"></section>
  6. </configSections>

  1. <!– NServiceBus –>
  2. <MsmqTransportConfig InputQueue="SendingEndpointQueue"
  3.     ErrorQueue="error" NumberOfWorkerThreads="1" MaxRetries="5"></MsmqTransportConfig>
  4. <UnicastBusConfig>
  5.     <MessageEndpointMappings>
  6.         <add Messages="Project.Messages" Endpoint="ReceivingEndpointQueue"></add>
  7.     </MessageEndpointMappings>
  8. </UnicastBusConfig>

When I attempted to replace these settings, the WDP threw the following build exception:

An error occurred creating the configuration section handler for MsmqTransportConfig: Could not load file or assembly NServiceBus.Core’ or one of its dependencies.  The system cannot find the file specified.

I tried a number of workarounds, but I wasn’t able to resolve the issue.  In the end, I abandoned the WebConfigReplacement technique and started replacing the entire the web.config file using an ExcludeFromBuild command…

  1. <ItemGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
  2.   <ExcludeFromBuild Include="$(SourceWebPhysicalPath)\obj\**\*.*" />
  3.   <ExcludeFromBuild Include="$(SourceWebPhysicalPath)\**\.svn\**\*.*" />
  4.   <ExcludeFromBuild Include="$(SourceWebPhysicalPath)\**\.svn\**\*" />
  5.   <ExcludeFromBuild Include="$(SourceWebPhysicalPath)\**\*.csproj" />
  6.   <ExcludeFromBuild Include="$(SourceWebPhysicalPath)\**\*.user" />
  7.   <ExcludeFromBuild Include="$(SourceWebPhysicalPath)\bin\*.pdb" />
  8.   <ExcludeFromBuild Include="$(SourceWebPhysicalPath)\Notes.txt" />
  9.     
  10.   <!– WebConfigReplacement validates configSection references before
  11.         replacement and NServiceBus.Core or dependencies could not be found.
  12.         Now we are excluding web.config from build as it will be
  13.         manually replaced in BeforeBuild step.   –>
  14.   <ExcludeFromBuild Include="$(SourceWebPhysicalPath)\web.config" />
  15. </ItemGroup>

…and a BeforeBuild Copy task…

  1. <Target Name="BeforeBuild">
  2.   <Copy SourceFiles="$(SourceWebPhysicalPath)\Config\Web.Int.config"
  3.         DestinationFiles="$(CopyBeforeBuildTargetPath)\web.config" />
  4. </Target>

This approach considerably reduced the number of configuration files which I need to manage.  And it works too.  I’m not saying you should change your approach, but be aware of the potential issue if you start to implement custom configuration sections. 

Note: I’ve read that the WebConfigReplacement technique will only work for types which have been installed in the GAC.  I added NServiceBus.dll and NServiceBus.Core.dll to the GAC and that didn’t make much difference.  Perhaps NServiceBus.Core dependencies are the culprit?  I also read that some folks have implemented their own msbuild task to do a simple text replacement of the configSource property to solve this problem. The configSource property isn’t made available by NServiceBus and I didn’t go ahead and add it.Lazy me. Last thought: I tried many things but flipping the <ValidateWebConfigReplacement> switch to false would fix everything.  It didn’t.

jQuery Context Menu Plugin and Capturing Right-Click

I was thrilled to find Cory LaViska’s jQuery Context Menu Plugin a few months ago. In very little time, I was able to integrate the context menu with the jQuery Treeview.  I quickly had a really pretty user interface which took full advantage of limitedimage real estate.  And guess what.  As promised, the plugin worked in Chrome, Safari 3, IE 6/7/8, Firefox 2/3 and Opera 9.5.  Everything was perfect and I shipped to the Integration Environment.

One thing kept bugging though – right clicks aren’t the standard in a web environment. Sure, when one hovers over the treeview node, the mouse changed from an arrow to a pointer, but without help text most users will certainly left-click rather than right.

As I was already doubting the design decision, we did some Mac testing.  The context menu worked in Firefox but not Safari.  Damn.  That’s when I started digging into the Madness of Javascript Mouse Events.  Don’t tell, but it’s complicated.  About as close as one can get to capture the right-click mouse event on all major browsers on Windows and Mac is this:

    if (event.which == null)
       /* IE case */
       button= (event.button < 2) ? "LEFT" :
                 ((event.button == 4) ? "MIDDLE" : "RIGHT");
    else
       /* All others */
       button= (event.which < 2) ? "LEFT" :
                 ((event.which == 2) ? "MIDDLE" : "RIGHT");

Yikes.  The content menu code was simply checking if event.button == 2.  No problem.  Cory offers a jQuery Right Click Plugin which I’m sure works for windows but probably not the Mac either.  (Please note I haven’t verified this.)

Anyway, I decided to address my UI design concern and the Safari Mac issue in one swoop.  I decided to make the context menu respond to any mouse click event.  This didn’t take much – especially after seeing how Bill Beckelman updated the library to recognize the left click.

First, I added an AnyClick option to the library defaults:

  1. // Any click may trigger the dropdown and that's okay
  2. // See Javascript Madness: Mouse Events – http: //unixpapa.com/js/mouse.html
  3. if (o.anyClick == undefined) o.anyClick = false;

And then I trigger the context menu dropdown based on the following conditional:

if (evt.button == 2 || o.anyClick) {

Nothing tricky about that, right?  Finally, I updated my menu setup to include the AnyClick value, if true:

  1. $('.member').contextMenu({ menu: 'memberContextMenu', anyClick: true },
  2.             function (action, el, pos) {
  3.                 …

Now the context menu works in “all” environments if you left, right or even middle click. 

*Opera 9.5 has an option to allow scripts to detect right-clicks, but it is disabled by default. Furthermore, Opera still doesn’t allow JavaScript to disable the browser’s default context menu which causes a usability conflict.

Render MVCContrib Grid with No Header Row

The MVCContrib Grid allows for the easy construction of HTML tables for displaying data from a collection of Model objects. I add this component to all of my ASP.NET MVC projects.  If you aren’t familiar with what the grid has to offer, it’s worth the looking into.

What you may notice in the busy example below is the fact that I render my column headers independent of the grid contents.  This allows me to keep my headers fixed while the user searches through the table content which is displayed in a scrollable div*.  Thus, I needed a way to render my grid without headers. That’s where Grid Renderers come into play. 

  1. <table border="0" cellspacing="0" cellpadding="0" class="projectHeaderTable">
  2.     <tr>
  3.         <td class="memberTableMemberHeader">
  4.             <%= Html.GridColumnHeader("Member", "Index", "MemberFullName")%>     
  5.         </td>
  6.         <td class="memberTableRoleHeader">
  7.             <%= Html.GridColumnHeader("Role", "Index", "ProjectRoleTypeName")%>     
  8.         </td>       
  9.         <td class="memberTableActionHeader">
  10.             Action
  11.         </td>
  12.     </tr>
  13. </table>
  14. <div class="scrollContentWrapper">
  15. <% Html.Grid(Model)
  16.     .Columns(column =>
  17.             {
  18.                 column.For(c => c.MemberFullName).Attributes(@class => "memberTableMemberCol");
  19.                 column.For(c => c.ProjectRoleTypeName).Attributes(@class => "memberTableRoleCol");
  20.                 column.For(x => Html.ActionLink("View", "Details", new { Id = x.ProjectMemberId }) + " | " +
  21.                                 Html.ActionLink("Edit", "Edit", new { Id = x.ProjectMemberId }) + " | " +
  22.                                 Html.ActionLink("Remove", "Delete", new { Id = x.ProjectMemberId }))
  23.                     .Attributes(@class => "memberTableActionCol").DoNotEncode();
  24.             })
  25.     .Empty("There are no members associated with this project.")
  26.     .Attributes(@class => "lbContent")
  27.     .RenderUsing(new GridNoHeaderRenderer<ProjectMemberDetailsViewModel>())
  28.     .Render();
  29. %>
  30. </div>
  31. <div class="scrollContentBottom">
  32.     <!– –>
  33. </div>
  34. <%=Html.Pager(Model) %>

Maybe you noticed the reference to the GridNoHeaderRenderer class above?  Yep, rendering the grid with no header is straightforward.  

  1. public class GridNoHeaderRenderer<T> :
  2.     HtmlTableGridRenderer<T> where T: class
  3. {
  4.     protected override bool RenderHeader()
  5.     {
  6.         // Explicitly returning true would suppress the header
  7.         // just fine, however, Render() will always assume that
  8.         // items exist in collection and RenderEmpty() will
  9.         // never be called.  
  10.         // In other words, return ShouldRenderHeader() if you
  11.         // want to maintain the Empty text when no items exist.
  12.         return ShouldRenderHeader();
  13.     }
  14. }

Well, if you read through the comments, there is one catch.  You might be tempted to have the RenderHeader method always return true.  This would work just fine but you should return the result of ShouldRenderHeader() instead so the Empty text will continue to display if there are no items in the collection.

The GridRenderer feature found in the MVCContrib Grid is so well put together, I just had to share. 

* Though you can find countless alternatives to the fixed headers problem online, this is the only solution that I’ve ever found to reliably work across browsers. If you know something I don’t, please share.

Deploying ASP.NET Web Applications

In this episode, Noah and I explain how to use Web Deployment Projects to deploy your web application. This screencast will get you up and running, but in a future screencast, we discuss more advanced topics like excluding files, swapping out the right config files per environment, and alternate solution configurations. 

This screencast (and the next) are based on a write-up I did about ASP.NET Web Application deployment with Web Deployment Projects a while back.  Multi-media knowledge sharing.  You have to love it!

This is the first video hosted on Vimeo.  What do you think?

ASP.NET Membership Provider Setup

In this screencast, Noah and I show you how to quickly get started with the ASP.NET Membership Provider.  We’ll take you through basic features and setup and walk you through membership table creation with the ASP.NET SQL Server Wizard.

I’ve written about the ASP.NET Membership Provider and setup before.  If you missed the post, this introductory video may be for you.

 

 

This is one of our first screencasts.  If you have feedback, I’d love to hear it.