net, gists, aspnet, csharp comments edit

If you’ve worked with Windows Identity Foundation, you’ll find it very nearly mandates that you implement a passive security token service using classic ASP.NET web forms rather than MVC. It doesn’t lend itself well to testability, and in some cases it writes content directly to the response stream without you being able to govern when/how that happens.

All is not lost, though. Here are a couple of helpers and tips when working with Windows Identity Foundation in ASP.NET MVC to create a passive STS.

Programming Windows Identity FoundationFirst, drop what you’re doing and go buy a copy ofProgramming Windows Identity Foundation by Vittorio Bertocci. The documentation on WIF is surprisingly thin and this book is like the lost set of docs that makes everything clear. Will it directly help you specifically with ASP.NET MVC and WIF? No, but it will help you to understand what is going on with WIF so you know where you may need to insert yourself. It’ll also explain how things are supposed to work, so when you’re setting it up in MVC you can tell if things are going right or not.

Reflectoris your friend. I am not condoning that you copy/paste anything out of the WIF assemblies, but using Reflector to figure out what it’s doing is key.

For example, in WIF samples and in the WIF STS template you’ll see a call to FederatedPassiveSecurityTokenServiceOperations.ProcessSignInRequest followed closely by FederatedPassiveSecurityTokenServiceOperations.ProcessSignInResponse. The ProcessSignInResponse method takes in an HttpResponse rather than an HttpResponseBase, which removes you from the ability in your MVC controller to use the System.Web abstractions for testability. However, if you look at what ProcessSignInResponse is actually doing, it’s just taking the SignInResponseMessage that comes from ProcessSignInRequest and then it’s writing it out to the response stream. You can do the same thing yourself in your controller using the controller’s Response property and HttpResponseBase, allowing you to break that tie to the concrete System.Web classes.

Make use of model binding. In the STS template, the Default.aspx page they provide has a big if/then block that switches on query string parameter values to determine which WS-Federation action the incoming message has. Rather than that, wouldn’t it be better to have a controller action that looks like this?

// This ostensibly replaces Default.aspx in the STS template
public class DefaultController : Controller
{
  public ActionResult Index(WSFederationMessage message)
  {
    if(message.Action == WSFederationConstants.Actions.SignIn)
    {
      // Do your signin processing
    }
    // ...and so on; alternatively you could switch on message.Action.
  }
}

That, of course, assumes you have a model binder that will look at the incoming query string and parse a WSFederationMessage out of it. That’s not too hard to do, and we can pretty easily add support for the derived WSFederationMessage types to it, too, like SignInRequestMessage.

using System;
using System.Web.Mvc;
using Microsoft.IdentityModel.Protocols.WSFederation;

namespace MyNamespace.ModelBinders
{
  public class WSFederationMessageBinder : IModelBinder
  {
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
      if (controllerContext == null)
      {
        throw new ArgumentNullException("controllerContext");
      }
      if (bindingContext == null)
      {
        throw new ArgumentNullException("bindingContext");
      }

      try
      {
        var message = WSFederationMessage.CreateFromUri(controllerContext.HttpContext.Request.Url);
        if (!bindingContext.ModelType.IsAssignableFrom(message.GetType()))
        {
          throw new WSFederationMessageException();
        }
        return message;
      }
      catch (WSFederationMessageException ex)
      {
        bindingContext.ModelState.AddModelError("", ex);
        return null;
      }
    }
  }
}

You can then register that model binder for the various WS-Federation message types at app startup:

var binder = new WSFederationMessageBinder();
ModelBinders.Binders[typeof(WSFederationMessage)] = binder;
ModelBinders.Binders[typeof(AttributeRequestMessage)] = binder;
ModelBinders.Binders[typeof(PseudonymRequestMessage)] = binder;
ModelBinders.Binders[typeof(SignInRequestMessage)] = binder;
ModelBinders.Binders[typeof(SignOutRequestMessage)] = binder;
ModelBinders.Binders[typeof(SignOutCleanupRequestMessage)] = binder;

Now you can actually do the controller action the way you’d like, with a strongly-typed WSFederationMessage parameter and it will work.

Of course, if you look at the Default.aspx in the WIF STS template, it throws an UnauthorizedAccessException if a WS-Federation message comes in and isn’t a sign-in or sign-out request. You can do the same thing declaratively in MVC using an authorization filter. That would change your controller action to look more like this:

[RequireWSFederationMessage(AllowedActions = WSFederationMessageActions.SignIn | WSFederationMessageActions.SignOut)]
public ActionResult Index(WSFederationMessage message)
{
  // ...handle the message...
}

Something like that, where you could allow specific message actions to pass through, otherwise the user is seen as “unauthorized.”

Create a filter attribute for ensuring only proper message types are allowed through. First you’ll need that WSFederationMessageActions enumeration so you can specify what’s allowed and what’s not.

using System;

namespace MyNamespace.Filters
{
  [Flags]
  public enum WSFederationMessageActions
  {
    All = WSFederationMessageActions.Attribute | WSFederationMessageActions.Pseudonym | WSFederationMessageActions.SignIn | WSFederationMessageActions.SignOut | WSFederationMessageActions.SignOutCleanup,
    Attribute = 1,
    SignIn = 4,
    SignOut = 8,
    SignOutCleanup = 16
  }
}

Yes, I could have just calculated the result of the “or” operation for the “All” but this way if any values change, I don’t need to mess with “All.” Do it your way if you’re not cool with this.

Next, the filter attribute:

using System;
using System.Collections.Generic;
using System.Web.Mvc;
using Microsoft.IdentityModel.Protocols.WSFederation;

namespace MyNamespace.Filters
{
  [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
  public sealed class RequireWSFederationMessageAttribute : FilterAttribute, IAuthorizationFilter
  {
    // Lookup table for converting string actions to the associated flag
    private static readonly Dictionary<string, WSFederationMessageActions> _actionLookup = new Dictionary<string, WSFederationMessageActions>()
    {
      { WSFederationConstants.Actions.Attribute, WSFederationMessageActions.Attribute },
      { WSFederationConstants.Actions.Pseudonym, WSFederationMessageActions.Pseudonym },
      { WSFederationConstants.Actions.SignIn, WSFederationMessageActions.SignIn },
      { WSFederationConstants.Actions.SignOut, WSFederationMessageActions.SignOut },
      { WSFederationConstants.Actions.SignOutCleanup, WSFederationMessageActions.SignOutCleanup },
    };


    public WSFederationMessageActions AllowedActions { get; set; }

    private object _typeId = new object();
    public override object TypeId
    {
      get
      {
        return this._typeId;
      }
    }

    public RequireWSFederationMessageAttribute()
    {
      // Default to allowing all actions.
      this.AllowedActions = WSFederationMessageActions.All;
    }

    public bool IsAllowed(string action)
    {
      if (
        String.IsNullOrWhiteSpace(action) ||
        !_actionLookup.ContainsKey(action)
      )
      {
        return false;
      }
      var enumAction = _actionLookup[action];
      return (this.AllowedActions & enumAction) == enumAction;
    }

    public void OnAuthorization(AuthorizationContext filterContext)
    {
      if (filterContext == null)
      {
        throw new ArgumentNullException("filterContext");
      }

      WSFederationMessage message = null;
      // If you can't parse out a message or if the parsed message
      // isn't an allowed action, deny the request.
      if (
        !WSFederationMessage.TryCreateFromUri(filterContext.HttpContext.Request.Url, out message) ||
        !this.IsAllowed(message.Action)
        )
      {
        filterContext.Result = new HttpUnauthorizedResult();
        return;
      }
    }
  }
}

Now you have a filter attribute that will check to make sure the incoming message is of an expected type and will deny access if it’s not.

Hopefully some of this will help you get working with WIF in ASP.NET MVC. It’d have been nice if MVC had been considered in the initial rollout of WIF, but no such luck. I don’t even see a Connect page for accepting suggestions. Fingers crossed for the next release…!

General Ramblings comments edit

On a somewhat daily basis, I have this weird sort of “aha!” moment where I realize, again, that I’m a father, and that’s really weird to me. I picture fathers as guys that are older than I am, which is to say, that “being a father” somehow equates to “higher age” even though that’s obviously not remotely true. Of course, I also don’t feel like I’m really an adult yet, either, even being in my 30’s, given concerns about getting enough time to play Rock Band overtake my desire to, say, watch the evening news. I own a house, too, and when I think about that in concrete terms it weirds me out as well.

I also have a difficult time equating “baby” and “human,” like Phoenix is some sort of small animal that needs to be taken care of (like a house cat). I find myself talking to her the way I talk to the cats, sitting her on the couch and saying, “See, now you’re on the human chair!” when, duh, she is a human so of course she’s on the human chair. I think that will probably change when she has, you know, motor control and some mechanism of communication beyond “scream.”

I don’t think Jenn has this sort of cognitive dissonance issue over feeling like she’s-a-mom-but-she’s-not-a-mom. I think it’s sort of clicked for her. I suppose I’ll get there eventually. For now, it’s just still… surreal.

General Ramblings comments edit

I find that I’m blogging less due to services like Twitter that let me blurt out truncated, incomplete thoughts and flush them from my mind without fully forming them. That, plus the breakneck pace work has taken since I returned from paternity leave, plus general malaise (in some cases) has yielded a bit of a blog drought. I won’t apologize for not blogging because I hate that. I just haven’t done it, and that’s that.

I do have some smaller, not fully-formed thoughts that I haven’t blasted out in other forms, or maybe have tweeted about and dropped, so I figured I’d flesh some of those out here. Maybe relieve a bit of the psychic weight of that “to-do” list, as it were.

I sent out a request (over various media) for suggestions for over-the-ear headphones that don’t pinch your ears. I got a few good suggestions, but I should have explained requirements. Of course, that’s hard to do over Twitter in 140 characters, so:

  • I’ll be using them (and leaving them) at work, so a $300 pair of headphone is out. People can’t keep their hands off my stuff. I just found one of my action figures on another guy’s desk last week. I don’t need some spendy headphones getting “borrowed.”
  • I’ll mostly be listening to Pandora or other fairly compressed music sources. They don’t have to be reference quality.

Sony MDR-XD200
HeadphonesI ended up getting a cheap pair of Sony MDR-XD200 headphones. $22 at Amazon at the time of this writing. I’m wearing them now, as I write this, and they seem reasonably comfortable. The bass is a little light in them, which, I’m sure, could be rectified by purchasing a more expensive, higher quality set of headphones. For work, for now, these will do.

 

If you find you’re being asked to do something that has no logic behind it no matter which way you slice it, it’s probably politically motivated. Think about it.

 

My wife, Jenn, who is awesome, proved she understands comics. I have some sitting on my bedside table (stuff I’ve not read through yet) and she was dusting. She moved the comics, dusted, waited quite some time to ensure there was no residual Pledge hanging out, then washed and dried her hands prior to replacing them. Like I said - awesome.

 

We still can’t really figure out which one of us my daughter, Phoenix, looks like. It’s a common source of conversation for relatives, and I entertain it well enough, but I really don’t care. Who does she look like? I have no idea. You know what I do know? I know she smells like me. If I let my hair grow long (which turns out more “big” than “long”), fail to wash my hair, or don’t put gel in my hair one day, my head has a very distinctive smell. You can smell my pillow and know which one is mine. Anyway, Phoenix’s head smells like me. So out of a room of identical kids, I’d still be able to find mine blindfolded. I think that’s pretty awesome.

Speaking of Phoenix, we have noticed she is far easier to feed when swaddled or otherwise incapacitated. If her arms are free, the bottle gets close and suddenly she has this Incredible Hulk strength and the arms fly up in front of her face into a sort of impenetrable forcefield that makes it impossible to actually get the bottle to her mouth. Move one arm and the other arm compensates. I totally can’t wait until she has some semblance of muscle control.

 

I’m pondering getting a Kindle. From what I’ve seen, I’d probably end up getting the smaller Kindle rather than the Kindle DX. I’ve done some research on e-readers and based on price and my general use case, I think the Kindle would work out nicely. If anything, it’d help me determine how often I use an e-reader. Eventually I want to get an iPad (on which I would use the Kindle app for reading), but given my propensity to constantly tweak things, my budget, and my Android-based phone, I think a Kindle is a good start.

 

I am thinking about getting a sound bar for our game room. Right now we have a full home theater system up there (receiver, game systems, TV, etc.) but the speakers I have up there are these giant towers that are nearly impossible to place reasonably given the room layout. That and my lack of ability/desire to start running wires all over leave me either with a wireless setup or a sound bar. I know you audiophiles will get up in my grill about sound quality and immersion and I know. I hear you. It’s just, again, a wire and size issue. Perhaps a decent set of satellite speakers and a throw rug would also answer the question, given that a decent sound bar costs more (in some cases) than an equivalent satellite speaker system with a subwoofer.

 

The Hunger
GamesI have been reading The Hunger Games based on the recommendation from just about everyone and it is a very compelling read. It’s the first book I’ve been sucked into in a while. I suppose that sort of pegs me as one of those people who doesn’t read complex stories or try to expand their reading level. You’re probably right. I don’t think the comics in The New Yorker are generally funny (which doesn’t mean I don’t understand them, just that I don’t think they’re funny); I don’t agree that most of the “classics” you’re forced to read during school are worth spending the time and effort on; and when I read for fun I don’t really want to have to expend a ton of mental effort to try and figure out what the book is trying to say. I want to have fun, relax, and escape for a while. If that means I end up reading books that show up in the “teen” section of the bookstore more often than not, well… so be it.

 

I [still] hate Facebook. I hate that most of the comments people leave on there have “LOL” somewhere in them, overused to the point it has lost meaning and is almost more punctuation than anything. I hate that people won’t actually send you a damn email when they have your email address and instead will do some “post to your wall” or “Facebook message” bullshit. I hate that people will leave entirely unrelated comments on things (e.g., post a picture of a house plant and get, “Hey, didn’t see you over the holidays. How was your Christmas?”). I hate that people pretty much abandon spelling, grammar, and punctuation, especially given Facebook doesn’t have the message length limitations Twitter has that would otherwise require the abbreviations and shortcuts. Yeah, I could go on all day about how much I really despise it, even amidst its obvious ubiquity on the net. I’m sure there will come a day when “Facebook” equates to “internet” for people the way that “the world-wide web” currently generally equates to “internet” for people. Get off my lawn, young punks.

 

I have been told by various relatives and friends that I should write a book. I’ve considered it. It’d be something you find in the humor section that has random stories and rants and sells 150 copies total. There are actually several reasons I haven’t.

  • Most of the stories people encourage me to write about would only be funny to people who were there or who know the people involved. “Had to be there,” as it were.
  • Of the remaining stories, they’re mostly at the expense of a friend or family member, and they’d only be thinly-veiled. I could probably embellish and change things a bit, but the people who know would know exactly what I was talking about and I don’t really want to hurt anyone’s feelings. Even if it would be pretty funny.
  • When I tell stories, I talk with my hands. You’d miss that in book form, and trust me, it adds to the story.
  • There would probably be a lot of dick and fart jokes, which is not something, I think, that most people expect from me. Well, people who don’t know me, right? RIGHT?

Anyway, no book. Maybe later in life, in retirement, when it won’t matter anymore. I’m sure there’s a market for that story about the wedding that had the midget in the cowboy outfit. Just not quite yet.

windows comments edit

I’m probably the only person who didn’t realize that if you hold down Shift and right-click a folder in Windows 7, you get additional commands that you don’t normally see. For example, holding shift down when you right-click a folder gives you an “Open command window here” option, which obviates the need for a “Command Prompt Here” power toy (at least for the basic prompt).

Thing is, I don’t want to have to hold Shift down. I just want it there all the time.

The “Open command window here” item is listed in your registry under HKCR\Directory\shell\cmd and HKCR\Drive\shell\cmd. If you look in those keys, you’ll see a REG_SZ value called “Extended” that is floating there without any actual value assigned.

The "Extended" registry
value

If you delete that “Extended” value, then “Open command window here” will always show up and you don’t have to hold Shift down. Conversely, if you add a no-value “Extended” key to things, they’ll stop showing up until you hold Shift down.

And don’t forget to look at both the Directory and the Drive registry keys as mentioned above or you’ll wonder why it shows up sometimes and not in others.

YMMV. This works for me, might not for you. I’m not responsible if you delete something important and your machine comes crashing down around you. You have to be extra careful when you muck with the registry.

media comments edit

In Christmas 2009 I got a Creative Vado HD camera. It’s a nice, convenient little camera and we use it quite a bit. The only real issue I’ve found with it is in editing the video it takes. On Windows XP, if you install the software that comes with the camera, the files play just fine but you can only edit them using the editor that comes with the camera. On Windows 7, the files play just fine without installing any additional software, and you can edit the files… in Windows Live Movie Maker and that’s about it. There’s something not-quite-right with the file format and I’m not the only person who’s encountered it.

I use Sony Vegas to edit my videos. It’s a nice program with a lot of power behind it, and while it’s not the easiest thing to figure out, it is certainly flexible enough to grow with you as you get better at editing and making movies. Problem is, when you drop a Vado HD file into Vegas 9.0, it sees the audio but no video.

I blogged how to add H.264 video support to Vegas once I figured it out - install the x264vfw codec. For Sony Vegas 9, that fixes it.

Unfortunately, that doesn’t work in Vegas 10.

I upgraded to Sony Vegas 10 because it’s actually noticeably faster in processing/rendering video and is far more reliable than Vegas 9. Vegas 9 would occasionally crash on me for no reason; 10 really hasn’t crashed… but now I see a different symptom.

Without x264vfw, Vegas 10 doesn’t see the video on Vado HD files… and while it sees that audio exists, it can’t interpret it, so you see a flat line audio track that can’t play. If you try to play it, Vegas hangs.

Adding the x264vfw codec, Vegas 10 sees the video, but the audio still doesn’t work.

Again, on Windows 7 with Windows Live Movie Maker, you can play and edit these Vado HD files just fine.

I submitted a support question to Sony and after a fairly lengthy delay, I got the following response:

Hi Travis,

Thank you for contacting Sony Creative Software. First, I apologize for the unusually long delay in responding to you. Our new Vegas Pro 10 has been well-received and as such, a high number of people are coming to us for support on this product.

Unfortunately, we (and other editing programs) have encountered issues with Creative Vado footage and are currently looking to correct it. I have found that this forum link has helpful suggestions for your problem (and includes links to codec packs that help the product read the files better):

http://forum.videohelp.com/threads/302604-Creative-Vado-HD-AVI-%28H-264%29-Editing

These codec packs are not created by us and we do not do support on them, so any questions you may have regarding them I recommend you direct them to that forum.

We hope to include this codec in future versions of the software so that this extra step is no longer needed. Thank you for your report!

So it turns out Sony is aware of the issue but hasn’t yet addressed it. At least they’re aware of it.

In the suggested forum link (and in other forums), people have arrived at basically three solutions:

  1. Convert the Vado HD file to another format that Vegas understands and drop the converted file in.
  2. Split the audio and video in the Vado HD file into separate files. Convert the video part but leave the audio alone. Add the two separately into Vegas.
  3. Install x264vfw. That fixes it for Vegas 9 but not Vegas 10.

My solution went with option 1 - convert the Vado HD file to another format that Vegas understands. I use Windows Live Movie Maker (since it’s free) to do that conversion.

In Windows Live Movie Maker, create a new custom setting for videos. Use the following values, which will work for converting the high quality Vado HD files into something with no noticeable quality loss:

  • Width: 1280
  • Height: 720
  • Bit rate: 8500
  • Frame rate: 30
  • Audio format: 192kbps, 48kHz, stereo

Drop your movie into the Windows Live Movie Maker timeline.

Save the movie using the new custom setting.

Import the new/converted movie into Vegas.

Done and done. Not perfect, but better than nothing. Hopefully this gets addressed soon.