Friday, July 23, 2010

Session State not working even though you have enabled it?!

This was a doozie... I was working on a local dev box running Windows Vista and .NET 2.0. I pulled down another developer's web project that uses Session State variables, and when I went to test it, I received this error:

"System.Web.HttpException: Session state can only be used when enableSessionState is set to true, either in a configuration file or in the Page directive..."
I did some sleuthing, and find different recommendations:
  1. Add to your web.config file, within the area.
  2. Add to the same area.
  3. Make sure is in the httpModules area of your root level web.config file (some people said machine.config, not sure which, but I tried both).
  4. Add EnableSessionState="true" to the .aspx @Page directive.
Well, I tried all of these. Yet I still received this error. I opened up IIS Manager and looked at the root level of the site. There's even a configuration panel for "Session State," and "InProc" was already selected. EVERYTHING was turned on, why wasn't it working???

I just figured it out, although I have no idea how or why it was required:
  • In IIS Manager (in IIS7), go to the top level of the website in question.
  • Instead of clicking on the Session State panel, double-click the "Modules" area.
  • Scan that list and see if you have a module for Session State configured (I did not).
  • If not, click the Add Managed Module... button.
  • Type "Session" in the first box (no quotes).
  • In the second box, type "System.Web.SessionState.SessionStateModule" (no quotes)
  • Click the checkbox "invoke only requests to asp.net" (at least, that's what I did)
Now try your application again. If you're lucky like me, it just worked!

Saturday, May 1, 2010

Information on 3G iPad GPS and International Roaming

UPDATE: I am back from my trip in Italy, and everything worked great. I used only about 100MB of 3G data on the iPad, although keep in mind I was also using an iPhone some of the time. It worked perfectly for our trip. Being able to consult maps, the web, and related information was very handy.

I can also highly recommend the TomTom for Italy iPhone app (with the hardware phone holder that amplifies the GPS and charges the phone). We drove all over Italy using this device, and rarely made mistakes in getting to our destinations!




First, let's talk GPS in the iPad

The GPS in the iPad works with or without a 3G plan.

It's called "Assisted GPS," but don't let the name fool you, it's true GPS. The "assist" you get from the cell towers is that you get an immediate approximate location, and more importantly, the tower information tells the GPS chip in the iPad which GPS satellites to lock onto. This speeds up the process of acquiring a true GPS lock.

However, if you are in an area with zero 3G cell coverage, your iPad will still obtain a GPS lock, it's just going to be a bit slower initially.

In addition, if you're near any WiFi routers, the iPad will acquire an approximate location based on data from services like Skyhook, automatically. (Assuming you're able to connect to at least one of those WiFi routers to obtain an internet connection that the iPad can use to query the remote Skyhook data!)

Based on my testing yesterday, the GPS in my iPad (without any 3G plan enabled, mind you) was following me pretty damn precisely. I walked the sidewalk around my office complex, with the map program open, and it was dead accurate and very smooth updating, more so than my iPhone.

Of course, if you haven't enabled the 3G plan, and if you have no WiFi connection, you won't be able to use many GPS programs anyway, since they typically are downloading maps and other stuff from the net.

3G Data Plans

Most people know AT&T is offering two plans, $15 for 250MB and $30 for unlimited. If you get low on the 250MB plan, they provide warnings so you'll know. You then have the option of paying another $15 for another 250MB, or paying $30 for 30 days of unlimited, from that point in time. (No, you can't just pay an extra $15 to 'upgrade' to unlimited!) These plans auto-renew, until you cancel, but there's no lock in or contract.

AT&T also has international data roaming plans. These are priced the same as adding data roaming on iPhone or any other device, with several tiers, and the top end capping out at $200 for 200MB of data (in a 30-day window, just like the domestic plans). Unlike the iPhone plans, there are no overages or overage fees -- you simply run out of your allotment, and to continue, you must add another international roaming plan. (Keep in mind you'll need WiFi access to enable this plan, since your 3G coverage will have run out!)

Contrast this with the iPhone roaming plans, where if you go over, you're not warned initially, and you're paying $5 per MB over!

The international plans are a one-time fee, they do not auto-renew. You can also pick which day they start on, up to a year from your purchase date. So you can time it perfectly for your departure date.

Note: You must have an existing 3G data plan on the iPad to add international roaming.

It is simple to add both the 3G data plan and the international data add-on directly from the iPad settings app, look for "Cellular Data."

$200! $200! Anything Cheaper?

The only thing that would be cheaper is if you were to just get a pre-paid micro-sim card in the country you're traveling to. Instead of the high rates you're paying AT&T, you'll be paying a fraction of that. The problem is the micro-sim format is still really new (as of May 2010), and you may have trouble locating a provider in your travel destination that carries them. But the iPad is unlocked and it will work if you can find one. (Some people suggest cutting down a regular SIM card to fit the micro-sim slot, which may work.)

Personally, I did not want to wander around on my vacation looking for a foreign cell provider with a micro-sim, so I bit the bullet and ordered an international plan from AT&T. I'll be traveling May 7 - 23 in Italy, and will post an update when I return if I have any trouble. (I'm traveling with an iPhone 3GS with 100MB data plan, the iPad with 200MB, and a blackberry with unlimited email data... yeah, work is fun!)

Tuesday, March 2, 2010

MSDeploy Bug: Archives Directories Referenced in HTTP Redirect Virtual Directories


Alternate title: MSDeploy Recursively Copying Data Files During Sync (Infinite Loop)


We were testing msdeploy recently to migrate an IIS 6 web server to IIS 7, and discovered something that took a while to track down.

When you run the -verb:sync option (aka -verb:migrate), and you are trying to archive one or more of your IIS 6 websites to an archive directory, you may discover that msdeploy goes into an infinite loop recursively copying directories into each other. In our case, it eventually bombed, but only after creating a directory structure so deep that Windows itself could not delete it.

(Sidebar: to fix that issue, we had to write a little script that would dig down dozens of directories at a time, then move the remaining directory tree to the root level, then continue digging another dozen directories deep, move the next tree to the root level, and so on until it finished. Then we were able to delete each of these dozen-directory-deep trees from the root level! This idea was adapted from Microsoft's article.)
Anyway, back to the problem at hand...

It turns out, long-forgotten, were virtual directories in IIS that were created for the purpose of creating HTTP Redirects. IIS 6 forces you to first create a virtual directory, give it a real directory that it points to, and only THEN can you change its properties so that it acts like an HTTP Redirect to another resource entirely.

You may not have realized, but IIS 6 is still storing your original directory location in the metainfo for that virtual directory. If you, like someone here (OK, me), just filled in "D:\" or some other root level directory temporarily, then msdeploy will try to archive that directory when it's doing its sync function. YES, I realized long ago that it wasn't wise to use a root level directory, for security reasons alone, but it only takes one of these slipping past you to cause this problem.....

And if you, like us, decided to tell msdeploy to archive to the same drive that you referenced in that virtual directory, you will discover that msdeploy will happily attempt to recursively archive your folder, archive your folder, archive your folder, archive your folder, archive your folder, archive your folder..........

I feel this is a bug in msdeploy. Why does it need to archive these 'old' directory references in virtual directories that are being used as redirects?

The fix is to go back through all of your HTTP Redirect virtual directories, switch the radio button over to the primary directory setting, change the directory to something harmless (e.g. c:\temp\my-special-directory), and then change the setting back to your HTTP Redirect. I actually did this editing the MetaBase.xml file directly, but that's outside the scope of this article!

Good luck and back up your MetaBase and IIS sites before screwing with this...

Thursday, February 25, 2010

iPhone ActiveSync on Gmail, with Custom From: Address

I finally figured out how to get my iPhone to use ActiveSync for Gmail, while still allowing me to use a custom reply-to address. Your mileage may vary, but here you go.

NOTE: This procedure worked for me, but may not work for you. Backup your iPhone before trying it!

(Outside the scope of this document, you must already have 2 accounts setup on your iPhone: (1) An IMAP account that is downloading email from gmail.com, and (2) an ActiveSync account that you're using to sync up Contacts and Calendars. And you must have your vanity reply-to address already registered within your Gmail account. For the purpose of this article, I'll say my vanity address is me@mydomain.com.)

So, with the above as our starting point.

  1. Go into iPhone Settings, then click "Mail/Contacts/Calendars."

  2. Click on the "Fetch New Data" option.

  3. Scroll down and click on "Advanced."

  4. Set your IMAP account to "Manual."

  5. Set your ActiveSync account to "Push."

  6. Back out 2 screens so that you're on the "Mail/Contacts/Calendars" settings area.

  7. Click on your ActiveSync account, and then turn Mail ON. (Calendar and Contacts are probably already ON.)

  8. Click the "Account Info" button at the top.

  9. Change the "Email" field to be your vanity reply-to address, e.g. me@mydomain.com.

  10. Back out 2 screens, to the "Mail/Contacts/Calendars" screen.

  11. Click on your IMAP account.

  12. Underneath "IMAP Account Information," there should be a field named "Address." Edit that field to use that same vanity address, e.g. me@mydomain.com.

  13. Below that are 3 fields for "Incoming Mail Server." Erase the text in each of those 3 fields. (We do this so that your phone won't ever try downloading mail via IMAP.)

  14. Now back out to the main screen (the home screen).

  15. Start the Mail app, and once you're in the inbox, click the back button, and then once more until you see your 2 accounts shown.

  16. Click the ActiveSync account, and then click "Inbox."
Now you should be in your ActiveSync inbox, and it will download your email.

If you start a new message, or reply to an existing message, it should use your me@mydomain.com vanity address as the From: address. The gmail.com address is still exposed in the "hidden" headers, like Return-Path, but there's not much you can do about that.

NOTE: This worked for me, but may not work for you. Backup your iPhone before trying!

Friday, February 5, 2010

iPhone Video Orientation (Tallscreen/Vertical Video)

We have been working with Encoding.com recently to get "tallscreen" (vertically-oriented viewing mode) support working on incoming iPhone videos. Encoding.com now finally supports these videos, but you will need to recognize things correctly on your end, or you won't like the results.

In short, you need to recognize that the video is vertically oriented, and if it is, you want to swap your output WIDTH and HEIGHT numbers in your encoding.com request. If you do that, encoding.com will do the rest.

To understand why, here is what I've learned about how iPhone video works...

The iPhone records video to disk the same way each time: as if you've turned the phone 90 degrees to the left, and put it in landscape mode. This is considered "0 degrees," and the video is recorded in this landscape mode, at 640 x 480 (4:3), no matter which way you have the phone oriented.

If you turn the phone to any of the other positions, it doesn't change the way it writes the bits on disk, it just records the "Rotation" flag according to the orientation the phone was in when the recording process started.

  • 0 degrees: landscape, turned on the phone's left side
  • 90 degrees: vertical/normal, with home button on bottom
  • 180 degrees: landscape, but turned on the phone's right side instead of left
  • 270 degrees: vertical/upside-down, with home button on top
All of Apple's recent video players (i.e. Quicktime) are aware of this rotation flag, and so you might never realize your video is being recorded the way it is until you try to view it on a player that doesn't support it, or encode the video with an encoder that doesn't recognize it. In one of these players or encoders, the video would look to be turned on it's side or upside down.

Encoding.com now supports this flag, and I have confirmed it recognizes it correctly in all 4 positions.

So the only thing you need to do is to recognize that if the rotation is 90 or 270, you need to flip the Width and Height numbers, that's it. Encoding.com does the rest.

So, for example, a user uploads a vertically-oriented video to you (either 90 or 270 degree rotation), recorded at the usual iPhone 640 x 480. You see that it's rotated, and your encoding.com request specifies that the output you want is now flipped, 480 x 640 (W x H). Encoding.com gets your source video, sees the rotation flag, and flips it properly while encoding -- and since you specified the proper output size, the video comes out as expected!

(If the video rotation is 180 degrees, you don't need to do anything. The W x H does not change, since it's still in landscape, and encoding.com will correctly flip the video 180 degrees when encoding it.)

Currently we are using the open source "MediaInfo" program to easily obtain information about an incoming video, and to find whether or not the "Rotation" flag has been set, and to what.

Monday, August 10, 2009

Microsoft Junk Mail Reporting Program (JMRP) Sucks!

Anyone else frustrated with Microsoft's Junk Mail Reporting Program (JMRP)?

It's a feedback loop that lets legitimate email senders receive junk mail reports from hotmail.com/msn.com/live.com email users.

Well, that's how it's supposed to work.

We have been on this feedback loop for years now, and our company sends only legitimate email that our subscribers specifically request. As any mail sender knows, you can't avoid a few people each day that hit the "Report Spam" button for your email rather than "Delete." (Usually it's an accident since they put the buttons so close together, and don't tell them what a negative impact the Report Spam button has in the first place.)

So this JMRP program is supposed to solve this. You get on this program, and Microsoft will forward any spam reports to you for your email, and you can unsubscribe the user. Perfect!

Unfortunately, Microsoft routinely fails to send all the reports to us. If someone is reporting us as spam, and we aren't alerted to this, how can we unsubscribe the user? Now we're being punished for the spam report that we seem to be ignoring, because we're not getting the report in the first place!

We have confirmed this is happening by reviewing example reports Microsoft shows for us in their web interface (called SNDS -- "Smart" Network Data Services). We routinely see junk reports for emails that were never sent to us. We've even researched our mail server logs to make sure that no attempt from Microsoft was accidentally rejected or not processed. Nope. Everything is fine on our end.

Within a few days, our 'level' on JMRP (in the "SNDS" interface) shows as yellow or even red, even though our email routines have not changed one iota. This must be due to these missing reports.

It gets worse. When we've tried to explain what's happening, no one at JMRP gets it. Either they get confused and think we aren't on the feedback loop yet, and send us to the 30 part form that subscribes you to the program, or they simply do not get it, and I have to explain the problem again. And again. And again.

This time I thought it was different -- we actually got someone to repeat back the problem to us as if they understood it (after only 5 or 6 emails back and forth). AWESOME right? Nope. The next email we received was someone saying now they understand the problem and are doing research to help us fix it. What questions do they ask us to fill out (again)? Oh, the same 30 part questionnaire you fill out when you join the JMRP program.... nothing at all that would help them actually figure out what is wrong on their end.

I lost it at this point and berated the support drone for failing to grasp the problem. What do I get back? A response from a different drone saying, "I'm sorry you're [insert totally incorrect description of our problem here]." This is after there must be a paper trail a mile long of me repeatedly explaining the problem in very simple terms:

WE ARE ON JMRP ALREADY.
YOU ARE NOT SENDING US ALL THE JUNK REPORTS.

It never reaches anyone with a clue. And if it does, that person is never to be heard from again.

So we are stuck with thousands of our subscribers not receiving email from us that they want.

I understand fighting spam is a top priority for Microsoft, but the system they've devised is routinely blocking non-spam email from a company like ours, that has been sending only legitimate email for 15 years now, a company that is jumping through every single hoop they hold in front of us. What good is this system?

If you have any complaints about JMRP or the SNDS system, please post them as comments here. If Microsoft wants to contact me, please leave a comment and I will contact you in whatever way you wish.

Right now, JMRP is a big fat failure. It's worse than a failure, people actually think it's working, and it's seriously damaging the ability for legitimate senders to get through.

P.S. My favorite part of JMRP is the SNDS web interface. Check out the unreadable header, complete with nearly invisible white navigation links laid over a light blue background. You can just about make out "View Data," but I defy you to read the rest of the links:

Tuesday, August 4, 2009

Configuring a Wireless Bridge Using Two Apple Airport Expresses

Here's the scenario: You want to setup a wireless network, and you also need to connect a non-WiFi network device to your new wireless network. E.g. you're setting up a wireless network at work, and you've got a network printer that only has ethernet, no WiFi, that you want to connect to your network. For the purpose of this exercise, we'll use this scenario to explain the setup.

Step 1. Buy Two Airport Expresses. I recommend these because they are easy to setup, they work great, and the design is ingenious (it's about the size of your standard wall plug). If you don't have any ethernet cable, you'll need to buy at least one, maybe two ethernet cables. One will go from the cable/dsl modem to an airport express, the other will connect your printer to the second airport.

Optionally: You may want to buy the more expensive Airport Extremes instead of the Expresses, in the event that you want more ethernet ports available. But you can always add on a cheap switch later if you need more ports on an Airport Express.

Step 2. Unwrap both devices, and mark them to keep them straight. Put a sticker or mark one with a Sharpie so you can tell them apart. One of these will be the heart of your wifi network, the one every device connects to -- we'll call this Airport A. It will be connected to your cable/dsl modem.

The other will be connected to your non-Wifi device (e.g. your printer), allowing it to connect to Airport A and the Internet... we'll call this one Airport B.

Step 3. Plug Airport A into power. Plug it into the wall near your cable/dsl modem. You'll see an amber light blinking on the Airport, this is normal.

Step 4. Insert the Airport Express setup CD into your computer, and run the software. After a minute you should see an Airport available named "Base Station xxxxxx," where xxxxxx will be a series of letters and numbers. Select this, and press the Continue button to configure it.

Step 5. Configure Airport A.

You'll have a few options to fill in now:

  • AirPort Express Name: You can name it anything you want, such as Airport A.
  • AirPort Express Password: This is a password on the device you'll need whenever you want to re-configure the Airport Express. You will not be sharing this with others.
  • Select what you want to do with Airport Express: Choose "I want to create a new wireless network."
Continue to the next screen:
  • Wireless Network Name: This is different from above. Other people will use this to identify your WiFi network if you want them to connect to it. (And, hey, maybe even when you don't want them to connect to it?!)
  • WPA/WPA2 Personal: Choose this option and enter a password you will be comfortable giving to your guests to use your WiFi network. For strong security, this should be different from the password you chose on the previous screen. You wouldn't want your guests to be able to re-configure your Airport Express.
Continue to the next screen:
  • Select how you connect to the Internet. For this example, you'll choose the first option, "I use a DSL or cable modem with a static IP address or DHCP."
Continue past the next screen, "Using DHCP," is the normal option for most people. Your ISP will send information to the Airport Express to connect it to the internet using this setting.

Continue to the next screen and after reviewing your choices, press "Update."

The on-screen options should prompt you to finish and allow Airport A to restart if necessary. You should also restart your cable/dsl modem at this time.

You can now connect to the internet by connecting your computers to Airport A.

Step 6. Plug Airport B into power. Plug it into the wall near your printer. You'll see an amber light blinking the Airport, this is normal.

Step 7. Restart the Airport Utility software. If you don't see the new "Base Station xxxxxx" appear, go ahead and restart the Airport Utility software. Within a minute you should see it appear on the left side. Select it and continue on to configure it.

Step 8. Configure Airport B.

You'll have a few options to fill in now:
  • AirPort Express Name: You can name it anything you want, such as Airport B.
  • AirPort Express Password: This is a password on the device you'll need whenever you want to re-configure the Airport Express. You will not be sharing this with others. You should choose the same password as you chose above (not your WiFi password, but the first password you chose for the device configuration), just to keep them straight.
  • Select what you want to do with Airport Express: Choose "I want AirPort Express to join my current network."
Continue to the next screen:

  • Select what you want to do with AirPort Express: Choose "I want Airport Express to wirelessly join my current network."
Continue to the next screen:
  • Wireless Network Name: Enter the Wireless Network name you chose for Airport A here. This is the WiFi network that Airport B will connect to, wirelessly.
  • Wireless Security: Choose "WPA/WPA2 Personal."
  • Wireless Password: Enter the same Wireless Network password you chose above for Airport A's WiFi network. (The password you established to give out to your guests.)
Continue to the next screen and after reviewing your choices, press "Update."

The on-screen options should prompt you to finish and allow Airport A to restart if necessary.

Step 9. Connect Airport B to your printer with an ethernet cable. Follow your printer's instructions for setting up your network connectivity on the printer. When prompted, select "DHCP" and not static IP address.

Step 10. You're done.