Scott Hanselman

Hanselminutes Podcast 149 - Deconstructing "blu" - a new WPF Twitter client from thirteen23

February 13, '09 Comments [10] Posted in Podcast | Windows Client | WPF
Sponsored By

blu Scott talks to Doug Cook, Hal Saville, and Lee Brenner about their dramatic new Twitter client, called "blu" (formerly "chirp") with a jelly aesthetic you have to see to believe. How do they find developing in WPF? What's their workflow? What's coming for the next release of blu? Let's put the pressure on them to make it even better, eh?

Subscribe: Subscribe to Hanselminutes Subscribe to my Podcast in iTunes

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!

Building quality software is never easy. It requires skills and imagination. We cannot promise to improve your skills, but when it comes to User Interface, we can provide the building blocks to take your application a step closer to your imagination. Explore the leading UI suites for ASP.NET and Windows Forms. Enjoy the versatility of our new-generation Reporting Tool. Dive into our online community. Visit www.telerik.com.

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?

About Scott

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

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

Hanselminutes Podcast 148 - MEF - Managed Extensibility Framework with Glenn Block

February 13, '09 Comments [2] Posted in Learning .NET | Podcast | Programming
Sponsored By

Glenn Block There's been lots of talk about MEF lately, but what the heck is it? Is it an Open Source Project or is it part of the .NET Framework? Is it both? Is it an IOC Container or something new? Glenn Block sets Scott straight in this interview recorded on the Microsoft Campus.

Subscribe: Subscribe to Hanselminutes Subscribe to my Podcast in iTunes

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!

Building quality software is never easy. It requires skills and imagination. We cannot promise to improve your skills, but when it comes to User Interface, we can provide the building blocks to take your application a step closer to your imagination. Explore the leading UI suites for ASP.NET and Windows Forms. Enjoy the versatility of our new-generation Reporting Tool. Dive into our online community. Visit www.telerik.com.

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?

About Scott

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

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

ASP.NET Wire Format for Model Binding to Arrays, Lists, Collections, Dictionaries

February 13, '09 Comments [14] Posted in ASP.NET | ASP.NET MVC
Sponsored By

Levi Broderick, a Senior Developer on ASP.NET MVC and all around smart dude, posted some details to an internal Microsoft mailing list today and I thought it was worth sharing. Levi agreed and I've expanded on it some. Phil blogged some about Model Binding to a List last October.

The default model binder will handle a number of collection types for you, if you play by the rules and make your HTML form elements follow a certain format.

If the method signature looks like this:

public ActionResult Blah(Person[] people) {
// ...
}

And we are given this input in our HTML:

<input type="text" name="people[0].FirstName" value="George" />
<input type="text" name="people[0].LastName" value="Washington" />
<input type="text" name="people[1].FirstName" value="Abraham" />
<input type="text" name="people[1].LastName" value="Lincoln" />
<input type="text" name="people[3].FirstName" value="Thomas" />
<input type="text" name="people[3].LastName" value="Jefferson" />

Which turns into this as a HTTP POST:

people%5B0%5D.FirstName=George&people%5B0%5D.LastName=Washington&people%5B1%5D.FirstName=Abraham&people%5B1%5D.LastName=Lincoln&people%5B3%5D.FirstName=Thomas&people%5B3%5D.LastName=Jefferson

Which is basically:

people[0].FirstName = "George"
people[0].LastName = "Washington"
people[1].FirstName = "Abraham"
people[1].LastName = "Lincoln"
people[3].FirstName = "Thomas"
people[3].LastName = "Jefferson"

Then it will be just as if we had written this in code:

people = new Person[] {
new Person() { FirstName = "George", LastName = "Washington" },
new Person() { FirstName = "Abraham", LastName = "Lincoln" }
};

The way that we read in the properties is by looking for parameterName[index].PropertyName.  The index must be zero-based and unbroken.  In the above example, because there was no people[2], we stop after Abraham Lincoln and don’t continue to Thomas Jefferson. 

If the signature looks like this:

public ActionResult Blah(IDictionary<string, Company> stocks) {
// ...
}

And we are given this in HTML:

<input type="text" name="stocks[0].Key" value="MSFT" />
<input type="text" name="stocks[0].Value.CompanyName" value="Microsoft Corporation" />
<input type="text" name="stocks[0].Value.Industry" value="Computer Software" />
<input type="text" name="stocks[1].Key" value="AAPL" />
<input type="text" name="stocks[1].Value.CompanyName" value="Apple, Inc." />
<input type="text" name="stocks[1].Value.Industry" value="Consumer Devices" />

Which like this:

stocks[0].Key = "MSFT"
stocks[0].Value.CompanyName = "Microsoft Corporation"
stocks[0].Value.Industry = "Computer Software"
stocks[1].Key = "AAPL"
stocks[1].Value.CompanyName = "Apple, Inc."
stocks[1].Value.Industry = "Consumer Devices"

Then it will be just as if we had written:

stocks = new Dictionary<string, Company>() {
{ "MSFT", new Company() { CompanyName = "Microsoft Corporation", Industry = "Computer Software" } },
{ "AAPL", new Company() { CompanyName = "Apple, Inc.", Industry = "Consumer Devices" } }
};

The way that we read in the keys is by looking for parameterName[index].Key, and the way that we read in the values is by looking for parameterName[index].Value.  If the key or value type is a complex type (like Company, in the above example), then we treat parameterName[index].Key or parameterName[index].Value as the entire field prefix and start appending the .PropertyName suffix to the end of it.  The index must also be zero-based and unbroken, as mentioned previously.

Parameters of type IEnumerable<T>, ICollection<T>, IList<T>, T[], Collection<T>, and List<T> are bound using the first syntax.  Parameters of type IDictionary<TKey, TValue> and Dictionary<TKey, TValue> are bound using the second syntax.

Of course, as with most of ASP.NET MVC, if you don't like this behavior you're welcome to change it by writing your own binders for specific types or by pulling the information from a FormCollection directly and doing your own thing.

Levi adds:

FWIW – you don’t need the bracket notation if you’re submitting simple types to the server.  That is, if your request contains key=foo&key=bar&key=baz, we’ll correctly bind that to an IEnumerable<T>, IList<T>, ICollection<T>, T[], Collection<T>, or List<T>.  In the first sentence in this paragraph, "simple type" means a type for which TypeDescriptor.GetConverter(typeof(T)).CanConvertFrom(typeof(string)) returns true.  This makes a handful of cases simpler.

Thanks to Levi for the nitty gritty!

About Scott

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

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

Moonlight 1.0 Release - Open Source Silverlight 1.0 Implementation on Linux

February 12, '09 Comments [4] Posted in ASP.NET | Open Source | Silverlight | Windows Client | WPF
Sponsored By

image Congrats to Miguel (nice guy and a fine dancer) and team for the release of Moonlight 1.0. What is it?

"Implementation of Silverlight for Unix systems has officially reached its 1.0 level. We are feature complete, we pass all the Microsoft regression test suites and we shipped support for Microsoft's Media Pack for x86 and x86-64 architectures.

Moonlight is available as a Firefox plugin that can be installed with a single click from the moonlight download page."

It's an implementation of Silverlight 1.0 for Unix. That includes graphics, video/audio and the JavaScript bridge. It's not Silverlight 2.0, yet, so it has no execution engine. There's no CLR. Rather one uses Javascript to do work.

In the future (pronto, espero, Miguel?) Moonlight 2.0 will be the Unix version of Silverlight 2.0 and include the ECMA CLR execution engine (fancy words for "CLR on Linux in the browser").

You can watch a Silverlight, ahem, 2, screencast of the installation process over on Tim's blog or check these static screenies of me running OpenSUSE and Firefox, visiting http://videoshow.vertigo.com/ (a Silverlight 1.0 site), installing Moonlight, and watching a video. If you want to try it, you can burn a LiveCD (bootable ISO) that includes it here.

Moonlight 1.0 Installation Screenshots

I'm running OpenSuse 10.3 and Firefox 2, just to point out that you don't have to be super-bleeding edge to run this plugin. I visit http://videoshow.vertigo.com/ first, and I get the Microsoft Silverlight plug-in download badge.

Moonlight Install Step 1

Note that the folks that ran this page have not coded specially for Moonlight. When the badge is shown, clicking on it sends you to a Microsoft link that will sniff your browser and OS and send you to the right place for Silverlight. If Microsoft sees you need Silverlight 1.0 and you've got Linux, you're sent to http://www.go-mono.com/moonlight. This is cool (read: no evil) as Microsoft's detection code redirects you to Mono. Next, you get this screen:

Moonlight Install Step 2

Now, I select 32-bit vs. 64-bit, the click Download the Plugin, and I get the standard Firefox installation dialog, like any Firefox plugin:

Moonlight Install Step 2

Click "Install Now" and restart Firefox. I hit http://videoshow.vertigo.com/ and I can see the Silverlight application right there.

Moonlight Install Step 3

At this point in our installation, you're running all Open Source software. You won't, however, be able to play videos that require non-Open-Source-ed codecs. But, you can install the Microsoft Media Pack that includes codecs Microsoft has made available for Moonlight by right clicking on the Silverlight player and clicking "Install Microsoft Media Pack." Or, you'll be prompted the first time the Silverlight app tries to play the media.

Even thought Moonlight 1.0 exposes Silverlight 1.0 features, it uses a 2.0 media stack (minus DRM). That means, you can use media that uses these codecs:

Video:

  • WMV1: Windows Media Video 7
  • WMV2: Windows Media Video 8
  • WMV3: Windows Media Video 9
  • WMVA: Windows Media Video Advanced Profile, non-VC-1
  • WMVC1: Windows Media Video Advanced Profile, VC-1

Audio:

  • WMA 7: Windows Media Audio 7
  • WMA 8: Windows Media Audio 8
  • WMA 9: Windows Media Audio 9
  • WMA 10: Windows Media Audio 10
  • MP3: ISO/MPEG Layer-3
    • Input: ISO/MPEG Layer-3 data stream
    • Channel configurations: mono, stereo
    • Sampling frequencies: 8, 11.025, 12, 16, 22.05, 24, 32, 44.1, and 48 kHz
    • Bit rates: 8-320 kbps, variable bit rate
    • Limitations: "free format mode" (see ISO/IEC 11172-3, sub clause 2.4.2.3) is not supported.

Basically, the first time that Moonlight hits a page that contains media, it will ask you whether you want to install the Microsoft Media Pack which contains the codecs for all of the formats listed before. Microsoft offers the codecs for Linux on x86 and Linux x86-x64. If you want codecs on other *nix platforms, go vote here.

Now, click a video, and it'll play nicely in Moonlight on Linux:

Moonlight Install Step 3

Very cool. It was a smooth and fast install and it runs great. Where's Moonlight 2.0?! ;) Seriously, though, congrats to the team. If you want to check out the source for Moonlight 1.0, you can find it here.

Detecting and Supporting Moonlight and Google Chrome

While the Video.Show guys didn't have to do anything to support Moonlight, if you want to really customize the detection experience, make sure to visit Tim's blog post on Moonlight and Silverlight Detection scripts. He's updated the Silverlight.supportedUserAgent.js helper script to check for Linux and report correctly, and shows you how to hack in support (the currently unsupported but seems to work but don't quote me on that) for Google Chrome.

If you're interested in learning more about Silverlight, check out http://silverlight.net/learn/ as it's full of video tutorials and samples.

About Scott

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

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

Back to Basics: 32-bit and 64-bit confusion around x86 and x64 and the .NET Framework and CLR

February 11, '09 Comments [34] Posted in ASP.NET | Back to Basics | Learning .NET | Programming | Windows Client
Sponsored By

I'm running 64-bit operating systems on every machine I have that is capable. I'm running Vista 64 on my quad-proc machine with 8 gigs of RAM, and Windows 7 Beta 64-bit on my laptop with 4 gigs.

Writing managed code is a pretty good way to not have to worry about any x86 (32-bit) vs. x64 (64-bit) details. Write managed code, compile, and it'll work everywhere.

The most important take away, from MSDN:

"If you have 100% type safe managed code then you really can just copy it to the 64-bit platform and run it successfully under the 64-bit CLR."

If you do that, you're golden. Moving right along.

WARNING: This is obscure and you probably don't care. But, that's this blog.

Back to 32-bit vs. 64-bit .NET Basics

I promote 64-bit a lot because I personally think my 64-bit machine is snappier and more stable. I also have buttloads of RAM which is nice.

The first question developer ask me when I'm pushing 64-bit is "Can I still run Visual Studio the same? Can I make apps that run everywhere?" Yes, totally. I run VS2008 all day on x64 machines writing ASP.NET apps, WPF apps, and Console apps and don't give it a thought. When I'm developing I usually don't sweat any of this. Visual Studio 2008 installs and runs just fine.

If you care about details, when you install .NET on a 64-bit machine the package is bigger because you're getting BOTH 32-bit and 64-bit versions of stuff. Some of the things that are 64-bit specific are:

  • Base class libraries (System.*)
  • Just-In-Time compiler
  • Debugging support
  • .NET Framework SDK

For example, I have a C:\Windows\Microsoft.NET\Framework and a C:\Windows\Microsoft.NET\Framework64 folder.

If I File|New Project and make a console app, and run it, this is what I'll see in the Task Manager:

64-bit app running in Task Manager

Notice that a bunch of processes have *32 by their names, including devenv.exe? Those are all 32-bit processes. However, my ConsoleApplication1.exe doesn't have that. It's a 64-bit process and it can access a ridiculous amount of memory (if you've got it...like 16TB, although I suspect the GC would be freaking out at that point.)

That 64-bit process is also having its code JIT compiled to use not the x86 instruction set we're used to, but the AMD64 instruction set. This is important to note: It doesn't matter if you have an AMD or an Intel processor, if you're 64-bit you are using the AMD64 instruction set. The short story is - Intel lost. For us, it doesn't really matter.

Now, if I right click on the Properties dialog for this Project in Visual Studio I can select the Platform Target from the Build Tab:

image

By default, the Platform Target is "Any CPU." Remember that our C# or VB compiles to IL, and that IL is basically processor agnostic. It's the JIT that makes the decision at the last minute.

In my case, I am running 64-bit and it was set to Any CPU so it was 64-bit at runtime. But, to repeat (I'll do it a few times, so forgive me) the most important take away, from MSDN:

"If you have 100% type safe managed code then you really can just copy it to the 64-bit platform and run it successfully under the 64-bit CLR."

Let me switch it to x86 and look at Task Manager and we see my app is now 32-bit.

image

Cool, so...

32-bit vs. 64-bit - Why Should I Care?

Everyone once in a while you'll need to call from managed code into unmanaged and you'll need to give some thought to 64-bit vs. 32-bit. Unmanaged code cares DEEPLY about bitness, it exists in a processor specific world.

Here's a great bit from an older MSDN article that explains part of it with emphasis mine:

In 64-bit Microsoft Windows, this assumption of parity in data type sizes is invalid. Making all data types 64 bits in length would waste space, because most applications do not need the increased size. However, applications do need pointers to 64-bit data, and they need the ability to have 64-bit data types in selected cases. These considerations led the Windows team to select an abstract data model called LLP64 (or P64). In the LLP64 data model, only pointers expand to 64 bits; all other basic data types (integer and long) remain 32 bits in length.

The .NET CLR for 64-bit platforms uses the same LLP64 abstract data model. In .NET there is an integral data type, not widely known, that is specifically designated to hold 'pointer' information: IntPtr whose size is dependent on the platform (e.g., 32-bit or 64-bit) it is running on. Consider the following code snippet:

[C#]
public void SizeOfIntPtr() {
Console.WriteLine( "SizeOf IntPtr is: {0}", IntPtr.Size );
}

When run on a 32-bit platform you will get the following output on the console:

SizeOf IntPtr is: 4

On a 64-bit platform you will get the following output on the console:

SizeOf IntPtr is: 8

Short version: If you're using IntPtrs, you care. If you're aware of what IntPtrs are, you likely know this already.

If you checked the property System.IntPtr.Size while running as x86, it'll be 4. It'll be 8 while under x64. To be clear, if you are running x86 even on an x64 machine, System.IntPtr.Size will be 4. This isn't a way to tell the bitness of your OS, just the bitness of your running CLR process.

Here's a concrete example. It's a pretty specific edgy thing, but a decent example. Here's an app that runs fine on x86.

using System;
using System.Runtime.InteropServices;

namespace TestGetSystemInfo
{
public class WinApi
{
[DllImport("kernel32.dll")]
public static extern void GetSystemInfo([MarshalAs(UnmanagedType.Struct)] ref SYSTEM_INFO lpSystemInfo);

[StructLayout(LayoutKind.Sequential)]
public struct SYSTEM_INFO
{
internal _PROCESSOR_INFO_UNION uProcessorInfo;
public uint dwPageSize;
public IntPtr lpMinimumApplicationAddress;
public int lpMaximumApplicationAddress;
public IntPtr dwActiveProcessorMask;
public uint dwNumberOfProcessors;
public uint dwProcessorType;
public uint dwAllocationGranularity;
public ushort dwProcessorLevel;
public ushort dwProcessorRevision;
}

[StructLayout(LayoutKind.Explicit)]
public struct _PROCESSOR_INFO_UNION
{
[FieldOffset(0)]
internal uint dwOemId;
[FieldOffset(0)]
internal ushort wProcessorArchitecture;
[FieldOffset(2)]
internal ushort wReserved;
}
}

public class Program
{
public static void Main(string[] args)
{
WinApi.SYSTEM_INFO sysinfo = new WinApi.SYSTEM_INFO();
WinApi.GetSystemInfo(ref sysinfo);
Console.WriteLine("dwProcessorType ={0}", sysinfo.dwProcessorType.ToString());
Console.WriteLine("dwPageSize ={0}", sysinfo.dwPageSize.ToString());
Console.WriteLine("lpMaximumApplicationAddress ={0}", sysinfo.lpMaximumApplicationAddress.ToString());
}
}
}

See the mistake? It's not totally obvious. Here's what's printed under x86 (by changing the project properties):

dwProcessorType =586
dwPageSize      =4096
lpMaximumApplicationAddress =2147418111

The bug is subtle because it works under x86. As said in the P/Invoke Wiki:

The use of int will appear to be fine if you only run the code on a 32-bit machine, but will likely cause your application/component to crash as soon as it gets on a 64-bit machine.

In our case, it doesn't crash, but it sure is wrong. Here's what happens under x64 (or AnyCPU and running it on my x64 machine):

dwProcessorType =8664
dwPageSize      =4096
lpMaximumApplicationAddress =-65537

See that lat number? Total crap. I've used an int as a pointer to lpMaximumApplicationAddress rather than an IntPtr. Remember that IntPtr is smart enough to get bigger and point to the right stuff. When I change it from int to IntPtr:

dwProcessorType =8664
dwPageSize      =4096
lpMaximumApplicationAddress =8796092956671

That's better. Remember that IntPtr is platform/processor specific.

You can still use P/Invokes like this and call into unmanaged code if you're on 64-bit or if you're trying to work on both platforms, you just need to be thoughtful about it.

Gotchas: Other Assemblies

You'll also want to think about the assemblies that your application loads. It's possible that when purchasing a vendor's product in binary form or bringing an Open Source project into your project in binary form, that you might consume an x86 compiled .NET assembly. That'll work fine on x86, but break on x64 when your AnyCPU compiled EXE runs as x64 and tries to load an x86 assembly. You'll get a BadImageFormatException as I did in this post.

The MSDN article gets it right when it says:

...it is unrealistic to assume that one can just run 32-bit code in a 64-bit environment and have it run without looking at what you are migrating.

As mentioned earlier, if you have 100% type safe managed code then you really can just copy it to the 64-bit platform and run it successfully under the 64-bit CLR.

But more than likely the managed application will be involved with any or all of the following:

  • Invoking platform APIs via p/invoke
  • Invoking COM objects
  • Making use of unsafe code
  • Using marshaling as a mechanism for sharing information
  • Using serialization as a way of persisting state

Regardless of which of these things your application is doing it is going to be important to do your homework and investigate what your code is doing and what dependencies you have. Once you do this homework you will have to look at your choices to do any or all of the following:

  • Migrate the code with no changes.
  • Make changes to your code to handle 64-bit pointers correctly.
  • Work with other vendors, etc., to provide 64-bit versions of their products.
  • Make changes to your logic to handle marshaling and/or serialization.

There may be cases where you make the decision either not to migrate the managed code to 64-bit, in which case you have the option to mark your assemblies so that the Windows loader can do the right thing at start up. Keep in mind that downstream dependencies have a direct impact on the overall application.

I have found that for smaller apps that don't need the benefits of x64 but need to call into some unmanaged COM components that marking the assemblies as x86 is a reasonable mitigation strategy.  The same rules apply if you're making a WPF app, a Console App or an ASP.NET app. Very likely you'll not have to deal with this stuff if you're staying managed, but I wanted to put it out there in case you bump into it.

Regardless, always test on x86 and x64.

Related Posts

About Scott

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

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

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