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.

March 2008 - Posts

  • What's Wrong With This Code (#19)

    Leroy was shocked when the source code appeared. It was familiar yet strange, like an old lover's kiss. The code was five years old – an artifact of Leroy's first project. Leroy slowly scrolled through the code and pondered his next move. It wasn't a bug that was bothering Leroy – there were no race conditions or tricky numerical conversions. No performance problems or uncaught error conditions. It was all about design …

    public class BankAccount
    {
        
    public void Deposit(decimal amount)
        {
            _balance += amount;
            LogTransaction(
    "Deposited {0} on {1}", amount, DateTime.Now);
        }

        
    public void Withdraw(decimal amount)
        {
            _balance -= amount;
            LogTransaction(
    "Withdrew {0} on {1}", amount, DateTime.Now);
        }

        
    public void AccumulateInterest(decimal baseRate)
        {
            
    decimal interest;

            
    if (_balance < 10000)
            {
                interest = _balance * baseRate;
            }
            
    else
            {
                interest = _balance * (baseRate + 0.01);
            }
            LogTransaction(
    "Accumulated {0} interest on {1}", interest, DateTime.Now);
        }

        
    void LogTransaction(string message, params object[] parameters)
        {
            
    using(FileStream fs = File.Open("auditlog.txt", FileMode.OpenOrCreate))
            
    using(StreamWriter writer = new StreamWriter(fs))
            {
                writer.WriteLine(message, parameters);
            }
        }

        
    public decimal Balance
        {
            
    get { return _balance; }
            
    set { _balance = value; }
        }

        
    decimal _balance;
    }

    "Times have changed, and so I have, fortunately", Leroy thought to himself. "And so will this code…"

    To be continued…

  • Custom Aggregations In LINQ

    Aggregate is a standard LINQ operator for in-memory collections that allows us to build a custom aggregation. Although LINQ provides a few standard aggregation operators, like Count, Min, Max, and Average, if you want an inline implementation of, say, a standard deviation calculation, then the Aggregate extension method is one approach you can use (the other approach being that you could write your own operator).

    Let's say we wanted to see the total number of threads running on a machine. We could get that number lambda style, or with a query comprehension, or with a custom aggregate.

    var processes = Process.GetProcesses();

    int totalThreads = 0;

    totalThreads = processes.Sum(p => p.Threads.Count);

    totalThreads = (
    from process in processes
                    
    select process.Threads.Count).Sum();            

    totalThreads =
         processes.Aggregate(
                0,                                  
    // initialize
                (acc, p) => acc += p.Threads.Count, // accumulate
                acc => acc                          // terminate
          );

    This particular overloaded version of Aggregate follows a common pattern of "Initialize – Accumulate – Terminate". You can see this pattern in extensible aggregation strategies from Oracle to SQLCLR. The first parameter represents an initialization expression. We need to provide an initialized accumulator – in this case just an integer value of 0.

    The second parameter is a Func<int, Process, int> expression that the aggregate method will invoke as it iterates across the sequence of inputs. For each process we get our accumulator value (an int), and a reference to the current process in the iteration stage (a Process), and we return a new accumulator value (an int).

    The last parameter is the terminate expression. This is an opportunity to provide any final calculations. For our summation, we just need to return the value in the accumulator.

    StdDev

    Now, let's compute a more thorough summary of running threads, including a standard deviation. Although we could get away with a simple double accumulator for stddev, we can also use a more sophisticated accumulator to encapsulate some calculations, facilitate unit tests, and make the syntax easier on the eye.

    class StdDevAccumulator<TSource>
    {        
        
    public StdDevAccumulator(IEnumerable<TSource> source,
                                
    Func<TSource, double> avgSelector)
        {
            SampleAvg = source.Average(avgSelector);
            SampleCount = source.Count();
        }

        
    public StdDevAccumulator<TSource> Accumulate(double value)
        {
            TotalDeviation +=
    Math.Pow(value - SampleAvg, 2.0);
            
    return this;
        }

        
    public double ComputeResult()
        {
            
    if (SampleCount < 2)
            {
                
    return 0.0;
            }
            
    return Math.Sqrt(TotalDeviation / (SampleCount - 1));  
        }

        
    public double SampleAvg { get; set; }
        
    public int    SampleCount { get; set; }
        
    public double TotalDeviation { get; set; }
    }

    Put the accumulator to use like so:

    var processes = Process.GetProcesses();

    var summary = new
        {
            TotalProcesses = processes.Count(),
            TotalThreads = processes.Sum(p => p.Threads.Count),
            MinThreads = processes.Min(p => p.Threads.Count),
            MaxThreads = processes.Max(p => p.Threads.Count),
            StdDevThreads = processes.Aggregate(    
                    
    new StdDevAccumulator<Process>(processes, p => p.Threads.Count),
                    (acc, p) => acc.Accumulate(p.Threads.Count),                    
                    (acc)    => acc.ComputeResult()
            )
        };

  • March 28th Links: ASP.NET, ASP.NET AJAX, ASP.NET MVC, Visual Studio, Silverlight, .NET

    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

    • Kigg - Building a Digg Clone with ASP.NET MVC: Kazi Manzur Rashid published an excellent Digg-clone sample built with ASP.NET MVC last February.  He recently updated the code to work with ASP.NET MVC Preview 2 (full details here).  You can download the latest version of his source code here.

    • Testing with the ASP.NET MVC Framework: Simone Chiaretta has a great article that discusses how to test controllers using ASP.NET MVC Preview 2.  Note: the next ASP.NET MVC preview release will include a number of refactorings that will simplify controller testing considerably (and avoid the need to mock anything for common scenarios).

    Visual Studio

    • VS 2008 Web Deployment Hot-Fix Roll-Up Now Available for non-English Languages: Last month we shipped a hot-fix release that fixes a number of bugs, adds a few features, and improves performance for web development scenarios in VS 2008 and Visual Web Developer 2008 Express.  Last month's release only worked with the English-language VS 2008 products.  Yesterday we shipped an update that now works for all VS 2008 languages except Portuguese and Russian (which are still to come in the future). 

    • Hotfix Available for VB Performance Issue in VS 2008: The Visual Basic team recently released a hotfix as well that addresses a performance issue with large files that contain XML documentation.  Read this post to learn more about how to download it if you are running into this issue.

    Silverlight

    • Using Silverlight 2's DataGrid with WCF + LINQ to SQL: This 15 minute video blog demonstrates how to build a LINQ to SQL object model on the server and publish it using WCF.  It then demonstrates how to build a Silverlight client that uses the new Silverlight DataGrid control, and which calls the WCF service to retrieve the LINQ to SQL data to populate it with.

    • Simple Editing of Web Service Data in a DataGrid: Mike Taulty has a nice blog post that shows how to create a WCF service on the server, and then use it from a Silverlight 2 client to retrieve data, bind it to a DataGrid, allow users to update rows, add/delete rows, and then save it back to the server using Silverlight 2 Beta1.

    • Sorting with Silverlight 2's DataGrid Control: The DataGrid control in Silverlight 2 Beta1 doesn't yet have built-in column sorting support (it is coming in Beta2).  That hasn't stopped Matt Berseth though!  In this post he shows how to implement sorting using a custom header column approach.  Also check out Matt's post here, which provides a DataGrid test page that shows off a number of the current DataGrid features.

    • Open Source Silverlight Charts with VisiFire: Silverlight doesn't yet have built-in charting controls.  The good news is that the folks at Webyog just released a really cool set of open source Silverlight charting controls (complete with animation support) that enable you to easily build great looking charts.  Their model makes it super easy to use the chart components within existing HTML or AJAX applications.

    .NET

    • FormatWith and DateTime Extension Methods: James Newton-King and Fredrik Kalseth have some nice posts and samples that demonstrate how to use the new extension method feature in the VB and C# languages in VS 2008 to create some useful convenience libraries. 

    Hope this helps,

    Scott

  • New Log Reporting, Database Management, and other cool admin modules for IIS 7

    One of the core priorities we focused on when building IIS 7 was to enable a rich .NET extensibility model that provides developers with the hooks to easily plug-in and extend the web server. 

    These extensibility hooks are provided in the web-server pipeline (enabling scenarios like the new IIS7 Bit Rate Throttler), within the configuration system (enabling developers to create new web.config schema settings), within the health monitoring system (enabling developers to add custom trace events), and within the admin tool (enabling developers to plug-in new admin UI modules).

    We added these extensibility hooks so that anyone can easily extend and enhance the web server using .NET.  We also selfishly wanted them so that we can ship regular feature packs that add additional features to the core web server.

    IIS 7 Admin Pack Preview 1 Released

    Last week the IIS team shipped the first technical preview of some really cool administration modules that I think web developers will find super useful.  This preview adds several new features to the IIS7 Admin Tool:

    • Database Manager: Built-in SQL Server database management, including the ability to create, delete, and edit tables and indexes, create/edit SPROCs and execute custom queries.  Because it is integrated in the IIS administration tool it all works over HTTP/SSL - which means you can use the module to remotely manage your hosted applications (even with low-cost shared hosting accounts), without having to expose your database directly on the Internet.

    • Log Reports: Built-in report visualization with charting support for log files data.  Full range selection and custom chart creation is supported, as well as the ability to print or save reports.  Like the database manager you can use this module remotely over HTTP/SSL - which means it works in remote shared hosting scenarios.

    • Configuration Editor: This is a power module that provides complete control over editing all web.config settings within the admin tool.  You can configure it to track the changes you make using the UI and have it auto-generate configuration change scripts that you can then save and tweak to re-run later in an automated way.

    • Request Filtering UI: This admin module provides more control over the new request filtering feature in IIS7.  Check out Carlos' blog post here for details on how to use it.

    • .NET Authorization: This admin module provides a custom authorization rules editor which allows you to more easily manage the ASP.NET <authorization> configuration section.

    • FastCGI UI: This admin module provides more support for editing all the new <fastCGI> settings (for when you use FastCGI modules with IIS7 like PHP).

    Below are some screen-shots and simple walkthroughs of the Log Reporting and Database Manager administration UI modules:

    Log Reporting Admin Module

    Have you ever deployed a web application onto a server and wondered how much load it is getting?, what the average response time from the server is?, or whether many server errors are occurring (and if so on what URLs)?  All of these settings are carefully logged by IIS in a text based log file.  Today most people use command-line tools like the IIS Log Parser utility to query and analyze these files.

    The IIS 7 Admin Pack and the new "IIS Reports" admin module now enable you to also query and chart your reports graphically within the IIS admin tool:

    Out of the box the "IIS Reports" admin module comes with a bunch of pre-built logparser-based reports that you can easily run on your sites and applications:

    Below is a simple graphical report we could pull up that looks at the HTTP status codes being returned by my "TestSite" application (note how we are using the "bar graph" visualization option):

    Reports can optionally be filtered using a date range.  You can also push the print or save buttons within the report page to generate a printer or a local saved version of the report.

    The IIS7 Admin Tool is a rich client application (built using WinForms) - but it does all of its remote access and work using HTTP based web-services that connect to the remote web-server.  This means it will work through firewalls, and a hoster does not need to open up ports in their network in order to enable it. 

    Once a hoster installs the IIS 7 Admin Pack on their web-servers, remote customers managing their hosted sites using the IIS admin tool (which is built-into Vista and available as a download for Windows XP clients) will automatically be prompted to enable the IIS Reports admin module (the install of the client-side module is seamless).  They'll then be able to use the reports module inside their admin tool to pull up reports for their remote hosted sites.

    Note: hosters can optionally disable this feature if they want, or choose to restrict or customize the list of reports provided.  Hopefully most hosters will chose to just make this a standard feature of all IIS and ASP.NET plans they offer.

    Database Manager Module

    Have you ever deployed your application and database to a remote hosting provider and wanted to make a quick change to the database (but your hosting provider didn't support accessing it using the SQL admin tool)?  Using the new "database manager" module within the IIS admin tool you can now remotely access your database and make changes to it using HTTP/SSL through the web-server. 

    Just connect your IIS administration tool to your remote site and click the new "Database Manager" icon:

    By default the Database Manager module will look at the <connectionStrings> section of your web application's web.config file, and allow you to easily access any of the databases your hosted application is using. 

    For example, below my TestSite application has a "NorthwindConnectionString" setting in the <connectionStrings> section of my web.config (which is why it shows up in my list of connection nodes).  When I click it I can view and edit my SPROCs and Table Schema (including indexes):

    We could right-click on any table to edit the row data within it, or alternatively perform a custom SQL query to retrieve a custom set of data:

    What is nice is that a hoster can easily enable all of the above database admin features for both dedicated and shared hosting plans (even when there are hundreds or thousands of customers on a single server).  Like all other modules in the admin tool, all communication between the rich client front-end and the backend at the hoster is done over HTTP/SSL based web-services (meaning it goes through firewalls and doesn't require the hoster to open any new ports - nor expose the SQL server directly on the Internet). 

    Hopefully this database administration module will just be a standard feature that all IIS hosters enable - which will make remote hosted data management much easier going forward.

    Summary

    Over time you'll see even more admin UI modules be shipped in the IIS 7 Admin Pack and many more features enabled (Carlos, who runs the dev team building the admin tool, is actively asking for suggestions on what you'd like to see via his blog - so drop him a comment if you have a suggestion or want to provide some encouragement).

    You can download the first technical preview of IIS 7 Admin Pack release here as well as learn more about it via the online documentation here.  The above modules work with both the IIS7 release in Vista SP1 as well as Windows Server 2008.

    Hope this helps,

    Scott

  • And Equality for All ... Anonymous Types

    Given this simple Employee class:

    public class Employee
    {
        
    public int ID { get; set; }
        
    public string Name { get; set; }    
    }

    How many employees do you expect to see from the following query with a Distinct operator?

    var employees = new List<Employee>
    {
        
    new Employee { ID=1, Name="Barack" },
        
    new Employee { ID=2, Name="Hillary" },
        
    new Employee { ID=2, Name="Hillary" },
        
    new Employee { ID=3, Name="Mac" }
    };

    var query =
            (
    from employee in employees        
            
    select employee).Distinct();

    foreach (var employee in query)
    {
        
    Console.WriteLine(employee.Name);
    }

    The answer is 4 – we'll see both Hillary objects. The docs for Distinct are clear – the method uses the default equality comparer to test for equality, and the default comparer sees 4 distinct object references. One way to get around this would be to use the overloaded version of Distinct that accepts a custom IEqualityComparer.

    Let's try the query again and project a new, anonymous type with the same properties as Employee.

    var query =
      (
    from employee in employees                            
      select new { employee.ID, employee.Name }).Distinct();

    That query only yields three objects – Distinct removes the duplicate Hillary! How'd it suddenly get so smart?

    Turns out the C# compiler overrides Equals and GetHashCode for anonymous types. The implementation of the two overridden methods uses all the public properties on the type to compute an object's hash code and test for equality. If two objects of the same anonymous type have all the same values for their properties – the objects are equal. This is a safe strategy since anonymously typed objects are essentially immutable (all the properties are read-only). Fiddling with the hash code of a mutable type gets a bit dicey.

    Interestingly – I stumbled on the Visual Basic version of anonymous types as I was writing this post and I see that VB allows you to define "Key" properties. In VB, only the values of Key properties are compared during an equality test. Key properties are readonly, while non-key properties on an anonymous type are mutable. That's a very C sharpish thing to do, VB team.

  • Three New Security Tutorials Now Available

    I've been working on some tutorials for the www.asp.net site on the topics of forms authentication, authorization, membership, and roles. The first set of tutorials covered security basics and examined forms authentication in detail; the second set looked at the Membership system and the SqlMembershipProvider. The third set of tutorials are now available online and focus on the Roles framework and the SqlRoleProvider.

    • Creating and Managing Roles [VB | C#] - examines the Roles framework and the SqlRoleProvider. Shows how to create new roles and manage these roles from a web page interface.
    • Assigning Roles to Users [VB | C#] - looks at the Roles framework methods for assigning and removing users from roles.
    • Role-Based Authorization [VB | C#] - shows how to perform role-based URL authorization, as well as how to programmatically grant or deny functionality based on the currently logged in user's role(s). Also looks at using the LoginView control to display different content based on the logged on user's role.

    All tutorials are available in C# and VB versions, include a complete, working source code download, and are available to download as PDF. The next batch of tutorials examines creating administrative pages to manage user accounts.

    Enjoy! - http://asp.net/learn/security/

  • Inner, Outer, Let's All Join Together With LINQ

    The least intuitive LINQ operators for me are the join operators. After working with healthcare data warehouses for years, I've become accustomed to writing outer joins to circumvent data of the most … suboptimal kind. Foreign keys? What are those? Alas, I digress…

    At first glance, LINQ appears to only offer a join operator with an 'inner join' behavior. That is, when joining a sequence of departments with a sequence of employees, we will only see those departments that have one or more employees.

    var query =
      from department in departments
      join employee in employees
          
    on department.ID equals employee.DepartmentID
      select new { employee.Name, Department = department.Name };

    After a bit more digging, you might come across the GroupJoin operator. We can use GroupJoin like a SQL left outer join. The "left" side of the join is the outer sequence. If we use departments as the outer sequence in a group join, we can then see the departments with no employees. Note: it is the into keyword in the next query that triggers the C# compiler to use a GroupJoin instead of a plain Join operator.

    var query =
      from department in departments
      join employee in employees
          
    on department.ID equals employee.DepartmentID
        
      into employeeGroup
      select new { department.Name, Employees = employeeGroup };

    As you might suspect from the syntax, however, the query doesn't give us back a "flat" resultset like a SQL query. Instead, we have a hierarchy to traverse. The projection provides us a department name for each sequence of employees.

    foreach (var department in query)
    {
        
    Console.WriteLine("{0}", department.Name);
        
    foreach (var employee in department.Employees)
        {
            
    Console.WriteLine("\t{0}", employee.Name);
        }
    }

    Flattening a sequence is a job for SelectMany. The trick is in knowing that adding an additional from clause translates to a SelectMany operator, and just like the outer joins of SQL, we need to project a null value when no employee exists for a given department – this is the job of DefaultIfEmpty.

    var query =
      from department in departments
      join employee in employees
          
    on department.ID equals employee.DepartmentID
        
      into employeeGroups
      from employee in employeeGroups.DefaultIfEmpty()
      select new { DepartmentName = department.Name, EmployeeName = employee.Name };

    One last catch – this query does work with LINQ to SQL, but if you are stubbing out a layer using in-memory collections, the query can easily throw a null reference exception. The last tweak would be to make sure you have a non-null employee object before asking for the Name property in the last select.

  • ASP.NET MVC Source Code Now Available

    Last month I blogged about our ASP.NET MVC Roadmap.  Two weeks ago we shipped the ASP.NET Preview 2 Release.  Phil Haack from the ASP.NET team published a good blog post about the release here.  Scott Hanselman has created a bunch of great ASP.NET MVC tutorial videos that you can watch to learn more about it here.

    One of the things I mentioned in my MVC roadmap post was that we would be publishing the source code for the ASP.NET MVC Framework, and enable it to be easily built, debugged, and patched (so that you can work around any bugs you encounter without having to wait for the next preview refresh release).

    Today we opened up a new ASP.NET CodePlex project that we'll be using to share buildable source for multiple upcoming ASP.NET releases.  You can now directly download buildable source and project files for the ASP.NET MVC Preview 2 release here.

    Building the ASP.NET MVC Framework

    You can download a .zip file containing the source code for the ASP.NET MVC Framework for the release page here.  When you extract the .zip file you can drill into its "MVC" sub-folder to find a VS 2008 solution file for the project: 

    Double-clicking it will open the MVC project containing the MVC source within VS 2008:

    When you do a build it will compile the project and output a System.Web.Mvc.dll assembly under a \bin directory at the top of the .zip directory.  You can then copy this assembly into a project or application and use it.

    Note: the license doesn't enable you to redistribute your custom binary version of ASP.NET MVC (we want to avoid having multiple incompatible ASP.NET MVC versions floating around and colliding with each other).  But it does enable you to make fixes to the code, rebuild it, and avoid getting blocked by an interim bug you can't work around.

    Next Steps

    Our plans are to release regular drops of the source code going forward.  We'll release source updates every time we do official preview drops.  We will also release interim source refreshes in between the preview drops if you want to be able to track and build the source more frequently.

    We are also hoping to ship our unit test suite for ASP.NET MVC in the future as well (right now we use an internal mocking framework within our tests, and we are still doing some work to refactor this dependency before shipping them as well).

    Hope this helps,

    Scott

  • The Code Trip Rolls into San Diego Tuesday, March 25th

    Over the past several weeks, some dedicated developers have been undertaking a grand Code Trip, travelling around the Western half of the United States in a bus speaking and hanging out at Code Camps, User Groups, and conferences. On Tuesday, March 25th the Code Trip bus rolls into San Diego to take over the San Diego .NET User Group meeting (along with regular speaker Michele Leroux Bustamante).

    For more information, and to register for the event, visit http://thecodetrip.com/1/san-diego-dotnet-user-group. Should be a fun and interesting night.

  • IIS 7.0 Bit Rate Throttling Module Released

    Video on the web is now one of those common scenarios that every user takes for granted, and increasingly every major site is incorporating in some form (product videos, training videos, richer advertising scenarios, user generated content, customer testimonials, etc).

    One of the challenges when adding video to a site, though, is delivering it in a way that doesn't cost a fortune.  Network bandwidth costs a lot of money, and the cost of high quality video usage can quickly add up.

    The blog post below provides a quick overview of some of the options you can use to reduce the cost of delivering video, and discusses a new free download - the IIS 7.0 Bit Rate Throttling Module - that was released a few days ago and which enables you to easily save money when serving video from an IIS web server using any video technology (including Silverlight, Windows Media Player and even Flash).

    Option 1: Using a Video Hosting Service

    One approach you can take to reduce video bandwidth costs is to use a video hosting service like YouTube or the free Microsoft Silverlight Streaming Service.  This allows you to use someone else's network to deliver the video content, and avoid having to pay the bandwidth costs yourself.

    If you aren't familiar with the Silverlight Streaming service, it allows you to upload up to 10GB of videos and download 5 Terabytes/year of video content (at up to a 1.4 Mbps bit-rate) for free.  You can build any custom Silverlight client player application you want to embed the video within it.  This means it doesn't require a specific video player look and feel, nor a service logo/watermark to play the video.  This allows you to fully integrate the video into your site and use whatever UI you want to host it.

    Option 2: Hosting Video on Your Own Servers

    Sometimes using a video hosting service doesn't make sense (for example: you want to use custom authentication to grant/deny user's access, you want to play really long video segments, or you want to serve up custom ads in your videos).  Instead you might want to serve the video up from your own servers and have complete control over it. 

    There are typically two options you can use to deliver the video from your servers: using a streaming approach or a progressive video download approach:

    Streaming Server Scenario

    In a streaming scenario a client (like Silverlight, Windows Media Player, Flash or Real Networks) connects to a streaming server.  The streaming server then sends down the video stream to watch, and typically enables a user to dynamically skip ahead/behind, pause or stop the video stream.  When the user closes the browser or navigates away from the page the video stream automatically stops transmitting.

    Windows Media Services (WMS) is a free streaming server download available for Windows, and can stream video to both Windows Media Player and cross-platform Silverlight browser clients.  It is generally regarded as the most server scalable and cost effective way to enable video streaming on the web, and handles both on-demand file streaming scenarios (for example: streaming a .wmv file) as well as live stream scenarios (for example: a sporting event like the Olympics that is happening live in real time).

    Windows Media Services can be used on any version of Windows Server - including the new Windows Server 2008 Web Server edition (which only costs $469, enables up to 4 processors and 32GB of RAM, and supports IIS, ASP.NET, SharePoint, and Windows Media Services).

    Progressive Download Scenario

    In a progressive download scenario a client (like Flash or Silverlight) downloads a video directly off of a web-server, and begins playing it once enough video is downloaded for it to play smoothly.

    The benefit of using a progressive download approach is that it is super easy to setup on a web-server. Just copy/ftp a video up to a web-server, obtain a URL to it, and you can wire it up to a video client player.  It doesn't require any custom web-server configuration, nor require a streaming server to be installed, in order to enable.

    The downside of using a progressive video download approach, though, is that web-servers are by default designed to download files as fast as possible.  So when a user clicks to watch a video on your site, your web-server will attempt to transmit it to the client as fast as possible.  This is fine if the user decides to watch the entire video.  But if the user stops watching the content half way through the video (or navigates to a different page), you will have downloaded a bunch of video content that will never be watched.

    If the remaining un-watched video content is several megabytes (or even tens of megabytes) in size, you will end up over time spending a lot of money on bandwidth that is not benefiting your business/site at all....

    IIS 7.0 Bit Rate Throttling Module

    Last week the IIS team shipped a new free IIS 7.0 bit-rate throttling module that makes progressive video scenarios much cheaper in cost.

    The bit rate throttling module enables you to easily configure bandwidth throttling rules for any type of media content downloaded from an IIS web server (including .WMV, .MOV, .FLV and .MP3 files).

    Out of the box, the bit rate throttling module causes IIS to quickly transmit a burst of initial media content when a file is requested.  By default the rules are set to look at the mime-type and bit-rate encoding of the file, and send as fast as possible enough of the media file to play 20 seconds of it.  Once the video client has 20 seconds of the media to play, the IIS bit rate throttling module will then throttle down the transmit rate to equal the bit-rate encoding of the file.  It will then monitor whether the video player on the client ever closes or navigates to a different video, and automatically stop the remainder of the file being sent if the user goes away.

    For example, if you are playing a 35MB video file that is encoded at a bit-rate of 500 Kbps, IIS will send a 20 second burst of the video (20 seconds @ a 500Kbps encoding == 1.25MB of content) as fast as possible to start the video client playing, and then download the remainder of the video at a download rate of only 500 Kbps (enough so that the user always has 20 seconds of video cached on the client so that they never get buffered).

    If after a minute the user gets bored and either stops the video or navigates to a new page, IIS will detect that they went away and stop transmitting the remainder of the 35MB file.  Since IIS only downloaded 80 seconds of total video in this scenario (the 60 seconds that the user watched + the 20 second buffer window), only 5MB instead of 35MB of network bandwidth ended up being used.  30MB of bandwidth savings repeated hundreds or thousands of times a day can easily translate to thousands of dollars of bandwidth savings per year....

    IIS 7.0 Bit Rate Throttling Module Download and Installation

    You can download and learn more about the IIS 7.0 bit-rate throttling module here.

    Once installed, you can click the "Bit Rate Throttling" node in the IIS admin tool:

    And then configure whatever bit-rate throttling rules you want on a per file or per file-type basis:

    The below whitepapers describe how to enable and use it more:

    Also check out Mike's post here and Vishal's post here and here for more details.

    Hope this helps make your video scenarios more cost effective,

    Scott

  • Mashups with SyndicationFeed and LINQ

    I was experimenting with the new SyndicationFeed class in 3.5 earlier this year and devised a mashup LINQ query:

    string[] feedUrls = { "http://www.OdeToCode.com/blogs/scott/rss.aspx",
                          
    "http://www.pluralsight.com/blogs/mainfeed.aspx",
                          
    "http://feeds.feedburner.com/ScottHanselman"    
                        };

    var items =
        
    from url in feedUrls
           
    let feed = SyndicationFeed.Load(XmlReader.Create(url))
        
    from item in feed.Items
        
    where item.PublishDate > DateTime.Now.AddDays(-30)
        
    orderby item.PublishDate descending
        select item;

    // display the most recent 15 items
    foreach (SyndicationItem item in items.Take(15))
    {
        
    Console.WriteLine("{0} : {1}",
            item.PublishDate.Date.ToShortDateString(),
            item.Title.Text);
    }

    The code is able to filter and sort RSS items from an arbitrary number of blogs with a 6 line query expression. I was thinking of this code when I ran across Scott Hanselman's Weekly Source Code 19 – LINQ and more What, Less How. Scott's reader David Nelson had the following observation:

    I disagree with Siderite, in that I think the LINQ example is more readable than the iterative example; however, as has been pointed out, it leaves no room for error handling or AppDomain transitions. This is a problem with LINQ in general; in trying to make everything very compact, it leaves too little room to maneuver.

    The LINQ query I'm using isn't production code. If just one blog is down and the XmlReader throws an exception, the entire operation is borked. One solution is to wrap the feed reading into a method that uses exception handling and returns an empty SyndicationFeed in case of an exception - then invoke the method from inside the query. Could anything else go wrong? Sure - one null PublishDate on an item and again we'd be borked. Bullet-proofing a LINQ query might take some work, especially when dealing with third party types.  

    As LINQ moves us into the "What" instead of the "How", it might be harder to see these types of error scenarios. LINQ is a fantastic technology, but like everything in software, it is a good idea to look the gift horse in the mouth. 

  • March's Toolbox Column Online

    After a three month hiatus, I am back to authoring the Toolbox column for MSDN Magainze. (Thanks to James Avery for authoring the column the last three months.) There has also been some changes to the content you'll find in Toolbox. When the column debuted in January 2006, it was designed to examine two to three indespensible developer tools and a book review. Specifically, it aimed to cover commercial tools designed by third-party vendors that weren't priced beyond levels that would require top-tier managerial approval to buy (in other words, it should not include products costing several thousands of dollars).

    The focus of the column has shifted a bit. Instead of focusing exclusively on commercial ISV products, the column is more dedicated to examining community-created projects and open-source software. We are also launching a new section in the Toolbox column called Blogs of Note, where I share and review interesting and informative technology-focused blogs. The column still includes a commercial ISV software reviews and a book review.

    The March issue of Toolbox includes coverage on:

    • Firebug - a free, open-source client-side Web development tool for the Mozilla FireFox browser. With Firebug you can quickly examine and modify the HTML, CSS, and JavaScript of a page, all directly within the browser. A must-have tool for web developers.
    • Scott Guthrie's Blog - Scott is one of the original creators of Microsoft's ASP.NET and, today, is the Vice President of the Microsoft Developer Division. His blog is a fountainhead of information on current and upcoming web technologies and tools.
    • Extending Reflector with Add-Ins - a look at the popular disassembler and class viewer, Reflector, along with information about a variety of free, community-created Reflector Add-Ins.

    In addition, I reviewed Lynn Beighley's book Head First SQL (O'Reilly). Here is a snippet from the review:

    Most books that teach SQL do so with dry prose and focus on business and accounting scenarios. O'Reilly's Head First SQL by Lynn Beighley turns this approach on its head, and to great effect. The topics covered in Head First SQL are familiar: the fundamentals of the SELECT, INSERT, UPDATE, and DELETE queries; JOINs; subqueries; data normalization; data and relational integrity; and so on. But the unique presentation in Head First SQL makes it fun to learn and easy to remember.

    ...

    Head First SQL shines in its ability to explain concepts in a way that makes even the most complicated scenarios seem like common sense. The chapter on JOINs is the most lucid and digestible description I've read yet. The same is true for the chapter on subqueries.

    I hope you like the shift in focus of the Toolbox column. I invite any feedback, comments, or constructive criticism you may have about the column at mitchell@4guysfromrolla.com. Likewise, send me any suggestions for products, blogs, or books to review!

    On a side note, it appears that the MSDN Magazine website has been retooled and many past links to my Toolbox columns are now broken. Boo. I've always been a firm believer that URLs are a public interface and therefore must remain in tact for the lifetime of the website (in theory, then, forever); it's frustrating that Microsoft doesn't share these same ideals.

    As always, if you have any suggestions for products, blogs, or books to review for the Toolbox column, please send them to me at mitchell@4guysfromrolla.com

  • March 14th Links: ASP.NET, ASP.NET AJAX, ASP.NET MVC and .NET

    I'm slowly recovering from keynoting at MIX last week, and have been digging my way out of backlogged email the last few days.  I'm going to try and finish catching up on blog comments this weekend - apologies for the delay in getting back to some of your questions.

    To kick-start my blogging again I thought I'd post a new link-listing series.  Today's post is mostly focused on ASP.NET and web related links.  I'm going to be doing more Silverlight and WPF posts soon.

    ASP.NET

    ASP.NET AJAX

    • New ASP.NET AJAX Control Toolkit Release: David Anson blogs about a new ASP.NET AJAX Control Toolkit release that the team made right before MIX.  This release includes a number of patches (including a bunch from the community) with bug fixes and improvements in a bunch of areas.

    ASP.NET MVC

    • Thoughts on ASP.NET MVC Preview 2 and Beyond: Phil Haack from the ASP.NET team has a great post where he talks about the ASP.NET MVC Preview 2 release, as well as some of the features and work that will show up in the next preview drop.  One of the major focuses in Preview 3 will be improvements to the testing workflow of controllers.

    • Cheesy Northwind Sample Code: Scott Hanselman has posted a sample application that shows building a simple data driven application using the ASP.NET MVC Framework and the Northwind sample database.

    • Securing Your Controller Actions: Rob Conery shows how to use the new ASP.NET MVC ActionFilterAttribute feature to apply declarative security rules to a controller.  Also check out David Hayden's post here for more security attribute examples.

    • Url Routing Debugger: Phil Haack posts a cool Url Routing Debugger he has built that demonstrates an easy way to test URL route conditions using the ASP.NET MVC framework.

    • ASP.NET MVC Test Project Integration with NUnit and Rhino Mocks: Joe Cartano from the VS Web Tools team walks-through using some NUnit and Rhino Mocks project templates that he has created.  These plug-into the new VS 2008 tools support for ASP.NET MVC, and enable you to easily get a test project started when you create a new ASP.NET MVC application.

    .NET

    • Graffiti: The folks at Telligent have recently released a sweet new CMS system for ASP.NET that is trivial to setup, and which provides a bunch of great content editing support.  Definitely worth looking at if you are in the market for an great way to publish or manage content on the web.

    • Beta of LINQ to LLBLGen Pro Released: Frans Bouma announces the first public beta release of LINQ to LLBLGen Pro (a very popular commercial ORM for .NET).  Frans has a very in-depth 14 post series that discusses how he built the LINQ support for it (a nice technical read).

    Hope this helps,

    Scott

  • Restarting VisualStudioHacks.com

    Back when I wrote Visual Studio Hacks the book I also started the companion site, I kept up for awhile and then it gradually got swept to the sideline. When I was getting ready to work on the second edition of the book (which O'reilly decided not to do) I revived the site and started posting to it again, I also got Jim Holmes and Mike Wood to write some articles. Then it went back into hibernation. The other day I was thinking about the site and figured I either need to kill it off, or try and revive it.

    Well, I decided to revive it. I threw out all the old custom code (I love deleting code!) and converted the site to Graffiti, tweaked the design a little bit, and re-launched it. Now comes the difficult part, actually getting some fresh content on it. Another thing I decided is to make the focus of the site more of a blog. It will still feature articles, and I am working on a couple of screencasts, but the blog will be the most active part of the site.

    Because I know that I don't have a ton of time, between consulting and other projects, I decided to look for someone to help out with the site. The other day I ran across Darren Stokes who was writing some excellent Visual Studio posts over on his blog and have convinced him to join forces and write for Visual Studio Hacks instead. I am thrilled to have him on board and I think between the two of us we will be able to turn Visual Studio Hacks into the premier Visual Studio focused site. His first Visual Studio Links post is already up.

    From a business perspective my main goal with the site is to help increase the visibility of The Lounge, and in particular the .NET Small Publishers Room of The Lounge. You will notice I nixed all the google ads and am only running The Lounge ad.

    Third time is a charm they say, let's hope that turns out to be true for this site. Check it out, subscribe to the feed, let me know what you think.

    -James

  • Atlanta Code Camp 2008

    From the Atlanta Code Camp site: 

    At long last, we are happy to announce registration for the 4th annual Atlanta Code Camp is now open.

    What: All day geek fest focusing on code and not marketing fluff.
    When: Saturday, March, 29, 2008 All day (doors open at 7:30)
    Cost: Free! (If you are not satisfied, we promise a full refund.)
    Where: Devry University in Decatur - 250 North Arcadia Ave, Decatur, GA 30030 (view map)
    Speakers and Agenda: Currently being finalized. Check the www.AtlantaCodeCamp.com website over the next week to see the finalized version.

    To attend the event, you must register at the following link so that we can make sure to have food to feed you. http://www.clicktoattend.com/invitation.aspx?code=126492. If you don't register, we can't guarantee that you will be eligible for food or swag.

    During the Code Camp, lunch will be provided at no cost to you. After the event, we are planning on gathering in a local eatery to continue any discussions which we were not able to complete by our 5:30 pm end time. Location information will be made available at the event.

    The Atlanta Code Camps have historically "sold out" extremely rapidly and we don't expect this time to be any different. Please register quickly to lock in your spot as we are capping registration and attendance due to facility limitations. If you miss the registration cap, contact volunteer@atlantacodecamp.com to see if we can come to some other arrangement, otherwise you will have to wait until next year's event. Don't miss out.

    We hope you can join us for this exciting and informative event.

  • Review of Excellent Book: Linq in Action

    "LINQ in Action", published by Manning, is by far the best book available on Linq, both for those new to Linq and those already following it.  The authors, Fabrice Marguerie, Steve Eichert, and Jim Wooley, have done a fabulous job of explaining Linq from the basics to the advanced.  They even made it enjoyable to read, which makes it one of the best .Net books ever!

    The authors' introductory chapter shows us right away that this book is different by presenting a perfect balance of the problem, the history, and the solution.  Linq is a huge subject, but the authors are up to it, and they quickly whet the readers appetite for all of Linq -- Objects, Sql, and Xml.  We then get a very thorough explanation of the new language enhancements that Linq relies on, but which the authors clearly show to have uses of their own.  The chapter on Linq's building blocks, covering sequences, query operators, query expressions, and expression trees, was especially instructive to me, even though I've followed Linq from the alpha days, so again I'm sure this book has something for everyone.  The book then covers Linq to Objects very thoroughly, including common scenarios and performance considerations that other books never consider.

    The book then progresses to three chapters on Linq to Sql, which are of course my favorite since I'm really into O/R Mapping.  The authors cover not just the basics to get beginners up to speed, but they also cover far more advanced content than I was expecting.  For instance, they discuss not just the designer to setup mappings, but also the SqlMetal tool, and manual mappings using either attributes or xml.  They also discuss the various concurrency options, the entity life cycle, inheritance, and more.  The authors then give us three chapters on Linq to Xml, which again have something for everyone -- I especially like the chapter on common scenarios.  The book finishes with a very thorough chapter on extending Linq, with a Linq to Amazon example, and a chapter that ties it all together with a real-world example that was gradually put together during the course of the entire book.

    The authors also provide additional support and material online, including a bonus chapter on Linq to Datasets.  There is also downloadable code in both C# and VB, although the book actually shows both languages in most cases, and always points out the differences when there are differences between them.

    Disclaimer:  I personally know Jim and have seen him present on Linq multiple times, Steve was a user of my WilsonORMapper, even contributing to it, and I've known Fabrice in the online world for quite some time too -- but I did very much enjoy and learn even more from their most excellent book on Linq.

    LINQ in Action
  • Announcing Graffiti.Redirect 0.1

    In order to convert this site and Visual Studio Hacks to Graffiti I had to come up with a way to redirect all the existing links, while Graffiti includes an excellent migrator tool it doesn't have any way to handle redirects. In both cases I wanted to avoid having to do a ton of manual work to do the redirects.

    So I decided to write a graffiti plugin that would check the request against a regular expression and then redirect the request to the correct resource. Writing a graffiti plugin is not easy, there isn't much documentation, and I had to write most of the UI in javascript to do what I wanted, but I am happy with the result. (and thanks to Jayme for answering all my questions)

    Here is a quick screenshot:

    I toyed with the idea of trying to sell the plugin, but in the end I don't think it would be worth it and would rather just put it out there as open source and hopefully other's will get some use out of it and maybe step in and fix any bugs or add new features.

    I uploaded it and released it to Google Code.

    -James

  • Talks You Won’t See At the Local Code Camp

    The Lost Art of TSR Programming
    Abstract
    : Return to the glory days of DOS 2.0 and INT 21h as we write a simple Terminate and Stay Resident application using the latest software development techniques. We will construct our x86 assembler code using test driven development and mock extended memory managers.

    Why Am I Here On A Saturday?
    Abstract: Because even if you weren't here, you'd still be at the computer. Don't think you'd be doing chores at home, like dusting off the entertainment center, because chores are boring.

    Life of a Gnat
    Abstract: This session has nothing to do with GNU software, but will describe (in excruciating detail) the journey of the common fungus gnat from egg to adulthood. Pictures of mating swarms may not be appropriate for younger attendees.

    P.S. In all seriousness, the spring code camps are coming to the Mid-Atlantic and the topics are far better than the ones presented above.

    CMAP Code Camp – April 12th in Columbia, MD

    NoVa Code Camp South – March 20th in Woodbridge, VA

    Richmond Code Camp – April 26th

  • Visitors and Multiple Dispatch

    The visitor pattern is an elegant solution to a specific class of problems, but also comes with drawbacks in mainstream programming languages. There are various techniques one can us to minimize the drawbacks, however. This weekend I found some old but good articles harnessing the power of visitor while removing some of the pain:

    Both Brad and Kzu use reflection to effectively achieve multiple dispatch. The typical multiple dispatch mechanism used to implement the visitor pattern is a drag on maintenance and forces the pattern implementation to bleed into the visitor's targets – Brad's post shows all the gory details before he goes on the show a solution using reflection. Multiple dispatch isn't just a problem in C#, C++, and Java – it's also a problem in dynamic languages like Python and Ruby. Only a handful of languages inherently use multiple dispatch, or multimethods, with Common Lisp being the most notable.

    I tried a dispatch mechanism using Expression<T> today, but (in case you don't want to read any further) did not get a satisfactory result. If you keep reading, maybe you can think of something I missed. 

    Given these classes:

    public class Employee
    {
        
    public string Name { get; set; }
    }

    public class Manager : Employee
    {
    }

    How can you write a class like the following?

    public class EmployeeReport
    {
        
    public void Generate(IEnumerable<Employee> employees)
        {
            
    foreach (Employee employee in employees)
            {
                Visit(employee);
            }
        }

        
    void Visit(Employee employee)
        {
            
    // employee specific work ...
            Console.WriteLine("Visiting employee {0}", employee.Name);
        }

        
    public void Visit(Manager manager)
        {
            
    // manager specific work ...
            Console.WriteLine("Visiting manager {0}", manager.Name);
        }
    }

    The compiler will lay down code to invoke the Visit method that accepts an Employee reference, even when we really are referencing a Manager object at runtime. We need some mechanism that will thunk us into the best method based on the runtime type of the parameter, preferably without using a switch statement. A naïve try might look like the following:

    public void Generate(IEnumerable<Employee> employees)
    {
        
    foreach (Employee employee in employees)
        {
            DispatchVisit(employee);
        }
    }

    void DispatchVisit(Employee visitee)
    {
        
    Expression<Action<Employee>> expression = e => this.Visit(e);
        expression.Compile().Invoke(visitee);
    }

    Even though this code is generating IL at runtime via Compile, it still invokes the wrong method when we reach a Manager object. At compile time the compiler generates an expression tree to invoke the Visit accepting an Employee reference. We could go into the expression and make modifications to the Body before we call Compile, or we could build an expression tree manually. Either way, we need to pick out the exact method we need at runtime using the type of the parameter and a call to GetMethod:

    void DispatchVisit(Employee visitee)
    {
        
    MethodInfo methodInfo = this.GetType().GetMethod(
                                    
    "Visit", new Type[] { visitee.GetType() });
        
        
    ParameterExpression e = Expression.Parameter(visitee.GetType(), "e");
        
    LambdaExpression expression =
            
    Expression.Lambda(
                
    Expression.Call(
                    
    Expression.Constant(this, typeof(EmployeeReport)),
                    methodInfo,
                    e),
                 e);

        
        expression.Compile().DynamicInvoke(visitee);
    }

    This code works, because we are now getting a MethodInfo object that will reference Visit(Manager employee) when we have a manger object at runtime. But, the code is starting to look just as hairy as any other code generation technique, and we haven't even tried to address caching the compiled expression for performance, or moving up to an Expression<T>. 


  • Great Startup Advice

    Lots of people posting excellent startup advice (although you have to wade through the useless posts). Here are the ones I found useful:

    How to save money running a startup from Jason Calacanis - I think the dustup over the "workaholics" comment is just people looking for links, pretty sure Jason meant people who love their job and are passionate.

    Saving Money on Startups from Fred Wilson - Reaffirms many of Jason's points with some great real-world examples.

    A Couple of My Rules for Startups by Mark Cuban - Lots of good stuff here, love the advice on SWAG and keeping the organization flat.

    -James

  • My Presentations in Arizona this Tuesday

    This week I'm visiting Scottsdale Arizona and will be presenting at a free user group event during the day.  I'm presenting two sessions myself:

    1) Developing Applications using Silverlight 2: This will be a drill-down into the new Silverlight 2 Beta1 release, and how you can build applications with it using VS 2008 and Expression Blend.  You'll leave this session with a good understanding of the basics of Silverlight programming and how to start building applications with it.

    2) Developing Applications using ASP.NET MVC: This session will be a drill-down into the new ASP.NET Model-View-Controller framework option (which last week was updated .  You'll leave this session with a good understanding of what it is, how it works, and how to start building ASP.NET web applications with it.

    In addition to my sessions above, there will also be great sessions at the event from Microsoft employees on "Consuming Web Services with Microsoft Silverlight", "Encoding Video for Microsoft Silverlight", and "Serving Applications with Microsoft Silverlight Streaming". 

    You can sign up and attend the sessions for free.  Click here for more details on the events, and click here to register online to attend. 

    Hope to see some of you there,

    Scott

  • The Danger of Lorem ipsum

    I picked up a great quote from the Refresh The Triangle meeting the other night: "Copy is the easiest and often cheapest thing to fix." - Jeffrey Zeldman

     

    This really got me thinking about the role that copy plays in design. I often find myself leaving copy till the end, almost an afterthought, and rush to get something up to "fill the space" so I can go ahead and launch. This is pretty evident in the front page of 22books, I can definitely write a more compelling mantra for the site then what I tossed together hours before going live.

     

    I think this problem is best represented by the use of lorem ipsum text. Designers often use lorem ipsum text to fill in the parts of a design where the customers copy should go. The idea behind this is that using real text would distract you from the design, and lorem ipsum is gibberish for most of us. (wikipedia has an interesting history and examination) The problem is that this obviously is pushing the task of writing this copy to the very end where it will be shoe-horned into the rest of the design. Don't have enough text to fill up the space? Then you either ended up with a bad looking design or text that rambles and rambles to fill space. This is the same problem with using pre-defined site templates.

    I am working on a re-design of The Lounge and I am going to make the first step coming up with the copy and what I want to get across, then build the design around that copy.

    The text of your site is arguably the most important part of your site, leaving it to the end is a bad idea.

    -James

  • Travelogue: India

    Outside the Ella Compass Suites

    I spent the last week of February in Hyderabad, India. This was my first trip to India, and I thought I'd share some experiences.

    The Flight

    I flew from Washington D.C. to Hyderabad on Qatar Airlines. The longest leg, between D.C. and Doha, was on a Boeing 777-300ER – a long range jet with the largest engines in aviation history. The business class configuration on the plane made the time pass with relatively little agony. The lay-flat seats gave me 12 hours of sleep, and I used the on-demand entertainment system to pass the time with some new movies (mostly on the way home):

    I highly recommend Qatar Airlines. The business lounge in Doha is comfortable, and I had time to grab a shower in the marbled and well-stocked washrooms. Service is second none, and the food is the best I've ever had in the air – smoked salmon, brie, champagne, filet mignon, prawns, and Godiva chocolates. The endless stream of food and drink was served by a team of young models – all smiling and very easy on the eye.

    The downside to this experience is that my next domestic flight will feel worse than ever. Satan himself recruits airline executives from the United States to mange the first circle of hell.

    The Airport

    Golcanda Fort

    I just have to tell you about the Hyderabad airport experience. My flight, like most International flights to India, arrived in the middle of the night. You'd think an airport would be empty at 3 in the morning, but you'd be wrong. There was a 30 minute wait to get through immigration, which isn't too bad, but it was amusing. Lines would close and open arbitrarily, forcing people to shuffle and maneuver into new lines. There were things that happened in this shuffle that would have resulted in bloodshed had they happened in, say, Newark, N.J. But this was India, and personal space can't afford to exist.

    At one point a new line opened, but the man behind the counter shouted "women only!" So I stayed in the long line of forlorn looking men and together we stared at this long line of women. For a brief moment I was hoping this would turn into one of the scenes I've watched in Bollywood movies. You know – the line of women start singing and dancing, and then the line of men start singing and dancing, and before you know it, the entire cast is embracing and gyrating out the door to freedom. I did some light stretching to warm up in case the music started, but nothing materialized.

    The arrivals area outside was a sea of humanity. People were stacked 7 deep waiting for loved ones to arrive, or perhaps they were there just to watch the spectacle. I found my driver quickly, and waited just a few minutes for him to bring up the car. I listened to the jangle of excited voices. Watched the flashing and weaving of motorbikes. Felt a tug from a young lady begging. Smelled diesel fumes from rickshaw motors. Tasted dirt in the air.

    India welcomed me with an assault on all senses.

    Hyderabad

    Fruit stand outside Hyderabad

    Most of my time was spent in HITECH city, slightly northwest of Hyderabad proper. The Microsoft campus there is eerily similar to the campus in Redmond, right down to the color of the glass and signage. The only major difference is the unrelenting source of heat and light that hangs in the sky over the Hyderabad campus. Redmondites might have heard of it – it's called the sun. I was on campus everyday teaching for Pluralsight

    I did get a chance to venture into the city, and also to the nearby Golconda fort. The fort is built on a hill of granite and dates back to 1143. The outer wall has a circumference of 7km. Inside are iron studded gates, mosques, temples, ornate stonework, and a blend of Hindu and Muslim architecture. The gates also featured an impressive acoustical effect. A person can stand under the carefully designed dome and clap. That clap can be heard at the top of the mountain over one kilometer away! Hundreds of years ago, the claps would signal the king's arrival, or an enemy's encroachment.

    Riding in the streets of Hyderabad I witnessed only a glimpse of the diversity that is in India. A women wrapped in a brightly colored sari stands alongside a Muslim women covered in a plain black jilbab. An old farmer with a handful of vegetables stands alongside a young businessman with his cell phone. It's a dizzying mix of life in the swarming streets of an old city. And yes, the driving in India is everything you've ever heard it is – and quite possibly worse than you ever imagined.

    The road is lawless, but the people are polite. I'd say hospitality in India is second to none. Everyone I talked to was warm, inviting, and eager to share a story. It was entertaining to sit down at a meal and listen to conversations. Some talks would begin in English then suddenly veer into a local tongue. Another blink of the eye - and it's English again. Fortunately, someone was always willing to translate for me.

    Finally, I'd be remiss if I didn't tell you about the food. I've developed a passion for Indian food over the last 5 years, and was delighted to find a mix of both northern and southern cuisines in this centrally located city. I had vadas, idlis and somber during breakfasts. Dosas and biryanis ruled for lunch, while paneer dishes (including my favorites palek paneer and mutter paneer), and a variety of curries and tandoori dishes were fair game for dinner. I was as close to achieving a gastronomic orgasm as one can get (although I'll be honest – by the end of the week I had this undeniable craving for a New York style pizza).

    Suddenly, I Was Gone

    Downtown Hyderabad

    One week isn't a great deal of time to spend somewhere so far from home. I was just getting over the jetlag when I stayed up to catch a 5 a.m. flight home. In the airport, I was reading the local newspaper when I came across some funny ads:

    Increase your bust line with a new herbal mix developed by scientists in the United States! Start looking more attractive with a bigger bust line in 3 months! Call now!

    And:

    Increase your height using a new lotion developed in the United States! Don't be short any longer – just apply this lotion to the soles of your feet once a day for six months! Order now!

    Funny, because I think I've seen the same rip-offs advertised in U.S. newspapers, only the lotions are developed by wise monks who live in the misty mountains of India.

    I guess it's true the world over – countries far away from your own carry an aura of mystique and magic. Anything is possible over there!

    I was fortunate enough to see the mystique of India up close.

  • Extension Methods for Profit

    Some say we are living in the information age, but I say this is the advertisement age. Marketers strive to cover every square inch of the planet and outer atmosphere with slogans and promotions. We have ambient advertising and advergames, human billboards and celebrity branding.

    My prediction is that marketers will become more aggressive in placing advertisements directly inside the software used by information workers who are laden with disposable income. Microsoft is well positioned for the next wave of advertising with the addition of extension methods in C# and Visual Basic. Just imagine the number of eyeballs that will see the following methods in an Intellisense window.

    namespace System
    {
        
    public static class CurrentAdvertisements
        {
            
    public static void TheJoyOfPepsi(this object cola)
            {          
            }

            
    public static void BuiltFordTough(this object truck)
            {
            }

            
    public static void EatAtHooters(this object notForTheFood)
            {
            }
        }
    }

    Big bucks are waiting there.

    The only question is – will advertisers be content to stick with the traditional camel casing of method names, or will they pay a premium for Underscored_Product_Placements?

  • Announcing the .NET Small Publisher Room at The Lounge

    Since taking over The Lounge I have talked to a number of people interested in joining, but one of the issues with the revenue sharing model we use is that the sites in each room need to be somewhat comparable when it comes to influence and impressions. This means I have had to turn away publishers who might not be as large as the heavy weights currently in the .NET room. I have been thinking about how to best handle this and I have decided to launch a new room for smaller .NET publishers. I don't believe that impressions are everything and I think it is very valuable to an advertiser to have their ad run on these highly influential developers blogs. Here is the starting lineup of this new room: Geek. And Proud of it by Steven Harman B# by Ben Scheirman FrazzledDad by Jim Holmes The blog of Michael Eaton Visual Studio Hacks (will be running ads in the next couple days when the re-design launches) TechToolBlog by Tim Boland In this short list you have MVPs, conference organizers, speakers, and other influentials. I have also pushed to make The Lounge ads on these sites the only graphical ads you will see, and on the majority of the sites they will be the only ads. One of my other goals for this room is to offer a lower barrier to entry for advertising, blocks in this room start at $250/month (or $200 a month on a three month contract) which is much more affordable for smaller companies and possibly even Micro-ISVs. To start with I am only going to sell 2 blocks a month, so if you are interested please get in touch with me quickly before it sells out. If you have a .NET focused blog and are interested in joining the room please send me an email with a link to your blog and a couple sentences on why you think you would be a valuable addition to the room. I am not going to add more publishers until the room sells out, but after that I hope to add 3-5 publishers a month. -James
  • Focusing on Design

    Lately I have been thinking more and more about design. Not "big up front design" and the piles of specs and UML, but user interface and application design. When you think about the applications that you use the most, they are usually the applications that solve an important problem or provide an essential service, and they make it easy, simple, and enjoyable to do it.

    To people who would argue that back-end performance, uptime, scalability, unit tests, etc. are more important than design I would simply point to Twitter. Twitter has had many problems, but they continue to thrive because they provide an excellent service in such a nice and simple, usable, way. Don't get me wrong, Twitter needs to fix there problems, but you could fill up 140 characters pretty quickly with the names of all the sites that had tons of scalability, uptime, unit tests, and failed because they were hard to use.

    As a developer and a consultant I usually get zero input into the design of an application from a usability and design perspective. Over the last 8 years I have built a windows forms application that acts that feels like a FoxPro application, a web application that feels like a mix between a Windows application and an AS/400 application, and now I am working on a web application that feels and acts like an Access application. I guess it partly comes with the territory of working on enterprise applications that are replacing legacy systems, but I can only imagine the benefit to the application and the company if we had taken the time to re-think the problems we were solving and come up with a simpler and easier to use design.

    I don't want to make these mistakes on my own applications and sites, so one of my main goals this year is to learn the most I can about design.

    The other night I went to a local group called Refresh The Triangle and watched a presentation by Rob Goodlatte that really opened my eyes and helped me realize how much I don't know about design in general. Rob talked about designing a web site and how it is more than just aesthetics and you have to carefully look at the purpose and function first before just "making it look nice". In my mind I have always somewhat separated application functionality and UI design from the aesthetics and I can now see that they are all one and the same. You shouldn't do all your UI and application functional design and then just slap some pretty colors and design on there. And vice-versa you shouldn't mock up some pretty aesthetics and them mash your UI into it.

    This thought leads me down a path I didn't think I would be going, which is namely to become more of a graphic designer as well. In the past I have usually paid someone else to do design of my sites, but now I can see some of the problems that has caused. The rest of Rob's presentation includes lots of insight in how to use things like grids, baseline grids, typography, etc. These are all things I am going to spending more time learning and blogging about in the future.

    -James

This Blog

Syndication

Powered by Community Server, by Telligent Systems
'