Scott Hanselman

The Weekly Source Code 24 - Extensibility Edition - PlugIns, Providers, Attributes, AddIns and Modules in .NET

April 18, 2008 Comment on this post [17] Posted in ASP.NET | ASP.NET MVC | Learning .NET | Programming | Source Code | VB
Sponsored By

I've been getting more and more interested in how folks extend their applications using plugins and things. In my new ongoing quest to read source code to be a better developer, Dear Reader, I present to you twenty-fourth in a infinite number of posts of "The Weekly Source Code."

There's a lot of ways to "extend" an application or framework. Probably dozens of patterns. You can learn about the Gang of Four Patterns using C# over here.

I was looking and three chunks of code this week that extend things or are extensible. The first was xUnit.NET, the new Unit Testing Framework on the block (until I finally go File|New Project and bang out "HanselTest2000" ;) ) and the second was some source that Miguel Castro gave out at the March 2008 CINNUG meeting called Sexy Extensibility Patterns. Miguel has a Code Generation/Data Mapping tool called CodeBreeze that uses this patterns. It was on DNRTV a while back. The third was the plugin design of Windows Live Writer and the WLW SDK.

This post isn't trying to be an exhaustive list of anything, it's just some cool code that's got me thinking about interesting was to extend stuff. I like these three examples because each has more than one way to extend it.

Extending software means adding functionality that wasn't there to start with. There's MANY ways to do it though. For example, adding a script engine like VBA or PowerShell and hosting script would be one way. Making a public scripting-friendly API is a twist on that theme. Hosting AddIns or Plugins via deriving from base classes, implementing interfaces or sourcing events. using System.AddIn, is another.  Using a Dependency Injection Container is a more advanced and powerful way to extend applications.

xUnit.NET

image xUnit.NET is a .NET Unit Testing Framework from Brad Wilson and Jim Newkirk (formerly of NUnit fame). Initial reaction to their framework was a resounding "meh" as folks asked "seriously, do we NEED another Unit Testing Framework?" but they soldiered on, and just like the little Mock Framework that could, they're starting to get the respect they deserve. It's got an MSBuild task, Resharper and TestDriven.NET Test Runner support, and most importantly, the framework has some interesting extensibility points.

The xUnit.NET source code is exceedingly tidy. I mean that as a total complement, like when you visit someone's house and you find yourself asking "who is your decorator?" while simultaneously realizing that they are just THAT tidy and organized.

ASIDE: Not enough people use "Solution Folders" in Visual Studio. Seriously, folks, just right-click and "Add | New Solution Folder," start dragging things around and bask in the tidiness.

They've separately any controversial (my word) static extension methods into separate projects, xunitext and xunitext35 that includes .NET 3.5-specific features. So, certainly Extension Methods are a coarse extensibility point for developers "downstream" from your framework.

They use Attributes as MAJOR way to extend their framework. For example, say you want something to happen before and/or after a test.

namespace XunitExt
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class TraceAttribute : BeforeAfterTestAttribute
public override void Before(MethodInfo methodUnderTest)
{
Trace.WriteLine(String.Format("Before : {0}.{1}", methodUnderTest.DeclaringType.FullName, methodUnderTest.Name));
}

public override void After(MethodInfo methodUnderTest)
{
Trace.WriteLine(String.Format("After : {0}.{1}", methodUnderTest.DeclaringType.FullName, methodUnderTest.Name));
}
}
}

You just derive a new attribute from BeforeAfterTestAttribute, and put it on a test. The [Fact] attribute is a standard one. They use it instead of [Test]:

[Fact]
[Trace]
public void CanSearchForSubstrings()
{
Assert.Contains("wor", "Hello, world!");
}

Now, my code in Before() and After() above will execute for this test.

If you've got your own Test Framework but you want to move towards using xUnit.NET, they've got a [RunWith] attribute, where you can make your own Test Runner and say, for example, "run this test with nUnit." You can use it two ways, either as [RunWith(typeof(MyRunner)] or with a custom attribute like:

public class RunWithNUnitAttribute : RunWithAttribute
{
public RunWithNUnitAttribute()
: base(typeof(NUnitCommand)) {}
}

...where nUnitCommand implements a very clean interface called ITestCommand that "describes the ability to executes all the tests in a test class."

public interface ITestClassCommand
{
object ObjectUnderTest { get; }
ITypeInfo TypeUnderTest { get; set; }
int ChooseNextTest(ICollection testsLeftToRun);
Exception ClassFinish();
Exception ClassStart();
IEnumerable EnumerateTestCommands(IMethodInfo testMethod);
IEnumerable EnumerateTestMethods();
bool IsTestMethod(IMethodInfo testMethod);
}

I think this is a very elegant interface. The framework "eats its own dogfood" also, which means that the xUnit.NET guys have factored things appropriately (as they should have) such that they are using their own extensibility points. Using your own framework to build your stuff is the only way you'll know if you've got a great framework and it's the best way to find out what's NOT working.

The NUnitCommand implementation then uses the NUnit SDK/API to run test. This allows you to move over to xUnit.NET, if you like, from NUnit or another test framework a little at a time, while running all the tests under the same runner.

Another way to extend your code is through the use of existing well-known interfaces like IComparer<T>, for example. They're a test framework, so they're full of Asserts like Assert.Equal and Assert.Contains. The Assert.InRange has an overload, seen below, than can take an IComparer as an optional parameter.

public void InRange<T>(T actual,
T low,
T high)
{
Assert.InRange(actual, low, high);
}
public void InRange<T>(T actual,
T low,
T high,
IComparer comparer)
{
Assert.InRange(actual, low, high, comparer);
}

This might seem obvious to some, but it's thoughtfully obvious and a clean extensibility point. And thoughtfully obvious is easy to say and hard to do. I'm thinking that Moq and xUnit.NET just may be the new peas and carrots - they go together nicely and each have the similar goals.

Sexy Extensibility Patterns

You know someone likes their job and coding when they describe a pattern as "sexy" and not just "handsome" or "sassy." Miguel includes his slide deck and code in both C# and VB up on the CINNUG website.

Miguel calls out three main extensibility types that he uses (from his presentation):

  • Providers - Allow abstraction for data and behavior
  • Plugins- Adding new behavior
  • Modules - Centralize plug-in functionality and enforce manageable standards

Providers are based on the Strategy Design Pattern and look like this. You'll see stuff like this all throughout ASP.NET 2.0. A controller or context class needs a way (hence "strategy" to do something). Classically an instance of a class that provides the needed strategy is passed in, but nowadays it could come from an IOC framework, or just a config file.

They're often very simple and they're easy to write. Make an interface that provides something, usually data:

namespace Core
{
public interface IDataProvider
{
string GetSource();
string GetData(string source);
void LogData(string data);
}
}

Then use it. This is a simple example, but usually this would be buried in a ProviderFactory that would hide the config and activation, and even hold the new instance:

public void ProcessData()
{
string s_Provider = ConfigurationManager.AppSettings["dataProvider"];

Object o = Activator.CreateInstance(Type.GetType(s_Provider));

IDataProvider o_Provider = o as IDataProvider;
string s_Source = o_Provider.GetSource();

string s_Data = o_Provider.GetData(s_Source);

if (s_Data != "")
{
o_Provider.LogData(s_Data);
}
}

Aside: Personally I find the quasi-Hungarian naming in Miguel's source off-putting, but I know him well enough to say that. ;)

So, Providers provide stuff, and Plug-Ins add functionality, like:

public class ArchiveProcessing : IPostLogPlugin
{
void IPostLogPlugin.PerformProcess(string data)
{
// take data and archive it
}
}
public class ArchiveProcessing : IPostLogPlugin
{
void IPostLogPlugin.PerformProcess(string data)
{
// take data and archive it
}
}

You might have a bunch of plugins added to your config file and then call them synchronously, in this example, perhaps as a postProcessing step to a provider:

object section =  ConfigurationManager.GetSection("postProcessing");
List<plugininfo> o_Plugins = section as List;
foreach (PluginInfo o_PluginInfo in o_Plugins)
{
object o = Activator.CreateInstance(Type.GetType(o_PluginInfo.PluginType));
IPostLogPlugin o_Plugin = o as IPostLogPlugin;
o_Plugin.PerformProcess(s_Data);
}

Modules, in Miguel's parlance, are like Filters that get involved in a process and various points (like HttpModules) and change functionality. First you define some events:

public delegate void AcmeModuleDelegate<t>(T e);
public class ModuleEvents
{
public AcmeModuleDelegate<checkdatasourceeventargs> CheckDataSource { get; set; }
public AcmeModuleDelegate<preprocessdataeventargs> PreProcessData { get; set; }
public AcmeModuleDelegate<postprocessdataeventargs> PostProcessData { get; set; }
}

You might add a bunch of modules to your application and have them listen in at these three or more "events." Then you need to ask yourself, do these things fire in order and more importantly, can a module cancel the process? To make this happen, modules would have to each consciously respect the cancel boolean and that's not really enforceable.

A Module is passed a ModuleEvents in this example so they can hook up to the shared delegate. This is called a multi-cast delegate because if I call it, EVERYONE gets called:

public interface IAcmeModule
{
void Initialize(ModuleEvents events);
}

public class ArchiveModule : IAcmeModule
{
void IAcmeModule.Initialize(ModuleEvents events)
{
events.PostProcessData += events_PostProcessData;
}

void events_PostProcessData(PostProcessDataEventArgs e)
{
// perform archive functionality with processed data
}
}

You'd call the multicast-delagate like this

CheckDataSourceEventArgs o_EventArgs =  new CheckDataSourceEventArgs(s_Source);
o_FilterEvents.CheckDataSource.Invoke(o_EventArgs);

Or, you could spin through the delegates and invoke them yourself, checking the cancel flag and stopping the whole thing yourself. Miguel's got a nice sample app and PPT with lots more code that illustrates this point well.

Then you can take all these concepts and put them together into a single extensible app with providers, plugins, modules that all work together. I like to keep all my Interfaces separated in another assembly and version them slowly, only when the contract changes. 

Windows Live Writer

Windows Live Writer is what I use to post to my blog. I'm typing in it right now. If you're using an admin web page to post to your blog, stop. Go download it now, I'll wait here. Ok, it's got three kinds of extensibility (from MSDN):

  • Application API, for launching Writer to create new posts or "Blog This" items for links, snippets, images, and feed items.
  • Content Source Plugin API, for extending the capabilities of Writer to insert, edit, and publish new types of content.
  • Provider Customization API, for customizing both the capabilities of Writer as well as adding new capabilities to the Writer user interface.

Let's handle the last bullet, first, the Provider Customization API. Extensibility can also mean extending an application without using code at all. Check out how to extend the Windows Live Writer UI using only an XML file for DasBlog. No code was required. Sometimes, just a thoughtful XML file provides the extensibility points you need.

The Content Source Plugin API is a slick thing, letting you add your own "Insert" commands directly to WLW. There's 85 plugins at the time of this writing in the gallery.

This time last year I took Travis's CueCat and make a CueCat Windows Live Writer plugin so I could more quickly post my Monthly Reading List (which tragically, ended up being yearly out of laziness. Note to self: Self, post a monthly reading list.)

Anyway, I wrote an article for Coding4Fun and blogged as well. The Plugin looked like this:

Windows Live Writer has a cool model for Plugins. There's the potential for adding lots of functionality. You're adding a link and picture to the main UI, an undefined number of forms, plus you'll need storage, and you'll want to insert HTML into the main Editor window. This could potentially be a complex plugin model, but Joe Cheng and the others on the team made it, IMHO, very easy.

How does the plugin model for WLW enable all this? The code for a plugin speaks volumes:

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using WindowsLive.Writer.Api;

namespace AmazonLiveWriterPlugin
{
[WriterPlugin("605EEA63-B74B-4e9d-A290-F5E9E8229FC1", "Amazon Links with CueCat",
ImagePath = "Images.CueCat.png",
PublisherUrl = "http://www.hanselman.com",
Description = "Amazon Links with a CueCat.")]
[InsertableContentSource("Amazon Links")]
public class Plugin : ContentSource
{
public override System.Windows.Forms.DialogResult CreateContent(System.Windows.Forms.IWin32Window dialogOwner, ref string newContent)
{
using(InsertForm form = new InsertForm())
{
form.AmazonAssociatesID = this.Options[AMAZONASSOCIATESID];
form.AmazonWebServicesID = this.Options[AMAZONWEBSERVICESID];
DialogResult result = form.ShowDialog();
if (result == DialogResult.OK)
{
this.Options[AMAZONASSOCIATESID] = form.AmazonAssociatesID;
this.Options[AMAZONWEBSERVICESID] = form.AmazonWebServicesID;
Product p = Decoder.Decode(form.CueCatData);
AmazonBook book = AmazonBookPopulator.CreateAmazonProduct(p, form.AmazonWebServicesID);
string associatesId = form.AmazonAssociatesID.Trim();
string builtAmazonUrl = removed for cleanliness";
newContent = string.Format(builtAmazonUrl, book.ID, associatesId, book.Title, book.Author);
}
return result;
}
}
}
}

Their plugin model uses a combination of things. There's attributes on the class that give details on where images are (embedded as resources), text, URLs and a GUID for uniqueness. There's a base class that makes a "Hello World" plugin a one-line affair. And there's a clean way to show any WinForm, show it and tell WLW what the result was. The HTML is returned by reference in newContent while the return value was a standard DialogResult. If you need storage for state, they pass in a simple dictionary-like Interface to your plugin when you're initialized. As a plugin, you don't need to sweat storage, or how you appear in the list of plugins, you just focus on your main dialog.

Do you have any cool examples of elegant, cool, convenient, clever extensibility mechanisms?

About Scott

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

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Hanselminutes Podcast 108 - Exploring Distributed Source Control with Git

April 16, 2008 Comment on this post [18] Posted in Podcast
Sponsored By

git-logo My one-hundred-and-eighth podcast is up. In this episode I sit down with Robby, Gary and Andy from Planet Argon, a local Rails shop in Portland, OR, and talk about their experience as they move from Subversion to Git for their source control.

Links from the Show

Subscribe: Subscribe to Hanselminutes Subscribe to my Podcast in iTunes

If you have trouble downloading, or your download is slow, do try the torrent with µtorrent or another BitTorrent Downloader.

Do also remember the complete archives are always up and they have PDF Transcripts, a little known feature that show up a few weeks after each show.

Telerik is our sponsor for this show.

Check out their UI Suite of controls for ASP.NET. It's very hardcore stuff. One of the things I appreciate about Telerik is their commitment to completeness. For example, they have a page about their Right-to-Left support while some vendors have zero support, or don't bother testing. They also are committed to XHTML compliance and publish their roadmap. It's nice when your controls vendor is very transparent.

As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

Enjoy. Who knows what'll happen in the next show?

Technorati Tags:

About Scott

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

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Putting ASP.NET Dynamic Data into Context

April 11, 2008 Comment on this post [25] Posted in ASP.NET | ASP.NET Dynamic Data
Sponsored By

There's a lot of folks excited about ASP.NET MVC as an option for creating ASP.NET websites. As I say in my ASP.NET MVC talks, however, I figure about 5% of people creating ASP.NET sites will care about ASP.NET MVC. I say that for a number of reasons. ASP.NET MVC is a big paradigm shift. It enables the developer to make a more testable site, to have absolute control over their markup, and to separate concerns in order to keep their code DRY (don't repeat yourself). However, MVC is not yet the ideal solution, in my opinion, for really data- and forms-heavy sites. Creating an data grid with editing in place with sorting, movable columns and all that coolness is hard in MVC as someone needs to manage all that state for you and there's some underlying infrastructure that's not there.

So, What about the other 95% of developers? Certainly WebForms isn't going away, and it is a proven solution for line of business apps. Personally, I'll probably use some kind of hybrid as I have in the past at other jobs. DasBlog doesn't use MVC (yet) but it's templating system is MVC-like and it lives side-by-side with WebForms. Basically, there's a lot of WebForms developers out there just trying to get data up into a Grid or Edit view and also keep it DRY.

You'll probably stumble onto information around ASP.NET Dynamic in your wanderings and I wanted to give you some information to put Dynamic Data's pending release into ASP.NET's larger context.

What is ASP.NET Dynamic Data?

Here's the Preview Drop of Dynamic Data for download. It'll be released later this year in a future Service Pack for .NET Framework 3.5. This is a pre-release build that's updated since the relatively quiet preview release last December.

Fundamentally, Dynamic data is new controls for DetailsView, FormView, GridView, or ListView controls along with a lot of meta-infrastructure classes to make it possible. The design uses convention over configuration in a number of places, and this marks, IMHO, the recognition of a simpler way to do things.

If you can point at one thing in Dynamic Data and say, "that's it!",  it'd be DynamicControl. it's a control that takes metadata from your Database model (LINQ to SQL or LINQ to Entities in v1, other POCOs (Plain Old CLR Objects) or ORM's possibly in v.Next) and selects from a FieldTemplateUserControl.

Stated differently, if you've got a field in a dozen places that should show Phone Numbers, you probably want a Textbox, some validators, maybe a MaskedEditControl, or perhaps some 3rd party controls. You think about it as a Phone Number. if you decide to change that control, you want to change it for the whole application. You want to keep it DRY (Don't Repeat Yourself). Currently, unless you had the discipline to create a PhoneNumberUserControl, you'd have to do "monkey work" and go find all the instances of that field and keep them up to date. You'll be repeating yourself all over with data that should exist in one place, like the length of the field in the database, gets copied into possibly dozens of places, validators, controls, etc.

Here's a comment that my friend Peter Blum left on ScottGu's Blog. It actually was Peter, not the Product Team, who helped me "grok" Dynamic Data a few weeks ago. We spent a few hours on the phone talking and it finally popped for me.

I have been working with Dynamic Data for over a month and am very excited about it. I wanted promote an aspect of Dynamic Data that will be used in many other situations than the application Scott showed.

Dynamic Data introduces a new web control called DynamicControl. It can be used in FormView and ListView controls to provide a UI based on database-level schema. When using GridView and DetailsView, you add a DynamicField, which is a replacement for the BoundField that internally has a DynamicControl. (Thus has all of the features of a DynamicControl.)

This results in your Grids and data entry forms being built around tables and columns of your database with whatever smart data entry controls you like, such as the AJAX Control Toolkit's MaskedTextBoxExtender on a textbox or your favorite third party controls. The database schema also determines the validators for this column. That avoids errors implementing the right validators or updating them when the database schema is modified. (No more "how do I validate a BoundField?" issues!)

To me, Dynamic Data is a major step forward in developing data entry oriented web applications for ASP.NET.

imageOne of the demo's that is often shown is Dynamic Data's "scaffolding" feature. Basically, you point the wizard at a database and "poof" you've got a nice DataGrid Admin-like site. However, to dismiss it as a scaffolding tool is just the mistake I made when I first saw it.

How does it work?

There's a LOT of cool plumbing to Dynamic Data and I'll try to work with the team to get a podcast or two done and some articles explaining the deep how. Here's the basic how.

You can make a new Dynamic Data Website and it looks pretty much the same as any other site, because it is. It's a WebForms site just like any others, except for a new folder, called DynamicData. That folder has a web.config of its own to block access. This is the convention. Let's open it up.

image 

Let's say I want some serious customization. Let's so that the page for the Products table should be TOTALLY custom, but just the ListDetails page. I'll put that under /CustomPages. Let's say I want to use a Telerik control for DateTimes, Integers, and TextAreas, but just some of them.

 image

Nothing HAS to look the way it comes by default. Everything is customizable. If I want grid paging to look like whatever i want, I change the GridViewPager.ascx. You can customize at the Table, Column and DataType level.

I can put "hints" on a metadata-specific class like this:

[Range(0, 100)]
[UIHint("IntegerTelerik")]
public object UnitsOnOrder { get; set; }

That UIHint will be used later when I hook up a DynamicControl. As soon as DynamicData sees I'm bound to the UnitsOnOrder column, it'll automatically find IntegerTelerick_Edit - based on the naming and location convention - when it needs to show the "Edit" state. I can set it on a pull column basis, and then I can change it everywhere from one place.

Here's what that ASCX looks like in code:

<%@ Control Language="C#" Inherits="System.Web.DynamicData.FieldTemplateUserControl" %>
<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.Linq" %>
<%@ Register assembly="Telerik.Web.UI" namespace="Telerik.Web.UI" tagprefix="telerik" %>

<script runat="server">

protected void Page_Load(object sender, EventArgs e) {
var metadata = MetadataAttributes.OfType<System.ComponentModel.DataAnnotations.RangeAttribute>().FirstOrDefault();
if (metadata != null) {
RadSlider1.MinimumValue = (int)metadata.Minimum;
RadSlider1.MaximumValue = (int)metadata.Maximum;
}

}

protected override void ExtractValues(IOrderedDictionary dictionary) {
dictionary[Column.Name] = ConvertEditedValue(RadSlider1.Value.ToString());
}

</script>

<telerik:RadSlider ID="RadSlider1" runat="server" Value="<%# (short)FieldValue %>" />

See how it's generic (by that I mean non-specific, not CLR Generic)?  I've replaced the Textbox that is usually used for an Integer and am using a Telerik Slider. The [Range] attribute can be pulled off and popped into this instance of the control.

Here it is at runtime, next to some other Integer columns:

image

Now, I get to think about selecting the correct DataType via UIHint rather than using the ASCX directly. It makes the control really reusable within the context of data binding and keeps me from repeating myself.

I can add Validation Controls to a data type, so the Validation exists in one place, rather than repeated all over. For example, if you wanted to swap out validation for one, or all, your controls, to use Peter's Validation and More (which rocks, by the way, we bought a site license at my last job) than you'd do it once per data type.

This is just one VERY simple example, but it's, I think, I pretty good one. Thanks to Scott Hunter for helping me out with this as well as my talk at Devscovery last week. There are some good Dynamic Data samples he's done that you can download and check out. One includes a "before and after" application that shows how an address book would be coded using the new DynamicControl and the older way (using BoundControl).

An even cooler (and advanced) example is one where Scott Hunter wants to pull an funky binary encoded image out of an old database. He makes a custom control that handles a custom data type called "DbImage" and completely encapsulates the display of that column. From the point of view of the GridView, it's just a DynamicControl that shows itself as an <img> tag. 

Sheesh, ASP.NET is changing too fast, this is too much to absorb

This is a big deal to me because it's going to make a subset of my work easier. If I've got a database and I don't mind using LINQ to SQL or LINQ to Entities (for now), I'll be able to create CRUD (Create, Read, Update, Delete) websites WAY faster.

Projects with Dynamic Data will be more customizable than those "typical Microsoft demos" where someone drags a DataSource and GridView over to the Design Surface, shows you a list of Products from Northwind then waits for applause. ;)

Why is this NOT a big deal? Everything you are used to still works as before. This is additive and simple if you just want to avoid repeating yourself.

Why is it on Code Gallery?

You might notice that this pre-release drop is on MSDN Code Gallery, that's a temporary thing to get your feedback. It'll eventually find a home on http://www.asp.net as it's ultimately part of the larger ASP.NET framework.

Here's a diagram that we've used internally to decide where to put stuff. Consider this drop to be a "showcase" ;) as it'll only be up for a little while. If you have issues, bugs, opinions on Dynamic Data, go put them in the Issue Tracker as the team is watching closely!

clip_image001

Note: This Dynamic Data project at Code Gallery is a very temporary home for ASP.NET Dynamic Data in order to gather feedback. When ASP.NET Dynamic Data appears in an 'official' release, we will remove the release from this site and redirect you to the new 'official' release.

Should you Fear This Release?

It's a pre-release build, but it's pretty harmless. It does install a few Project Templates in VS, but it shouldn't screw up your VS install. If you are using ASP.NET MVC, be aware that this drop includes a version of the ASP.NET Routing. This will be reconciled when they all are released, but for now, be aware of your version numbers.

"This release includes the Dynamic Data runtime assemblies as well as versions of the System.Web.dll and System.Web.Extensions.dll assemblies that have been updated from the versions in the .NET Framework 3.5. The release also installs Visual Basic and C# templates that you can use in Visual Studio 2008 for creating a Dynamic Data Web site."

These updated DLLs will be GAC'ed, and there's a batch file for installing and uninstalling. The changes are largely additive, but if you're deeply risk-adverse, use a VM. The batch file will make it clear what's changing on your system and what's not. Be aware there's a different batch file for 64-bit vs. 32-bit systems. This will all be automatic in the final release as it'll be rolled into the .NET Framework.

Dynamic Data in a Nutshell

If you're using Data Binding and any of the DetailsView, FormView, GridView, or ListView controls to do CRUD, consider using Dynamic Data, especially if you're using the BoundColumn. It will save you time and trouble.

In the future, watch for the possibility of Dynamic Data for POCO (my term, not the teams), Dynamic Data for Silverlight and Dynamic Data for MVC. Now is your opportunity to be heard. I'd like the idea of Dynamic Data for NHibernate myself, so I'm pushing for that. Feel free to engage in the Dynamic Data Forums or post bugs on this release in the issue tracker.

Related Links

Technorati Tags: ,

About Scott

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

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

The Weekly Source Code 23 - Big Solution Edition

April 10, 2008 Comment on this post [8] Posted in Source Code
Sponsored By

My source code reading didn't have any rhyme or reason to it this week, but most of them were large, so this is the Big Solution Edition. In my new ongoing quest to read source code to be a better developer, Dear Reader, I present to you twenty-third in a infinite number of posts of "The Weekly Source Code."

BigPicture

Vertigo Software, the folks that did the Deep Zoom Hard Rock site at Mix have released to CodePlex their mouse-wheel support in a project called Big Picture. When I saw this initially, I said, "meh" but then realized upon reading it that there's some clever stuff here that goes beyond the mouse-wheel support that folks rushed to add (myself included) to their DeepZoom Helloworld Examples.

First, they've figured out (as of Silverlight 2.0 beta 1) how to disable the initial "zoom from nowhere" animation in DeepZoom. They turn UseSprings off initially, then turn it back on after the first motion has completed:

/// 
/// Handles the "MotionFinished" event fired by the MultiScaleImage, but only re-enables the "UseSprings"
/// property after the first motion completes (a little trick to properly bypass the initial "zoom in
/// from nowhere" animation when first loading)
///
/// The MultiScaleImage instance.
/// Unused RoutedEvent arguments.
void image_InitialMotionFinished(object sender, RoutedEventArgs e)
{
if (!isInitialMotionFinished)
{
isInitialMotionFinished = true;
image.UseSprings = true;
}
}

Simple, and obvious after the fact, but I hadn't figured it out. They also handle the issue of funky Uris in development vs. production by using App.Current.Host.Source:

Uri collectionUri;
if (Uri.TryCreate(App.Current.Host.Source, "/Collection/items.bin", out collectionUri))
image.Source = collectionUri;

They've also created a nice MultiScaleImageWrapper to encapsulate all the panning and zooming into one class.

DevServer

I wasn't sure what to make of this project when I started looking at it. The Project Description kind of made my eyes gloss over:

NetFXHarmonics DevServer is a web server hosting environment built on WPF and WCF technologies that allows multiple instances of Cassini-like web servers to run in parallel. DevServer also includes tracing capabilities for monitoring requests and responses, request filtering, automatic ViewState and ControlState parsing, visually enhanced HTTP status codes, IP binding modes for both local-only as well as remote access, and easy to use XML configuration.

Other than the WCF app we built at my last company, I haven't seen a lot of WCF stuff, and DevServer is an interesting and complete example of a Cassini-like Web Server. He wrote it because he wanted to more easily debug multiple WCF Services and ASP.NET Web Sites all working together. Rather than using client-side or sniffing tools, why not just take over the server?

The source is interesting to read holistically, but is also full of little useful utility methods. He parses out, decodes, and displays ViewState, shows headers, formatted and raw content, etc.

image_2

David Betz is a very prolific writer of code and has a number of projects up on CodePlex he's given back to the community. One particularly interesting one is his Minima .NET 3.5 Blog Engine that he uses as a training tool. It also, of course, runs his blog. Spend some time over there, there's lots to learn.

Visual LINQ Query Builder

LINQ is a little confusing and it can be difficult to visualize your queries and write them. Mitsu from MS France and his two French Students Simon Ferquel and Johanna Piou have written a Visual Query Builder for LINQ and enabled it in Visual Studio as an Add-In.

The Add-In uses WPF and has a number of cool animations and a fresh UI design. You can drag your LINQ to SQL classes in from the Class View and visually build the LINQ query using dynamically generated Listboxes and an innovative Tree View I've not seen before.

The Results pane shows not only a preview of the data that will be returned, but also the generated SQL and the generated LINQ query and code. The results are put in a static method in a static utility class.

 vlinq

image All the better, the code is available and while it feels early and beta-esque, it's an interesting read. I really enjoy looking at how folks lay out their solution structures.

They've also made liberal use of Class Diagrams, presumably because they're students, but also because they are attentive to detail, so for the harder parts, like Query Formatting, there is an associated Class Diagram. Another feature of VS2008 I always forget.

They've factored out an interesting VS Integration Project that could be of help to folks who are interested in making a Visual Designer and plugging it into Visual Studio. There's also a number of interesting WPF Controls like a "MultiStepControl" and "TreeListView."

This is an exceedingly large amount of work, and it's going to take me a while to digest it. In some ways it feels brilliant and in others it seems incredibly complex, possibly overly so. Fortunately, you don't have to read the source, you can just use by installing their MSI if you like.

About Scott

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

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Packing Light for Travel with Power and Geek Style

April 09, 2008 Comment on this post [39] Posted in Musings
Sponsored By

I've been traveling lately, and last week I posted 10 Guerilla Airline Travel Tips for the Geek-Minded Person. Next week I'm going to Seattle for the week and I really prefer to pack as light as possible. There's lots of tips on the net on how to squish your clothes (I use SpaceBags) and what luggage to use (I like half-sized wheeled totes) but what's really interesting to me is what gadgets and electronic equipment to pack that gives me the most functionality in the least space.

Here's what I'm packing for next week's trip:

Monster 4 Outlet Mini Power StripMonster 4 Outlet Mini Power Strip - Ordinarily I dislike Monster's stuff because its's so expensive, but this little gem is only $12. Paul Mooney gave me one of these and I love it. It's got four-outlets and a small extension core. The cord wraps around and it plugs into itself for storage. As Paul says, "When you're at the airport and you're looking for a plug, you're pushy. If you show up with one of these, you'll make three new friends!" They're amazingly useful when plugged into those lamps with outlets at the hotel.

Kensington Travel Plug Adapter Kensington 33117 International All-in-One Travel Plug Adapter - I love this plug. We took it all over Africa and Europe and it hasn't failed me yet. It even has a spare fuse inside. This plug is all-in-one with no pieces to lose. The plug tips are all stored inside and slide in and out. Use it along with the mini-power strip above and suddenly you've got four US power plugs. It doesn't convert voltage, but most electronic device adapters will convert voltage for you.

Maxtor 250 GB OneTouch Hard Drive Maxtor 250 GB OneTouch 4 Mini Portable Hard Drive - I've recently started doing all my presentations using Virtual Machines on this little drive. It's a great drive because it doesn't require external power, rather it uses a double USB cable to draw power. I have six VMs on this drive.

Kensington Power AdapterKensington K33197 120W Auto/Air Ultra Portable Notebook PC Power Adapter - This has replaced all my power bricks. It powers my PSP, iPod, anything USB, nearly any notebook, phone, digital camera. It'll even charge one high-power (laptop) and one low-power (phone) device at once with the Y-adapter. The brick is also about half the size of whatever came with your laptop. It's creepy small.

USB Mini CableUSB 2.0 A/Mini-B Cable (Black)- You literally can't have enough tiny USB cables. They are good for charging things, tethering with your SmartPhone for Internet access, or connecting to a portable hard drive. I keep at least four in my bag.

Garmin nuvi 350

Garmin nüvi 350 3.5-Inch Portable GPS Navigator - There just isn't a better GPS for your dollar than the Garmin Nuvi 250. I paid twice this and it was still worth it. The feature I like the most is that it speaks the street names using text-to-speech. The interface is clean and easy to use, and it has a mode for walking/hiking which is great around unknown cities. As an aside, it's got an SD Card slot, supports Audible audio-books, it's a passable MP3 player. It also charges via Tiny USB!

 

webcam Microsoft LifeCam VX-7000 Win USB - Don't listen to the low Amazon Reviews on this one. The early drivers sucked and the LifeCam software is a little "meh." However, the secret to this webcam is a Driver Only install. I use it in 64-bit Vista and do 640x480 high-res video calls with the family whenever I'm on the road, using the Skype Hi-Res Hack.

presentermouse

Microsoft Wireless Notebook Presenter Mouse 8000 - I've tried every little notebook mouse/usb dongle combo there is. Some have hidden USB receivers, some recess in the bottom, etc. This mouse has both a dongle, but also bluetooth. I've left the dongle at home and I just have to turn this mouse on and since I paired it once with my laptop, it just works. One less thing to sweat. Plus, it's a presenter mouse, so you just flip it over and it has a laser pointer, on screen magnifier, and Presentation Forward/Back buttons. It lets me move more freely when presenting, and my recent Mix presentation was better for it.

HTC Excalibur Dash

HTC S620 PDA Black Smartphone (Unlocked, Intl. Version) - I've got an HTC Excalibur unlocked phone that's hooked up to Cingular/AT&T. The best think I ever did was turn on unlimited data. Now I can use "Internet Sharing" with Windows Mobile. I can "tether" the laptop and the SmartPhone with two clicks, using either Bluetooth or USB (I use USB as it charges the phone also) and I've got pretty decent speed Internet (25k/sec) pretty much anywhere largish in the US. When I find a Wi-Fi hotspot that wants to charge me money, bam, I bust out the phone. I've found myself using public Wi-Fi less and less, as it's really dodgy in both reliability and speed, and just going with the slower, but always available AT&T Edge network. Both Gmail and Outlook notice when they are on slow connections and will adjust. Also, I don't need to carry around (or pay for) a Network Aircard for the laptop.

kindle Amazon Kindle - It's official, I loves my Amazon Kindle (my review). Sure, it's ugly. But it works. I don't have to sync it. I hate having one more thing to sync to some other thing. If it works wirelessly and I don't have to push any buttons, I like it. The Kindle delivers me the New York Times, Newsweek, and the Huffington Post, every day (or week, for Newsweek) and it just works. I've added a 2gig SD Card and put all my Audible books on it. I've got a dozen books, many free. The one caveat so far, I have had the battery run down over a few day period and the battery go dead when the wireless has been left on and constantly updates blogs, so I've started turning it all the way off at night and charging it like a cell phone. However, with wireless off, it'll go for 1000+ page turns before running down, plus it'll trickle charge from tiny USB.

About Scott

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

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

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