BusinessRx Community

Dedicated to the advancement of software, technology and the people who devote their lives to it.

Welcome to BusinessRx Community Sign in | Join | Help
in Search

BusinessRx Reading List

These blog entries are written by industry experts and leaders. We consider this content to be a good read for any software developer or web technologist.

December 2007 - Posts

  • January MSDN Toolbox Column Online

    The January MSDN Magazine is now available online and includes the first of three Toolbox columns that I wrote (filling in for Scott Mitchell). I wanted to focus on open source tools and agile books as much as possible during this opportunity so for the first column I featured:

    • MbUnit - Which I have been a fan of for quite some time.
    • Rhino.Mocks - The best of the .NET mock frameworks in my opinion.
    • dotTrace - The one commercial tool for this column, and one of the few commercial tools that I swear by.
    • Continuous Integration - Cool to see a book focused just on CI, and from AW Fowler series to boot.

    Already saw some good feedback on the column, would love to hear what you think.

    -James

  • New Job with McKesson and Other News

    Its been a very long time since my last post, but here I am again at last.  I just started a new job with McKesson this week as an ASP.NET Architect, where I'll be working on internal tools to support sales and marketing.  McKesson is currently 18th on the Fortune 50 list, being the largest health-care company, and I'll be working in their Alpharetta, GA, office.  I'm very excited about this change, both for the short-run and long-term, and I'm calling this a birthday present to myself since I just turned 40.  I still believe Mimsware to be the best Atlanta-based consulting company, and I highly recommend them, but I decided I wanted a more permanent role.  And McKesson isn't just any company -- they are also big enough that I can make a career with them and still find opportunity for change if I desire.  Its also a pleasant drive for me, taking back-roads from Woodstock, GA, although its a big change for myself and my family to not work from home.

    So that explains this post, but what have I been doing since the last one?  I suppose the easiest explanation is to simply say that I've been living!  My focus has very much been my family, and much less on being a tech guru, which was only a coincidence due to having lots of time a few years ago.  My wife Jenny is still cancer-free, and now reconstructive surgery is done, but earlier this year there was a tough time dealing with a reconstructive surgery that didn't heal which led to a much bigger surgery than expected.  But she's fine now and back at her job as a nurse in a cardiac cath lab.  Meanwhile, my kids are growing -- Tori is 10 and still enjoys dancing, while Zack is 9 and enjoys video games, and both stay busy with friends.  We also got a Wii, which is finally a game system we all can play together -- and I count it as real exercise in air-conditioning with no allergens!  I got Mario and Sonic Olympics for my birthday and even got a little sore.

    So what about the latest MS technology and my own endeavors like my O/RM?  I never set out to spend time on forums or to create a popular O/R Mapper -- I simply had a lot of free time several years back that I used wisely.  I love learning new technology, and I like to build something real that is useful to myself as part of that process, which is how it all started out.  I then discovered that others also found things I did very useful, which encouraged me to do even more, but then my O/RM took on a life of its own.  I found that I was no longer just learning or making something for myself, instead I was adding features for others and doing a lot of support also.  So Brian DeMarzo has taken my O/RM open source, and I'm just going to once again play with the latest MS stuff, like Linq to Sql and MVC for ASP.NET.  I may yet build something I think is useful enough to share with others, or at least learn enough for a new post, but if I don't then that's OK too.

  • LINQ and the DTO Tax

    Jean-Paul Boodhoo's post on MappingEnumerable<T> reminds me how DTOs sometimes require an inordinate amount of effort for the simple jobs they perform. You need to define them, instantiate them, map them, groom them, and take them for walks twice a day. It always felt to me that the language should help to reduce the DTO tax, somehow.

    In JP's post, he is using the following interface to define a mapper responsible for transforming domain objects into data transfer objects (screen bound DTOs, I'm assuming).

    public interface IMapper<Input, Output>
    {
        Output MapFrom(Input input);
    }

    Where a simple implementation might look like:

    public class DepartmentMapper : IMapper<Department, DepartmentDisplayItemDTO>
    {
        
    public DepartmentDisplayItemDTO MapFrom(Department input)
        {
            
    return new DepartmentDisplayItemDTO()
                {
                    ID = input.ID,
                    Name = input.Name
                };
        }
    }

    LINQ takes some of the grunge work out of mapping DTOs. For example, if you aren't injecting a mapping strategy at runtime, LINQ can transform a Department object into a Department DTO in place:

    IEnumerable<Department> departments = departmentRepository.GetAllDepartments();
     
    return
        from d in departments
       
    select new DepartmentDisplayItemDTO() { ID = d.ID, Name = d.Name };

    Alternatively, when there is a mapper in play for more convoluted mapping logic:

    IEnumerable<Department> departments = departmentRepository.GetAllDepartments();
    return
      from d in departments
     
    select departmentDisplayItemDTOMapper.MapFrom(d);

    ... which is equivalent to:

    IEnumerable<Department> departments = departmentRepository.GetAllDepartments();

    return departments.Select(d => departmentDisplayItemDTOMapper.MapFrom(d));

    I think LINQ eliminates the need for JP's MappingEnumerable<T> (a DTO tax), while keeping the advantage of deferred execution (an item isn't mapped until it is enumerated).

  • Creating Silverlight Player Templates

    Pete Brown is a local guy with a great deal of Silverlight content on his blog, and some cool wallpaper downloads. Pete pointed to the Expression Encoder White Paper today. The document describes itself as providing the "best practices and methods for providing integrated and branded media player skins for Microsoft Silverlight".

    After a quick read, I'd say the document does a fine job describing how to build custom skins and templates for the Silverlight media player. The techniques described in the document will also work with the ASP.NET Futures <asp:Media> control. Both of those controls provide additional features (like the standard VCR controls) on top of the Silverlight <MediaElement/>.

    The document gets confusing, however, when it describes the class hierarchy behind the player. For instance:

    _Button

    Players generally require buttons. This is javascript functionality bound to XAML elements and handles mouse events and animations.

    The _Button class handles binding the events and animations to the XAML. The intention is for you to handle the events you are interested in.

    See the example above in "Roll your own controls" for details on how to implement your own buttons making use of _Button.

    Cognitive dissonance comes into play several times in the document when the text describes how to consume underscored type like _Button. By convention, ASP.NET AJAX prefixes private fields, methods, and types with an underscore. When adding a new button to the player that is not one of the "well known" buttons (like the PlayPauseButton), it feels like a hack to instantiate or derive from an underscored class.

    Personally, I've been a bit frustrated at the lack of extensibility in the player control provided by Expression. There are no public methods available to override the behavior of the Next, Previous, and VideoWindow button clicks, for example. I hope the ASP.NET Futures version of the control will flesh itself out a little more in the future.

  • Update on 22books

    I launched 22books six days ago now and wanted to blog a brief update. So far I have been pretty happy with the response, most people have complimented the UI, and most importantly lots of people have told how easy it is use. I submitted the site to a handful of web application directory style sites and blogs and that has driven a little bit of traffic, right around 2,500 visits. I plan on doing a post about what has worked and what hasn't from the promotion stand-point.

    I just pushed out an update to the site that allows you to assign a category to your list (like favorites, author list, etc). One of the categories was inspired by Ben Carey who created a list called "Books that change my life". Another user followed his example and I really liked the idea so I wanted to encourage more people to do it.

    I have a many more features planned (and need to update the site to Rails 2.0), but I am going to take some time off for the holidays (although I might work some after Christmas).

    -James

  • Disabling the Submit Button Until a CheckBox is Checked

    A little over a year ago I created two ASP.NET validation controls that are missing from the ASP.NET Toolbox: CheckBoxValidator and CheckBoxListValidator. As their names imply, these validation controls validate a single CheckBox (ensuring its either checked or unchecked, depending on a property setting) and ensures that a specified minimum number of options are checked from a CheckBoxList. For some reason, the built-in ASP.NET validation controls do not validate against CheckBoxes.

    I recently updated the CheckBoxValidator control so that a page developer can optionally associate a Button, LinkButton, or ImageButton with the validator. In such a case, the CheckBoxValidator injects client-side script so that the associated button is disabled when the CheckBox is in the inappropriate check state, and enabled otherwise. The following screen shot illustrates this concept. On the left, the CheckBox is unchecked so the Submit button is grayed out; on the right, the CheckBox has been checked so the Button has become enabled.

    You can read more about this enhancement at Disabling the Submit Button Until a CheckBox is Checked. The complete source code and a simple working demo is available here.

  • Inheritance and the Entity Framework

    Here is an excerpt of the schema for the top level of OdeToCode:

    The Community_ContentPages table carries all of the data needed by every type of content – like moderation flags, published date, and owner ID. Community_Articles carries just the extra information needed for a published article – like the article text itself.

    Inside the code, Article and Book classes derive from ContentPage. Inheritance simplifies the implementation, because a great deal of the business logic applies to all the different types of content objects. For instance, the moderation and approval rules apply to articles, book reviews, comments, images, and other entities that all derive from ContentPage.

    Mapping to Objects

    Inheritance mapping is one good litmus test for the capabilities of an ORM product. LINQ to SQL, for example, only handles one of the three common strategies for modeling inheritance in an RDBMS – the "table per class hierarchy" strategy, which doesn't help me in this scenario. Most full featured OR/M products, like NHibernate, support multiple strategies, including the "table per subclass" strategy I need.

    The Entity Framework documentation includes some pointers on table per subclass mapping (known as "table per type" or TPT in EF terminology). Although the EF designer is easy for getting tables and columns spit out into a mapping file, I found working with the designer a bit tedious. Trying to model inheritance using the designer created build errors, so I did most of the XML editing by hand. The key to TPT mapping is:

    • Use a BaseType attribute when defining EntityTypes in the conceptual schema.
    • Define a single Key column only on the base EntityType in the conceptual schema.
    • In the mapping specification, combine the EntityTypeMapping tags for all derived types into a single EntitySet:
    <EntityContainerMapping StorageEntityContainer="dbo"
              
    CdmEntityContainer="OdeToCodeEntityContext">
      <EntitySetMapping Name="ContentPages">
        <EntityTypeMapping
              
    TypeName="IsTypeOf(OdeToCode.Core.Entities.ContentPage)">
          ...
        
    </EntityTypeMapping>
        <EntityTypeMapping
              
    TypeName="IsTypeOf(OdeToCode.Core.Entities.Article)">
          ...
        
    </EntityTypeMapping>
      </EntitySetMapping>
    </
    EntityContainerMapping>


    Querying

    Once the XML work is done, it's relatively easy to pull out persisted entities.

    Given the following DTO:

    public class ArticleSummary
    {
        
    public int ID { get; set; }
        
    public string Title { get; set; }
    }

    I can use the following LINQ query to pull out only Article objects. The trick is the OfType() operator:

    IQueryable<ArticleSummary> articles =
       
    from article in context.ContentPages.OfType<Article>()
       
    select new ArticleSummary { ID = article.ID,
                                    Title = article.contentPage_title };

    Although I still have some reservations about EF, I'm warming up to the framework...

    *If the naming convention strikes you as odd, then remember the schema was designed to work in a shared hosting environment where a single database might need to support multiple applications. The Community prefix helps to avoid naming collisions. An equivalent design today could use schemas in SQL 2005.

  • December 16th Links: ASP.NET, ASP.NET AJAX, ASP.NET MVC, VS, .NET, IIS7, WPF

    Here is the latest in my link-listing series.  Also check out my ASP.NET Tips, Tricks and Tutorials page for links to popular articles I've done myself in the past.

    ASP.NET

    ASP.NET AJAX

    ASP.NET MVC

    • PagedList<T> Support: Rob Conery posts a sample implementation of a pageable List<T> implementation that I showed in my original ASP.NET MVC demo at the Alt.net conference.

    Visual Studio

    • Spell Checker for Visual Studio: My team recently shipped a cool new Visual Studio add-in that provides spell checking support.  In addition to supporting spell checking within HTML files, it also supports spell checking within JavaScript, VB, C# and ASP.NET comments.  Works with both VS 2005 and VS 2008.

    • World of Warcraft for Visual Studio: A cool new add-on that enables support for building World of Warcraft game extensions using Visual Studio.  Definitely something to check out if you play World of Warcraft.

    • VS 2008 Color Schemes: Thomas Restrepo has posted some nice Visual Studio color scheme templates you can use to customize your text editor settings.

    Debugging .NET

    • Getting Started with WinDBG Par1 and Part2: Johan Berglin has an excellent set of posts that detail how you can use the WinDBG debugger to drill into a running ASP.NET application and analyze it to see what it is doing.  Microsoft Product Support uses this tool when helping debug deployed applications in production.  It is extremely powerful and something you might want to learn.

    • Automated .NET Hang Analysis: Tess Ferrandez from the ASP.NET Product Support team has a great blog post that describes an automated hang analysis tool she has written that uses WinDBG to pinpoint the root cause of common hangs with .NET applications.  Her blog is an excellent one to subscribe to - and is full of great debugging tips and tricks.

    IIS 7.0

    • Behavior Changes for ASP.NET applications running in Integrated Mode on IIS 7.0: Mike Volodarsky from the IIS team has a great blog post that details behavior changes for ASP.NET applications when they run in "integrated mode" on IIS 7.  "Integrated mode" enables ASP.NET developers to take advantage of much tighter integration with IIS - and enables a host of additional scenarios (richer URL rewriting, integrated authentication/authorization, etc).  If one of the behavior changes listed in Mike's document impacts your application, you can optionally change the application to run in "Classic Mode" - which maintains the same ASP.NET behavior as with IIS6.

    • Professional IIS 7 and ASP.NET Integrated Programming: Shahram Khosravi has recently written a great new book that describes how to take advantage of the new IIS7 "integrated mode" features with ASP.NET.  A great book to read if you are looking to take advantage of the new IIS7 features:

    WPF

    Hope this helps,

    Scott

    • New ASP.NET Dynamic Data Support

      The ASP.NET 3.5 Extensions CTP we shipped this past weekend contains a bunch of great new features.

      One of the cool new features is something we call "ASP.NET Dynamic Data Support".  In a nutshell this enables you to really quickly build data driven web-sites that work against a LINQ to SQL (and in the future LINQ to Entities) object model - and optionally allows you to-do this without having to build any pages manually.

      The best way to see this in action is to watch David Ebbo's awesome 17 minute screen-cast:

      You can also follow the steps below to easily get started and use the dynamic data support:

      Step 1: Create a ASP.NET Dynamic Data Site:

      Once you have the ASP.NET 3.5 Extensions CTP release installed, you can use VS 2008 or the free Visual Web Developer 2008 Express to create a new Web Site or Web Application Project that has the ASP.NET dynamic data support enabled:

      This will create a new web-site you can use that has some default template files in them, along with CSS style-sheets you can use to customize the look and feel of them:

      Step 2: Add a LINQ to SQL Data Model to Your Site

      LINQ to SQL is an O/RM (object relational mapper) that ships in .NET 3.5, and which allows you to model a relational database using .NET classes.  You can then query the database using LINQ, as well as update/insert/delete data from it.  LINQ to SQL fully supports transactions, views, and stored procedures.  It also provides an easy way to integrate data validation and business logic rules into your data model.

      The easiest way to get started with an ASP.NET Dynamic Data site is to add a new LINQ to SQL data model to your project (right-click->add new item->LINQ to SQL Classes item).  This will bring up the LINQ to SQL class designer.  Drag database tables from your server explorer to define a set of classes (with relationships) for your database schema:

      Step 3: Enable Dynamic Templates in Your Project:

      By default ASP.NET Dynamic Data projects provide built-in support for creating automatic "scaffolding" views of your LINQ to SQL and LINQ to Entities data models.  Dynamic Data projects include template pages and user controls that can automatically create built-in data browsing/editing/selection/deleting UI that is dynamically constructed at runtime based on the LINQ to SQL or LINQ to Entities data model you've added to your project.

      To enable this auto-scaffolding support, open the web.config file of your project, search for the "dynamicData" section within it, and set the "enableTemplates" attribute to "true":

      Note: this auto-scaffolding feature is currently turned off by default for security reasons (we want you to be explicit about turning it on). 

      Note: as you can see above, the ASP.NET dynamic data section provides optional URL mapping support that allows you to customize the URLs for your dynamic scaffold pages to be in whatever URL format you want.

      Step 4: Run Your Site

      Hit F5 to run your project.  You'll by default be taken to a default.aspx page that lists all of the table objects in your data model:

      Note: the default.aspx home-page is in the project - if you don't like how it looks just open it up and edit it however you want.

      Clicking on any of the table names in the list above will take you to a dynamic data page that lists the data within it:

      The default data view pages automatically create functional data navigation UI that includes built-in data paging and editing support (and are ASP.NET AJAX enabled):

      The data view pages automatically infer relationships between your related objects and provide automatic filtering support:

      The data view pages also automatically show relationships between your objects and allow users to easily navigate amongst them.  For example, notice how the Category column for products allows me to navigate to the category details for a specific product:

      The data view pages also enable automatic selection, editing and delete support.  Notice below how when in inline edit mode they automatically infer friendly foreign key names (allowing you to edit the "Category" and pick a name from a dropdownlist instead of having to specify a "CategoryID" integer):

      All of this works without having to create a single custom .aspx page or write any custom code.  All of the web UI is created dynamically off of your LINQ to SQL or LINQ to Entities data model.

      Step 5: Customizing the Site Further

      Having all of the above functionality work out of the box against your ORM data model is great for quickly getting your site up and running.  Once you get the basic site experience working, you can optionally go in and fully customize it - both at the data validation/business logic level as well as at the UI layer.

      You can add standard LINQ to SQL data model and business validation rules to your data model in order to enforce constraints.  The dynamic data pages will automatically work off of this logic, and provide appropriate error messages and validation UI based on them. 

      You can also optionally go in and customize the UI of any of the data pages you want.  Dynamic data projects allow you to customize the default look and feel of all data pages on the site, as well as customize the default look and feel of all column types used on the site.  You can customize both of these via the default template files added under the "/App_Shared" folder when you create a new dynamic data project:

      Simply edit any of the files above to customize the default data page views and/or default data column appearances. 

      You can also then optionally override the UI of specific data view pages by explicitly adding a .aspx page that maps to it in your project.  For example, I could override the default ListDetails behavior for Products by adding a \Products\ListDetails.aspx page to my project:

      You can then add any standard ASP.NET data control to the page.  You can also use the new dynamic data aware ASP.NET data controls that ship in the ASP.NET 3.5 Extensions CTP to the page.  These allow you to completely customize the look and feel of the UI - while still using the new dynamic meta-data provider to infer relationships and meta-data about your data model classes for default behavior.

      Learning More

      The above walk-through only touches on a few of the scenarios and capabilities you can enable with ASP.NET Dynamic Data Projects.  To learn more:

      1. Watch David's webcast
      2. Check out the ASP.NET Dynamic Data QuickStarts
      3. Subscribe to David Ebbo's, Scott Hunter's, and Marcin Dobosz's blogs
      4. Visit the ASP.NET Dynamic Data Forum to ask questions

      To learn more about LINQ to SQL and how you can use it to create data model classes, also check out my previous blog posts below:

      You can also watch the great LINQ and LINQ to SQL "How do I?" videos on the www.asp.net site here.

      Hope this helps,

      Scott

    • Announcing 22books

      If you have known me for very long you probably realized at some point that I have a ton of ideas and crazy plans, but I usually have a pretty hard time following through. This is most evident in the number of domain names and half-written projects I have laying around. Well, I think I may have finally broken myself of this habit. I followed through and got AutoTest.NET out, even if it still needs lots of work. I took over The Lounge, even though that was kind of cheating since I just had to install and configure existing code.

      200712121939

      Now I am ready to launch 22books, the rails side project I have been working on for a couple months. It's a pretty simple site that is centered around the creating and sharing of book lists. There are plenty of book sites out there, but 22books is different than most because I focused more on just book lists and less about cataloging all of your books.

      I approached this project with a couple goals. The first goal was to give people a place to easily create book lists, but the second goal was to create a large set of standard lists. Standard lists would be things like a complete list of Kurt Vonneguts works, or Booker Prize winnders, etc.

      I tried to make the site as simple and easy to use as possible, I will add more features in future releases, but I hope to keep the simplicity.

      Check it out and let me know what you think. I am going to blog this weekend about what tools/plugins I used to build it.

      -James

    • ALT.NET in Baltimore and D.C.

      Matthew makes the announcement in a blog post:

      So, you may ask yourself, there are already groups out in the DC area, such as CapArea.NET, RockNUG, CMAP, DC XP Users group among others. They are great user groups that put on a lot of great events that I have attended time and time again and at some point presented at one of them. It's my belief that this group can supplement them nicely and help each other out. Many of these groups spend a lot of time talking about the new things coming from Microsoft. That's a very good thing, but that's not what we're aiming for. The goal of this group is to form very active discussion groups and find new and better ways to develop software. This group practices the Open Space Technology and encourages people to bring topics to talk about.

      First meeting is this Thursday, Dec 13th.

      Join the mailing list, and watch for the roaming meeting to reach a location near you in the D.C. / Baltimore metropolitan area.

    • Taking over The Lounge

      If you ever look at my blog in a browser you might have noticed an ad on the right sidebar from The Lounge advertising network. The Lounge is an advertising network that was created by Kevin Fricovsky. About a week ago I talked Kevin into turning The Lounge over to me since he is going to be too busy in other ventures. Since then I have been working feverishly to get it all up and running on my servers and getting the publishers to switch over there code.

      If you haven't seen The Lounge before the basic idea is that we have rooms of publishers and advertisers can buy space in those rooms. Unlike conventional advertising we don't sell ads by the impression or click, but instead you buy 30 days of your ad being shown. If we have 9 publishers we could have up to 9 advertisers with each of their ads rotating on all 9 sites.

      I am pretty excited about this new opportunity and look forward to growing the .NET room as well as expanding out into new rooms.

      My current goal is to book up the current .NET room so if you work for a company that might be interested in advertising there please drop me a line!

      -James

    • Good Stuff #4

      Its so warm here it almost seems like a sin.

      -James

    • ASP.NET Version 3.5's Web.config File

      If you have had a chance to try out Visual Studio 2008, you likely have seen the rather bulky Web.config file Visual Studio generates when creating a new ASP.NET website or when converting an ASP.NET 2.0 website to 3.5. In one of Scott Guthrie's blog entries a commenter named Mike asked Scott for a rundown of the markup in the default Web.config file generated for version 3.5 ASP.NET applications.

      I went ahead and created such an article: Dissecting ASP.NET Version 3.5's Web.config File.

      Enjoy!

    • Good Stuff #3

      Busy day today, got ferret up and running which was very cool.

      -James

    • ASP.NET 3.5 Extensions CTP Preview Released

      Earlier today we released the first CTP preview of an "ASP.NET 3.5 Extensions" release that we've been working on (click here to read my previous post about our product roadmap).  This release brings additional runtime functionality to ASP.NET and .NET 3.5.  You can download it here (if you are using the MVC features also click here to download the MVC Toolkit extras).

      This first ASP.NET 3.5 Extensions preview release includes:

      • ASP.NET AJAX Improvements: New ASP.NET AJAX features in the ASP.NET 3.5 Extensions release include better browser history support (back/forward button integration, and server-side history management support), improved AJAX content linking support with permalinks, and additional JavaScript library improvements.
      • ASP.NET MVC: This model view controller (MVC) framework for ASP.NET provides a structured model that enables a clear separation of concerns within web applications, and makes it easier to unit test your code and support a TDD workflow. It also helps provide more control over the URLs you publish in your applications, and more control over the HTML that is emitted from them.
      • ASP.NET Dynamic Data Support: The ASP.NET 3.5 Extensions release delivers new features that enable faster creation of data driven web sites.  It provides a rich scaffolding framework, and will enable rapid data driven site development using both ASP.NET WebForms and ASP.NET MVC.
      • ASP.NET Silverlight Support: With the ASP.NET 3.5 Extensions release we'll deliver support for easily integrating Silverlight within your ASP.NET applications.  Included will be new controls that make it easy to integrate Silverlight video/media and interactive content within your sites.
      • ADO.NET Data Services: In parallel with the ASP.NET Extensions release we will also be releasing the ADO.NET Entity Framework.  This provides a modeling framework that enables developers to define a conceptual model of a database schema that closely aligns to a real world view of the information.  We will also be shipping a new set of data services (codename "Astoria") that make it easy to expose REST based API endpoints from within your ASP.NET applications.

      We will be publishing many blog posts and videos discussing the new features in the weeks and months ahead.  Click here to check out an initial set of Quickstart Samples that cover some of the new preview features. 

      Below you can find links to a few tutorial posts I've done (and a cool TDD one by Phil Haack) that cover the new ASP.NET MVC Framework option.  I'll be doing more posts on the non-MVC features in the extensions release in the weeks ahead as well:

      To ask questions or get help, please visit these forums on http://forums.asp.net

      Hope this helps,

      Scott

    • The Greatest Challenge in Software Development

      ... is choosing the right names.

      Local variables need names. Instance variables need names. Methods need names, too, as do classes, columns, delegates, events, files, forms, parameters, projects, products, services, styles, tables, and of course – namespaces. Namespaces are nothing but a name! So many names, and so few words to use.

      I was thinking about the amount of mental effort I expend in basic programming activities – like picking control structures (foreach versus do-while), or data structures (stacks versus lists), versus the amount of effort I expend to name all the abstractions in the simplest piece of software. Loops and structures are easy – naming requires a great deal of time and thought.

      After all these years of thinking about names, I still struggle to pick the perfect name. Naming is a skill I need to improve - because names are important. I can use all the right patterns, have 100% test coverage, exceed every performance requirement, and still feel like I've failed if the names produce a piece of software that looks amorphous carbon:

      Bad names kill good software by making the software un-maintainable.

      Here are some interesting reads on naming:

      I'd like to find more. Know of any others good ones?

    • ASP.NET 3.5 Extensions Preview is out

      (that's MVC)

      get it here.

      -James

    • ASP.NET MVC Framework (Part 4): Handling Form Edit and Post Scenarios

      The last few weeks I have been working on a series of blog posts that cover the new ASP.NET MVC Framework we are working on.  The ASP.NET MVC Framework is an optional approach you can use to structure your ASP.NET web applications to have a clear separation of concerns, and make it easier to unit test your code and support a TDD workflow.

      The first post in this series built a simple e-commerce product listing/browsing site.  It covered the high-level concepts behind MVC, and demonstrated how to create a new ASP.NET MVC project from scratch to implement and test this e-commerce product listing functionality.  The second post drilled deep into the URL routing architecture of the ASP.NET MVC framework, and discussed both how it worked as well as how you can handle more advanced URL routing scenarios with it.  The third post discussed how Controllers interact with Views, and specifically covered ways you can pass view data from a Controller to a View in order to render a response back to a client.

      In today's blog post I'm going to discuss approaches you can use to handle form input and post scenarios using the MVC framework, as well as talk about some of the HTML Helper extension methods you can use with it to make data editing scenarios easier.  Click here to download the source code for the completed application we are going to build below to explain these concepts.

      Form Input and Post Scenario

      To help illustrate some of the basics of how to handle form input and posting scenarios with the ASP.NET MVC Framework, we are going to build a simple product listing, product creation, and product editing scenario.  It will have three core end-user experiences:

      Product Listing By Category

      Users will be able to see a listing of all products within a particular product category by navigating to the /Products/Category/[CategoryID] URL:

      Add New Product

      Users will be able to add a new product to the store by clicking the "Add New Product" link above.  This takes them to the /Products/New URL - where they will be prompted to enter details about a new product to add:

      When they hit save, the product will be added to the database, and they will be redirected back to the product listing page.

      Edit Product

      On the product listing page users can click the "Edit" link next to each product.  This takes them to the /Products/Edit/[ProductID] URL - where they can change the product details and hit the Save button in order to update them in the database:

      Our Data Model

      We are going to use the SQL Server Northwind Sample Database to store our data.  We'll then use the LINQ to SQL object relational mapper (ORM) built-into .NET 3.5 to model the Product, Category, and Supplier objects that represent rows in our database tables. 

      We'll begin by right-clicking on our /Models sub-folder in our ASP.NET MVC project, and select "Add New Item" -> "LINQ to SQL Classes" to bring up the LINQ to SQL ORM designer and model our data objects:

      We'll then create a partial NorthwindDataContext class in our project and add some helper methods to it.  We are defining these helper methods for two reasons: 1) it avoids us embedding our LINQ queries directly in our Controller classes, and 2) it will enable us to more easily adapt our Controller to use dependency injection in the future.

      The NorthwindDataContext helper methods we'll add look like below:

      To learn more about LINQ and LINQ to SQL, please check out my LINQ to SQL series here.

      Building Our ProductsController

      We are going to implement all three of our core end-user browsing experiences using a single controller class - which we'll call "ProductsController" (right click on the "Controllers" sub folder and select "Add New Item" -> "MVC Controller" in order to create it:

      Our ProductsController class will handle URLs like /Products/Category/3, /Products/New, and /Products/Edit/5 by implementing "Category", "New", and "Edit" actions:

      Read Part 1 and Part 2 of my ASP.NET MVC Series to learn more about how these URLs are routed to the action methods on the ProductsController class.  For this sample we are going to use the default /[Controller]/[Action]/[Id] route mapping rule - which means we do not need to configure anything in order for the routing to happen.

      Our Controller actions will be using three View pages in order to render output.  The "List.aspx", "New.aspx", and "Edit.aspx" pages will live under the \Views\Products sub-folder, and be based on the Site.Master master page under \Views\Shared.

      Implementing Product Listing By Category

      The first part of the site that we'll implement will be the Product Listing URL (/Products/Category/[CategoryId]):

      We'll implement this functionality using the "Category" action on our ProductsController class.  We'll use our LINQ to SQL DataContext class, and the GetCategoryById helper method we added to it, to retrieve a Category object that represents the particular category indicated by the URL (for example: /Products/Category/3).  We'll then pass the Category object to the "List" view to render a response from it:

      When implementing our List view we'll first update our page's code-behind to derive from ViewPage<Category> so that our page's ViewData property will be typed to the Category object that was passed by our Controller (Part 3 discusses this more):

      We'll then implement our List.aspx like below:

      The above view renders the Category name at the top of the page, and then renders a bulleted list of the Products within the category. 

      Next to each product in the bulleted list is an "Edit" link.  We are using the Html.ActionLink helper method that I discussed in Part 2 to render a HTML hyperlink (for example: <a href="/Products/Edit/4">Edit</a>) that when pressed will navigate the user to the "Edit" action.  We are also then using the Html.ActionLink helper method again at the bottom of the page to render a <a href="/Products/New">Add New Product</a> link that when pressed will navigate the user to the "New" action.

      When we visit the /Products/Category/1 URL and do a view-source in the browser, you'll notice that our ASP.NET MVC application has emitted very clean HTML and URL markup:

      Implementing Add New Product (Part 1 - Background)

      Let's now implement the "Add New Product" form post functionality of our site.  We'll ultimately want users to see a screen like below when they visit the /Products/New URL:

      Form input and editing scenarios are typically handled in the ASP.NET MVC Framework by exposing two Action methods on a Controller class.  The first Controller Action method is responsible for sending down the HTML containing the initial form to display.  The second Controller action method is then responsible for handling any form submissions sent back from the browser.

      For example, for our "Add Product" screen above we could choose to implement it across two different ProductsController actions: one called "New" and one called "Create".  The /Products/New URL would be responsible for displaying an empty form with HTML textboxes and drop-down list controls to enter new product details.  The HTML <form> element on this page would then have its "action" attribute set to the /Products/Create URLThis means that when the user presses a form submit button on it, the form inputs will be sent to the "Create" action to process and update the database with.

      Implementing Add New Product (Part 2 - First Approach)

      Below is an initial implementation that we could use for our ProductsController. 

      Notice above that we now have two action methods involved in the product creation process - "New" and "Create".  The "New" action method simply displays a blank form to the user.  The "Create" action method is what processes the posted values from the form, creates a new Product in the database based on them, and then redirects the client to the category listing page for the product.

      The HTML form sent to the client is implemented in the "New.aspx" view called by the "New" action method.  An initial implementation of this (using textboxes for everything) would look like below:

      Note above how we are using a standard HTML <form> element on the page (not a form runat=server).  The form's "action" attribute is set to post to our "Create" action method on ProductsController.  The post will happen when the <input type="submit"> element at the bottom is pressed.  When this happens, the ASP.NET MVC Framework will automatically handle mapping the ProductName, CategoryID, SupplierID and UnitPrice values as method parameters to the "Create" action method on ProductsController:

      And now when we run the site we have basic product entry functionality working:

      Implementing Add New Product (Part 3 - Using HTML Helpers for Drop Down Lists)

      The product entry screen we created in the previous section works, but isn't very user friendly.  Specifically, it requires that the end user know the raw CategoryID and SupplierID numbers for the Product being entered.  We need to fix this by instead displaying an HTML dropdownlist that displays the human readable names.

      Our first step will be to modify our ProductsController to pass to the View two collections - one containing a list of available categories, the other a list of available suppliers.  We'll do this by creating a strongly typed ProductsNewViewData class that encapsulates these, and which we'll then pass to the View (you can learn about this in Part 3):

      We'll then update our "New" action method to populate these collections and pass them as the ViewData for the "New" view:

      Within our view we can then use these collections to generate HTML <select> dropdowns. 

      ASP.NET MVC HTML Helpers

      One approach we could use to generate our dropdowns would be to manually create our own <% %> for-loop containing if/else statements within the HTML.  This would give us total control over the HTML - but would make the HTML messy.

      A much cleaner approach that you can alternatively use is to take advantage of the "Html" helper property on the ViewPage base class.  This is a convenient object that exposes a set of HTML Helper UI methods that automate HTML UI generation.  For example, earlier in this post we used the Html.ActionLink helper method to generate <a href=""> elements:

      The HtmlHelper object (as well as the AjaxHelper object - which we'll talk about in a later tutorial) have been specifically designed to be easily extended using "Extension Methods" - which is a new language feature of VB and C# in the VS 2008 release.  What this means is that anyone can create their own custom helper methods for these objects and share them for you to use. 

      We'll have dozens of built-in HTML and AJAX helper methods in future previews of the ASP.NET MVC Framework.  In the first preview release only the "ActionLink" method is built-into System.Web.Extensions (the assembly where the core ASP.NET MVC framework is currently implemented).  We do, though, also have a separate "MVCToolkit" download that you can add to your project to obtain dozens more helper methods that you can use with the first preview release. 

      To install the MVCToolkit HTML Helper methods, simply add the MVCToolkit.dll assembly to your project references:

      Re-build your project.  And then the next time you type <%= Html. %> you'll see many, many more additional UI helpers that you can use:

      To build our HTML <select> dropdowns we could use the Html.Select() method.  Each method comes with overloaded method versions - all with full intellisense inside our views:

      We could update our "New" view to use the Html.Select options to display dropdownlists that use the CategoryID/SupplierID properties as the values and CategoryName/SupplierName as the display text using the code below:

      This will generate the appropriate <select> HTML markup for us at runtime:

      And give end-users an easier way to pick the Product Category and Supplier on our /Products/New screen:

      Note: because we are still posting a CategoryID and SupplierID value to the server, we do not need to update our ProductsController Create Action at all to support this new drop-downlist UI - it will just work.

      Implementing Add New Product (Part 4 - Cleaning Up Create with the UpdateFrom Method)

      Our ProductsController's "Create" Action method is responsible for handling the form posting of our "Add Product" scenario.   It currently handles incoming form parameters as arguments to the action method:

      This approach works fine - although for forms involving large amounts of values the method signatures on Actions can start to become a little hard to read.  The code above that sets all of the incoming parameter values to the new Product object is also a little long and monotonous.

      If you reference the MVCToolkit assembly, you can optionally take advantage of a useful Extension Method implemented within the System.Web.Mvc.BindingHelpers namespace that can help clean this up a little.  It is called "UpdateFrom" and can be used on any .NET object.  It takes a dictionary of values as an argument, and it will then automatically perform a property assignment on itself for any key that matches a public property on the object.

      For example, we could re-write our Create action method above to use the UpdateFrom method like so:

       

      Note: if you want to be more explicit for security reasons and only allow certain properties to be updated, you can also optionally pass a string array of the property names to update to the UpdateFrom method:

      Implement Edit Product Functionality (Part 1 - Background)

      Let's now implement the "Edit Product" functionality of our site.  We'll ultimately want users to see a screen like below when they visit the /Products/Edit/[ProductID] URL:

      Like the "Add New Product" form post example above, we are going to implement this form edit interaction using two ProductsController Actions that we'll call "Edit" and "Update": 

      "Edit" will display the product form.  "Update" will be used to handle the form's submit action.

      Implement Edit Product Functionality (Part 2 - Edit Action)

      We'll begin enabling our application's Edit functionality by implementing the ProductController's Edit action method.  When we created our product listing page at the beginning of this post, we built it so that the Edit action will take an id argument as part of the URL (for example: /Products/Edit/5):

      We'll want the Edit action method to retrieve the appropriate Product object from the database, as well as retrieve collections of the available Suppliers and Categories (so that we can implement dropdowns in our edit view).  We'll define a strongly typed view object to represent all of this using the ProductsEditViewData object below:

      We can then implement our Edit action method to populate this viewdata object and Render it with an "Edit" view:

      Implement Edit Product Functionality (Part 2 - Edit View)

      We can implement the "Edit.aspx" view page using the following approach:

      Note how we are using both the Html.TextBox and Html.Select helper methods in the sample above.  Both of these are extension methods from the MVCToolkit.dll assembly.

      Notice how the Html.Select helper method has an overloaded version that allows you to specify what the selected value is in the dropdownlist.  In the snippet below I'm indicating that I want the Category drop down item to be automatically selected based on the edit product's current CategoryID value:

      Lastly - notice how we are using the Url.Action() helper method to set the <form> element's "action" attribute:

      Both the Url.Action and Html.ActionLink helper methods use the ASP.NET MVC Framework's Routing Engine to generate URLs (read Part 2 for details on how URL generation works).  What this means is that if we change the routing rules for Edits in our site, we will not need to change any of the code in our Controller or View.  For example, we could re-map our URLs to use a more RESTful URL like /Products/1/Edit instead of /Products/Edit/1, and have the above Controller and View continue to work unmodified. 

      Implement Edit Product Functionality (Part 3 - Update Action)

      Our last step will be to implement the "Update" action method on our ProductController class: 

      Like our previous "Create" action method we'll take advantage of the "UpdateFrom" extension method to automatically populate our product object from the request.  Notice that rather then populate an empty product object though, we are using a pattern where we first retrieve the old values from the database, then apply the changes the user made to them, and then save them in the database. 

      Once the edit is made, we redirect back to the Product Listing page - and automatically set the /Products/Category/[CategoryID] to match the saved state of the Product we were working on.

      Summary

      Hopefully this post has helped provide some more details about how to handle Form Input and Post scenarios with the ASP.NET MVC Framework, as well as provided some context for how you can handle and structure common data entry and edit scenarios with it.

      Click here to download a .ZIP file that contains the source code for the completed application we built above.

      In future posts I'll cover how to handle validation and error recovery situations with form input and editing scenarios. I'll talk about some of the data and security scaffolding support built-in to enable rapid application creation.  I'll discuss how you can use ASP.NET AJAX to perform AJAX-enabled edits using the MVC framework.  And I'll drill deeper into how you can unit test and add dependency injection to your Controllers.

      Hope this helps,

      Scott