Scott Hanselman

Back to Basics: Big O notation issues with older .NET code and improving for loops with LINQ deferred execution

September 15, '11 Comments [58] Posted in Back to Basics | Learning .NET | LINQ
Sponsored By

Earlier today Brad Wilson and I were discussing a G+ post by Jostein KjĂžnigsen where he says, "see if you can spot the O(n^2) bug in this code."

public IEnumerable<Process> GetProcessesForSession(string processName, int sessionId)
{
var processes = Process.GetProcessByName(processName);
var filtered = from p in processes
where p.SessionId == sessionId
select p;
return filtered;
}

This is a pretty straightforward method that calls a .NET BCL (Base Class Library) method and filters the result with LINQ. Of course, when any function calls another one that you can't see inside (which is basically always) you've lost control. We have no idea what's going on in GetProcessesByName.

Let's look at the source to the .NET Framework method in Reflector. Our method calls Process.GetProcessesByName(string).

public static Process[] GetProcessesByName(string processName)
{
return GetProcessesByName(processName, ".");
}

Looks like this one is an overload that passes "." into the next method Process.GetProcessesByName(string, string) where the second parameter is the machineName.

This next one gets all the processes for a machine (in our case, the local machine) then spins through them doing a compare on each one in order to build a result array to return up the chain.

public static Process[] GetProcessesByName(string processName, string machineName)
{
if (processName == null)
{
processName = string.Empty;
}
Process[] processes = GetProcesses(machineName);
ArrayList list = new ArrayList();
for (int i = 0; i < processes.Length; i++)
{
if (string.Equals(processName, processes[i].ProcessName, StringComparison.OrdinalIgnoreCase))
{
list.Add(processes[i]);
}
}
Process[] array = new Process[list.Count];
list.CopyTo(array, 0);
return array;
}

if we look inside GetProcesses(string), it's another loop. This is getting close to where .NET calls Win32 and as these classes are internal there's not much I can do to fix this function other than totally rewrite the internal implementation. However, I think I've illustrated that we've got at least two loops here, and more likely three or four.

public static Process[] GetProcesses(string machineName)
{
bool isRemoteMachine = ProcessManager.IsRemoteMachine(machineName);
ProcessInfo[] processInfos = ProcessManager.GetProcessInfos(machineName);
Process[] processArray = new Process[processInfos.Length];
for (int i = 0; i < processInfos.Length; i++)
{
ProcessInfo processInfo = processInfos[i];
processArray[i] = new Process(machineName, isRemoteMachine, processInfo.processId, processInfo);
}
return processArray;
}

This code is really typical of .NET circa 2002-2003 (not to mention Java, C++ and Pascal). Functions return arrays of stuff and other functions higher up filter and sort.

When using this .NET API and for looping over the results several times, I'm going for(), for(), for() in a chain, like O(4n) here.

Note: To be clear, it can be argued that O(4n) is just O(n), cause it is. Adding a number like I am isn't part of the O notation. I'm just saying we want to avoid O(cn) situations where c is a large enough number to affect perf.

image

Sometimes you'll see nested for()s like this, so O(n^3) here where things get messy fast.

Squares inside squares inside squares representing nested fors

LINQ is more significant than people really realize, I think. When it first came out some folks said "is that all?" I think that's unfortunate. LINQ and the concept of "deferred execution" is just so powerful but I think a number of .NET programmers just haven't taken the time to get their heads around the concept.

Here's a simple example juxtaposing spinning through a list vs. using yield. The array version is doing all the work up front, while the yield version can calculate. Imagine a GetFibonacci() method. A yield version could calculate values "just in time" and yield them, while an array version would have to pre-calculate and pre-allocate.

public void Consumer()
{
foreach (int i in IntegersList()) {
Console.WriteLine(i.ToString());
}

foreach (int i in IntegersYield()) {
Console.WriteLine(i.ToString());
}
}

public IEnumerable<int> IntegersYield()
{
yield return 1;
yield return 2;
yield return 4;
yield return 8;
yield return 16;
yield return 16777216;
}

public IEnumerable<int> IntegersList()
{
return new int[] { 1, 2, 4, 8, 16, 16777216 };
}

Back to our GetProcess example. There's two issues at play here.

First, the underlying implementation where GetProcessesInfos eventually gets called is a bummer but it's that way because of how P/Invoke works and how the underlying Win32 API returns the data we need. It would certainly be nice if the underlying API was more granular. But that's less interesting to me than the larger meta-issue of a having (or in this case, not having) a LINQ-friendly API.

The second and more interesting issue (in my option) is the idea that the 2002-era .NET Base Class Library isn't really setup for LINQ-friendliness. None of the APIs return LINQ-friendly stuff or IEnumerable<anything> so that when you change together filters and filters of filters of arrays you end up with O(cn) issues as opposed to nice deferred LINQ chains.

When you find yourself returning arrays of arrays of arrays of other stuff while looping and filtering and sorting, you'll want to be aware of what's going on and consider that you might be looping inefficiently and it might be time for LINQ and deferred execution.

image

Here's a simple conversion attempt to change the first implementation from this classic "Array/List" style:

ArrayList list = new ArrayList();
for (int i = 0; i < processes.Length; i++)
{
if (string.Equals(processName, processes[i].ProcessName, StringComparison.OrdinalIgnoreCase))
{
list.Add(processes[i]);
}
}
Process[] array = new Process[list.Count];
list.CopyTo(array, 0);
return array;

To this more LINQy way. Note that returning from a LINQ query defers execution as LINQ is chainable. We want to assemble a chain of sorting and filtering operations and execute them ONCE rather than for()ing over many lists many times.

if (processName == null) { processName = string.Empty; }

Process[] processes = Process.GetProcesses(machineName); //stop here...can't go farther?

return from p in processes
where String.Equals(p.ProcessName, processName, StringComparison.OrdinalIgnoreCase)
select p; //the value of the LINQ expression being returned is an IEnumerable<Process> object that uses "yield return" under the hood
Here's the whole thing in a sample program.
static void Main(string[] args)
{
var myList = GetProcessesForSession("chrome.exe", 1);
}

public static IEnumerable<Process> GetProcessesForSession(string processName, int sessionID)
{
//var processes = Process.GetProcessesByName(processName);
var processes = HanselGetProcessesByName(processName); //my LINQy implementation
var filtered = from p in processes
where p.SessionId == sessionID
select p;
return filtered;
}

private static IEnumerable<Process> HanselGetProcessesByName(string processName)
{
return HanselGetProcessesByName(processName, ".");
}

private static IEnumerable<Process> HanselGetProcessesByName(string processName, string machineName)
{
if (processName == null)
{
processName = string.Empty;
}
Process[] processes = Process.GetProcesses(machineName); //can't refactor farther because of internals.

//"the value of the LINQ expression being returned is an IEnumerable<Process> object that uses "yield return" under the hood" (thanks Mehrdad!)

return from p in processes where String.Equals(p.ProcessName == processName, StringComparison.OrdinalIgnoreCase) select p;

/* the stuff above replaces the stuff below */
//ArrayList list = new ArrayList();
//for (int i = 0; i < processes.Length; i++)
//{
// if (string.Equals(processName, processes[i].ProcessName, StringComparison.OrdinalIgnoreCase))
// {
// list.Add(processes[i]);
// }
//}
//Process[] array = new Process[list.Count];
//list.CopyTo(array, 0);
//return array;
}

This is a really interesting topic to me and I'm interested in your opinion as well, Dear Reader. As parts of the .NET Framework are being extended to include support for asynchronous operations, I'm wondering if there are other places in the BCL that should be updated to be more LINQ friendly. Or, perhaps it's not an issue at all.

Your thoughts?

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

Guide to Installing and Booting Windows 8 Developer Preview off a VHD (Virtual Hard Disk)

September 14, '11 Comments [245] Posted in Tools | Win7 | Win8
Sponsored By

New Windows 8 Boot Manager?I've posted before about my intense love for Booting off a VHD (Virtual Hard Disk). It's lovely. Of course, once Hyper-V on the client happens, it will matter less, but for now, here I am, a guy with a perfectly good, working Windows 7 machine who wants to also run the Windows 8 Developer Preview.

I could do a few things to play with Windows 8. I could:

  • Try a virtualization solution, but it might not work, I may not have the drivers I need and it won't be as shiny as running "on the metal."
  • Sacrifice a machine I have lying around. I'll probably do that at some point, but I'd like to try it out on my actual hardware that I use all day long.
  • Swap out my C: drive and use my main machine. I don't have a tool-less case, and I'm also very lazy, so, um, ya.
  • Dual boot. Dual booting may feel ninja but it ALWAYS ends on tears. And sometimes blood.
  • Boot on real hardware from a Virtual Hard Disk.

Booting off a VHD is my current preferred solution for trying crazy stuff because the only speed hit I'll take is on the virtualized hard drive. Everything else is real hardware. I do this all the time with presentation VHDs and one-off daily builds of stuff.

Warranty

Of course, this is just some dude's blog. I puzzled this out and while booting to VHD is supported, messing with your boot manager - especially with Preview (that means, NOT RELEASE QUALITY) Software is a recipe for losing your job and a messy divorce. There's no warranty, express or implied. If you quake in fear from the following instructions, you need to STOP. It may be the case that you are actually a Non-Technical Friend and you don't realize it. Well, someone just told you. Please don't destroy your hard drive. I don't know you and I don't how how you got here. Stop calling. Jimmy no live here, you no call back!

Booting a Windows 8 VHD off a Windows 7 Primary System

These instructions come with the WORKS ON MY MACHINE seal of approvalWhew, now that's out of the way, let's void a few warranties, shall we?

Please note that there are a half dozen ways to do this. You can do it all from the command line using tools like ImageX, DISM, etc, or you can do a lot of it graphically with tools like BellaVista. This is just the way I did it. It's not gospel. I'm sure the folks in the comments will have much nicer ways. Take them all with a nice grain of sea salt. You can also SYSPREP the VHD directly from the ISO's WIM with IMAGEX if you know what that stuff means. It's a little subtle and requires you go get some tools. While my process  is a little baroque, it just needs the one ISO->USB tool.

Step 0 - Have a lot of Disk Space

I like to have a roomy VHD. You can make one that expands or you can make a fixed size. 40 gigs is usually enough, but I like 60 gigs as a nice round number, plus this is the Windows 8 Developer Preview with Developer Tools. If you don't have enough space when an expandable disk "bloats" itself to the fixed size on boot, it'll blue screen, so expandable or not, have the slack space.

Step 1 - Make a USB stick or DVD from the ISO

Go get the Windows 7 USB/DVD download tool and get yourself a USB stick that will hold at LEAST 10 gigs. I used a 16 gig one. Go through the process by pointing at the ISO you downloaded and then preparing your USB key. You can also use the resulting USB key to boot and install Windows 8 from your sacrificial hardware if you like.

Choose ISOChoose Media TypeInsert USB deviceCreating Bootable USB device

Step 2 - Make a Virtual Hard Drive

You can do this later in the process by pressing Shift-F10 while in the Setup Tool, but I like to prep things up front. You can do it from the Disk Management GUI or from DISKPART at the Administrator command line.

Be aware that your VHD needs to be on an internal drive or SATA drive. USB won't work as the drivers are initialized too late in the boot process.

Also, if your machine is BitLockered, your VHD needs to be on a non-BitLockered partition and you need to suspend BitLocker during this process. Also, know your recovery key because I don't know it.

2a. Start up an Administrator Console and run DISKPART. Execute the lines after DISKPART> below, changing them for your own system.

C:\Users\Scott\Desktop>diskpart

Microsoft DiskPart version 6.1.7601
Copyright (C) 1999-2008 Microsoft Corporation.
On computer: HEXPOWER7

DISKPART> create vdisk file=d:\VMs\Win8.vhd type=expandable maximum=60000

100 percent completed

DiskPart successfully created the virtual disk file.

DISKPART> select vdisk file=d:\VMs\Win8.vhd

DiskPart successfully selected the virtual disk file.

DISKPART> attach vdisk

100 percent completed

DiskPart successfully attached the virtual disk file.

DISKPART> create partition primary

DiskPart succeeded in creating the specified partition.

2b. OR do it from the Disk Management GUI:

Create and Attach Virtual Hard Disk

At this point, you've got a VHD that's empty, but ready to have Windows installed to it. The VHD and your system are NOT ready to be booted from. That will come in a minute.

Step 3 - Boot off the Windows 8 USB Key

Now, restart your computer with your new USB key plugged in and startup your BOOT MENU. The hotkey is usually F12 to bring it up. You want to boot off the Windows 8 USB key.

Side Note: Folks with Gigabyte Motherboards. These motherboards are notoriously hard to figure out a USB boot. You need to make sure that you USB key is only plugged into the board directly in the back. Then, don't use the Boot Menu, it never works. Instead, enter the BIOS with the DEL key and manually put your USB Key (it'll be detected by brand, so be prepared to recognize the string) at the top of the Hard Drive boot order.

Boot of your USB key

Step 4 - Attach the VHD while still inside SETUP

Pay attention here. Actually, hell, pay attention to the whole thing, it's subtle.

Start the SETUP process, click Install Not but DO NOT PICK A HARD DRIVE. As shown in this screenshot, instead hit SHIFT-F10 to get to a console. We want to attach our VHD and install to THAT instead.

Shift-F10 from within Windows 8 Setup

In the screenshot above I haven't touched anything, yet.

Below, I've run DISKPART and selected and attached the VHD with these now familiar commands:

DISKPART> select vdisk file=d:\VMs\Win8.vhd
DISKPART> attach vdisk

That will look like this screenshot.

DISKPART commands have been issued, but the drives aren't refreshed yet

Next, ALT-TAB back over to the list of disks and hit REFRESH. You'll see your VHD show up. Mine is the 60 gig one. That's the blank we are going to install to.

Now the 60 gig VHD is visible

Note that installation will warn you that this VHD can't be booted to. Yet. That's cool, go ahead and install to that empty VHD.

photo 4

At some point it'll ask you to restart the computer. The setup process isn't done yet, but go ahead and reboot and remove the USB key.

Your system should reboot and setup will continue, this time off the VHD.

NOTE: I had expected at this point to go and manually create a BCD entry using BCDEDIT.EXE from an Administrator command line as I did in my first post on booting to VHD but it seems that is all done for us now!

The Windows 8 Developer Preview build automatically noticed that I was trying to boot off a VHD and added a Windows Bootloader option and put the description in as "Windows Developer Preview," saving me a half dozen tedious steps. I was very pleasantly surprised! I'd like to hear if you had the same experiences, Dear Reader.

I could tell it was working because my C: drive is a totally silent SSD and my D: drive is spinning rust. When the setup continued I could totally hear the hard drive that holds the VHD spinning. The installation completed happily at this point with me having to manually create an entry with BCDEDIT.

I confirmed it with bcdedit.exe /v while running Windows 8 Developer Preview.

Setup completed, and I rebooted again to make sure I could get back into Windows 7.

In fact, I was shocked to find a completely new bootloader had come into play. I was literally open-mouthed staring at it. It's not text, it's graphical and friendly! It actually and literally "did the right thing." Awesome.

This seems to be the Windows 8 boot manager that you'll see if Windows 8 Developer Preview is the default. Otherwise you'll see the Windows 7 text-mode one first. Very cool. I hope it stays past the Developer Preview.

New Windows 8 Boot Manager?

Here's what you get if you click Other Options.

New Windows 8 Boot Manager?

That's it. To recap:

  1. Make an empty VHD
  2. Attach to the VHD just before installing Windows 8 Developer Preview
  3. Install to the VHD
  4. Rejoice

Hope this works for you, Dear Reader. I'm happily booting Windows 8 Developer Preview to VHD today.

One final disclaimer to be CRYSTAL CLEAR. I puzzled this process out with the same bits given out at http://dev.windows.com. I don't work for the Windows team and I don't know anyone over there. I have no idea if this will work in the future. I only know it worked on my home machine, tonight, once.

Related Links

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

Essential IFTTT (IfThisThenThat) - Programming Workflows for Humans using the Web's Social Glue

September 13, '11 Comments [15] Posted in Blogging | Tools
Sponsored By

There's hundreds of channels to plug into with IFTTTWow, every once in a while an app or website comes along that smacks me in the face. Not just a regular "Hey, that's cool" smack, but more of a "Duh, I should have made that and I would have had a license to print unlimited money and now those guys have already done it and no one will ever know my secret brilliance but they did it and I have no money but I should still tell everyone because they are awesome" smack in the face.

IfThisThenThat should be the next big thing on the social web. It's bloody brilliant.

Here's the dull description I made for nerds:

IFTTT is a cloud-based open-ended web workflow creator building on existing social APIs to create more sophisticated distributed aggregated tasks.

Here's my description for non-technical friend:

IfThisThenThat lets all your online stuff work together to do way more interesting stuff.

There are Channels, like Craigslist, Feeds, Twitter, etc. Those are places that data can come from or go to. There are triggers that a different for each kind of channel. One might be "the temperature goes over 100" or "I tweet something with a @mention" and then you can take action. You can combine them in any way you want.

Here's an example that I'll make right here as I blog. Let's say I want FourSquare checkins to show up in my Google Calendar. Didn't know you wanted to do that? ;) Oh, you do.

It's the magic of OAuth and the proliferation of nice, clean public APIs that makes this possible. As I add the FourSquare Channel to IFTTT, I authorize it to have access to my FourSquare data. I'm not giving them my FourSquare password, though, so I can always revoke access later if I like.

Any new checkin?

I'll select Any new check-in...then I'll select what to do from that same huge list of Channels:

What a huge list of channels!

I'll authorize Google Calendar in the same way, then the REALLY nice part shows up. Templated actions. Yes. I can add text from a dictionary of {{Addins}} (although I think that's a poor name from these {{Keywords}}, but whatever). This way I get complete control of what gets added.

Lots of Action Fields to choose from

I'm sure they'll include more documentation and details on what data is available to be passed between Channels.

Now, bask in the programming of it all. Bam.

If any new checkin on foursquare, add it to Google Calendar

Some examples are amazing in their elegant simplicity. Why is IFTT a great idea? Because it's an ideavirus. It fills a vacuum in your web experience you may not have even known existed. And now that you do, you won't be able to live without it.

If Scott blogs something, send the link to Instapaper to be read later

Hanselman to Instapaper IFTTT recipe

If MSFT stock goes above 30, email me.

Email me if our stock goes up

No, text me!

Text me if our stock goes up

That's better. Now, if I tweet something that is not a @Reply or RT, also post it to my Facebook Page:

Put new tweets on my Facebook Page

If I take any pictures and post them on Instagram, also save a copy in DropBox for me.

Download Instagram photos and save them in DropBox

Hey, you can do stuff with DropBox? Sometimes I find a file while on my phone but I can't download it. If I email you a link, save it to my DropBox, OK?

Save emailed links to DropBox

And, if I favorite something with a link, make sure to send a copy of that link to Instapaper.

Send twitter favorites to Instapaper

I know I tend to be hyperbolic, but this is cool like Yahoo Pipes was cool, except people without a PhD can use it. This is going to be huge.

There's a few interface quirks, like it's unclear how to make a new recipe (you make a task first, then click inspect task (an unlabeled arrow) there's an another unlabeled button that looks like a pharmacist's mortar and pestle (mixing UX metaphors between recipes and prescriptions) and you can create a recipe there.Still, these are nits. The workflows is there and I LOVE the giant iconography, clean typefaces, and above all, the sense of empowerment.

If you are on the interwebs and have a maze of social accounts, you need to seriously spend time time drinking in the wonder and the magic of IFTTT. It's gonna be massive. You heard it here. Now, go.

*hat tip to Rob Conery for turning me onto this!

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

Xbox 360 won't Auto Login to Live - Fixed due to RSTP and Spanning Tree setting in a NetGear Managed GS724TP Switch

September 13, '11 Comments [15] Posted in Bugs | Tools
Sponsored By

Victory pose, Halo StyleYou change something months ago, then noticed an unrelated problem weeks later, then it takes a year to figure out that they were related.

"A butterfly flaps its wings in Brazil and my Xbox stops getting a DHCP lease reliably."

A few months back, as my wife recalls, the Xbox in the living room stopped automatically logging into Xbox live. It was irritating in that "First World Problem" kind of way. We use the Xbox for Netflix and Hulu and she uses Zumba and some other Kinect Fitness stuff so it was a daily reminder to me that "Daddy is a lousy IT guy."

I don't remember when it stopped working other than it did. I set static leases in the main router. Then I set static IP addresses in the router. The ONLY thing that would fix it was to get the Xbox to Refresh/Renew the IP Address (even when it was static!) by going into the System menu of My Xbox, then Network Settings, Configure Network, then Additional Settings, then Restore to Factory Defaults. <sarcasm>Let me say that the wife LOVED this.</sarcasm>

Unrelated to this issue, a few weeks back I lost some save games on my now dead PS3 so tonight I decided to go and backup all my Xbox save games onto a new USB stick. I started with the Xbox in my office, but it wouldn't log in. This set off a spark in my head. I've got literally 34 happy devices with IP Addresses in my house (don't ask) from various vendors but the two Xboxen won't login? OK, that can't be me.

All my nicely labeled network cables in a bundle.At this point, of course, I'm unable to login to Xbox live easily so I get irritated and decide that I will shift gears and finally get this thing fixed.

Even though there's no realistic way that I will bust out the IP Networking textbook from college, hook up WireShark and start sniffing traffic, I like to fool myself into believing that I am that good of a technologist (or that I care THAT much) but the thought brings me comfort.

I start following the wires around from the Xbox to the router, as they are all numbered and labeled in the wiring closet.

Aside: Here's a Bit.ly Bundled Link of the complete "Wiring your house for Gigabit Ethernet 5 PART SERIES" when I wired my house a few years back.

However, I get lost as there's just so darn many wires in the wiring closet. It's getting crowded.

My new wiring closet door, open My new wiring closet door, closed

I realize, however, that the wires aren't going directly into main Router that gives out IP addresses. They are actually plugged into a lovely Netgear 24-port Gigabit GS724TP Managed Switch. Because I wired the whole house for Gigabit and wanted basically hard drive speeds on the wire, I needed a switch with the chutzpah to push a lot of bandwidth, and this switch was the one. All the wires in the house go into it - including the Xboxen. But which ones?

I needed to figure out which cables were the two Xbox cables and plug them directly into the router. I know the MAC addresses of both Xboxes so I logged into the switch's admin console. After failing to remember the password (I set this up 4 years ago, you know) and starting to panic, I tried "password" out of frustration. It worked.

It shouldn't have.

Why was my password a default password?

Something had changed. Oh! I flashed the firmware on this GS724TP switch last year with version 5.0.0.15. It must have reset everything to the defaults.

Now that I was logged in, I checked out the list of all the MAC Addresses and their associated ports.

My two Xboxes were plugged into g14 and g22

OK, so the two consoles are plugged into Ports 14 and 22, so I found them and moved the cables to plug directly into my router, rather than the managed switch.A graphical view of my managed switch.

They worked. Suddenly a year of obnoxious just stopped. Why?

What would cause one device (or class of device) to not get an IP address consistently via DHCP?

There's an article on Windows 2000 called DHCP Renewal Failures on Switched Networks that sounds familiar.

A client connected to an Ethernet switch may not receive a renewed DHCP IP address during startup. Releasing and renewing the IP address manually works.

There's apparently a magical thing called STP (Spanning Tree Protocol) that is very useful but also totally confusing to me. I have read this Wikipedia twice and I have no idea what it does. I'm sure it's lovely, really.

The Spanning Tree Protocol (STP) is a network protocol that ensures a loop-free topology for anybridged Ethernet local area network.

Of COURSE it is.

O_O

That is my blank stare, right there, FYI.

Interestingly, if you Google with Bing or DuckDuckGo for "spanning tree DHCP" you'll get results with words like "failure," "blamed," "fixed, "slowed down," and "acting strange." Ya, spanning tree rocks.

There's also a version of Spanning Tree called RSTP or Rapid Spanning Tree Protocol. All of these protocols are meant to make things work better and recover faster after a network failure and prevent routing loops. However, they appear to cause some trouble in certain clients, like my Xbox and possibly my iPhone and IPad as well.

Here's another explanation:

The problem might be related to what type of network device the DHCP client is connected to. If the client is connected to a switch that performs a spanning tree calculation during port initialization, then the port the client is connected to may not be available for 10-15 seconds. This is long enough to prevent the DHCP client from renewing or obtaining IP addressing information, and thus preventing the TCP/IP stack from initializing.

This is not a problem on all switches that perform spanning tree calculations. Some devices will perform the calculations in the background, and thus the port becomes available immediately. Also, this type of functionality is only required on ports that are connected to other switching devices. Therefore you don't really need it enabled on ports that have clients directly connected to them

A buddy of mine says:

[Spanning Tree is] not bad, but it is there to prevent routing loops. If you are sure you won't ever connect that port to another switch and make a routing loop, an alternative to disabling spanning tree is to enable portfast and I bet that would fix it too. The problem is the normal startup procedure for a port running spanning tree is about 20-25 seconds of watching traffic on the port before enabling. Thus, when you turn your Xbox on, it only waits x seconds for a DHCP reply where x is definitely shorter than the time spanning tree takes to enable the port.

Also, deep in this Australian forum was a comment:

Just to clarify that RSTP has a faster up time than STP. I don't think this is going to directly cause the "limited or no connectivity" issue.

However for some devices you need to have the port active right away. On a cisco switch this is called portfast and it skips the process of checking for loops(RSTP, STP). On some devices (xbox 360) this can cause DHCP issues when they're first turned on.

PCs are generally immune to this as they'll poll for a DHCP service several times while your media device might only try once.

And thus, this is how I fixed the issue with my Xboxes not logging into Live on the first try. I'd flashed a network switch without even thinking and it turned Rapid Spanning Tree Protocol on, which Xboxes (and some other network devices) don't like.

My solution, check the router or switch and turn RSTP or "Spanning Tree" off.

As an aside, it turns out that I could have even turned off RSTP at the port level on this Netgear GS725TP switch. Amazing hardware, this switch. Love it. Except for when it reset settings to defaults and irritated me for a year.

Related Links

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

NuGet Package of the Week #10 - New Mobile View Engines for ASP.NET MVC 3, spec-compatible with ASP.NET MVC 4

September 5, '11 Comments [18] Posted in ASP.NET | ASP.NET MVC | Mobile | NuGet | NuGetPOW
Sponsored By

Desktop ASP.NET MVC Application next to the same application in a mobile browserI did some basic mobile view engine work for ASP.NET MVC for Mix in 2009 and then created what I thought was a better ASP.NET MVC Mobile ViewEngine in 2010. Unfortunately, the second one (the "better" one) had a caching bug that only showed itself in Release mode. This last month, Jon, John, Peter and I updated NerdDinner to MVC 3 with Razor and a pile of other new features. One of those new features was jQuery Mobile support and that meant we need to fix this bad Mobile View Engine. Additionally, ASP.NET MVC 4 will include actual supported Mobile Views support, so the pressure was on.

However, we wanted to make sure any new MVC 3 Mobile View sample was mostly compatible with whatever scheme ASP.NET MVC 4 uses. The original folder layout for my proposed ViewEngine was by folder but the final design was to use file names. That means instead of ~/Views/Home/Mobile/Index.cshtml, you'd have ~/Views/Home/Index.Mobile.cshtml. Of course, you can change this if you really want to yourself, but that's the default.

Alternate Views shown in Solution Explorer in subfolders Alternate Views shown in Solution Explorer separated by filename differences, not folders

Peter Mourfield jumped in and did the updated Mobile View Engines and we've put them on NuGet for you, Dear Reader.

Remember, these are for ASP.NET MVC 3. You don't need them when ASP.NET MVC 4 comes out, and the general idea will be that you will remove the Razor (or WebForms) ViewEngine and replace it with the mobile version which is a superset of functionality.

ViewEngines.Engines.Remove(ViewEngines.Engines.OfType<RazorViewEngine>().First());
ViewEngines.Engines.Add(new MobileCapableRazorViewEngine());
ViewEngines.Engines.Remove(ViewEngines.Engines.OfType<WebFormViewEngine>().First());
ViewEngines.Engines.Add(new MobileCapableWebFormViewEngine());

You can do this bit of work in Application_Start, or with the Web Activator like the MobileViewEngines.Razor.Samples does. The sample NuGet package includes both VB and C#, so you'll want to delete the one you won't use. You only need to use the ViewEngine you need, so if you aren't using WebForms, don't bother with those lines.

The whole ViewEngine that Peter made is only 81 lines of code so you can certainly change it to your taste. Peter and I put the source on BitBucket for changes, forks and fixes.

image

Just add the word Mobile in your views, like Index.Mobile.cshtml or Details.Mobile.aspx and those will be used when a mobile browser is detected. The detection  is using the standard Browser.IsMobileDevice call from ASP.NET, so consider using a browser database like http://51degrees.mobi (also on CodePlex, and NuGet).

Remember, this is a clean-room implementation (not derived from ASP.NET MVC  4) that has just basic mobile view overrides. I'm glad it doesn't have the release mode bug like my previous ones did, and we are using this implementation live on http://nerddinner.com. Modify the source if you need advanced support for multiple mobile views (like iPhone, BlackBerry, etc) other than just "mobile" like this one does. There are features that this basic ViewEngine doesn't have that a more sophisticated solution like ASP.NET MVC 4's or other folks' implementations could have like:

  • Browser Overrides: Forcing or "opting out" of mobile and using desktop
  • Device-specific custom layouts

Still, we've found it to be simple and useful on NerdDinner and we hope it's useful to you.

Related Links

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.