Recently in Programming Category

WCF with Silverlight

| No Comments | No TrackBacks

We’ve been using Microsoft’s Silverlight and the Windows Communication Foundation for the last several months as the User Interface and Web Service framework for our just-launched course schedule proofing project, ROOMS. As people have been doing the scheduling off of paper since long before Washington State University was known as such, people have been really excited at the possibility of working with a newer technology.

I’m not going to be talking too much about Silverlight itself, as I’ve been the developer responsible for the back-end work since I got brought onto this project. Silverlight isn’t a bad framework, by any means, but I do personally favor interface technologies that don’t require plug-ins. That said, the interface Silverlight has allowed us to create would have likely been harder without the benefit of Silverlight.

For building Web Services, WCF has a lot going for it. You’re interface for the service is easily provided in a single interface class, your Data Transfer Objects (DTOs) decorated with a few attributes, and your transport protocol can be changed with a few simple configuration options. It’s really flexible. We’re using it not only for our webservices, but also to communicate with a Windows Service which handles several long running tasks, saving us from triggering those events with a timer.

However, there are some unfortunate side-effects of pairing a WCF web-service with Silverlight that aren’t necessarily obvious.

Security

Our application needs to run over a Secure Shell connection, so that we can protect the user’s login state, and eventually any confidential data that becomes a part of this application. While Silverlight supports cross-domain web-service requests, it does not appear to support these over a secure link. The article linked does refer to Silverlight2 Beta 1, but it appears to me that this was not changed for the RTW.

Because of this lack of Secure Cross-Domain Web Services, you’re required to host your WCF services in IIS, which requires some modifications to your web.config file, which I have posted about here. More troublesome, is that if you do need secure webservices from a cross-domain source, this technology forces you to take steps like we need to with modern AJAX applications, wrapping up a webservice ‘locally’ so that it can be called the way we need it to be. Lot’s of unnecessary work there.

The other step, that is easy to forget, is that the Security method needs to be set correctly on both sides of the connection. In your ServiceReferences.ClientConfig file, as well as your web.config, your security is likely set to ‘None’. This must be set to ‘Transport’ for SSL to work, but more importantly, if you set it to ‘Transport’ it will only work over SSL. You could set up a different, insecure, Endpoint in your web.config if you wanted to offer both, but this is extra work that seems, to me, to be somewhat more inflexible than necessary.

Configuration

The biggest challenge we’ve had using WCF for our services has been maanaging the configuration steps. Anytime we add a new method to our service, we’re forced to rebuild the Service Reference in the Silverlight config. There is no obvious way to automate this as a build step, partially because our web project depends on our Silverlight app, and the web server must be running in order to update the service reference. In an ideal world, I’d build my services, start up the web server, load the service references, and then finish building the Silverlight. I’ve looked into doing this with MSBuild and svcutil, but it does not appear to be that simple.

The tools Visual Studio provides in 2008 are also insufficient. Generally, we are forced to delete the entire service reference and re-adding it, and even then I’ll occasionally end up with strange errors that are non-obvious as to their source. The way the configuration management works to date feels like a house of cards, and I’ve periodically lost significant amounts of time to rebuilding service references.

To save time and configuration, we’ve opted to store our DTOs in a shared assembly between our Web project that hosts the services and the Silverlight project. To support this, we first attempted to create the DTO project as a Silverlight project, and merely add a reference to both projects. Regrettably, this does not work. Silverlight is not .NET 3.5 (which introduced WCF), and while there are a lot of similarities between the two technologies, the assemblies the Silverlight project links that declare the necessary attributes are not the same version as used by .NET 3.5 and WCF, so the linking fails.

We got lucky on this issue, and we were able to use Visual Studio to create links from the Web Project to the DTO files, so we can build them once for the Silverlight and once for the WCF without breaking any code. Cumbersome, yes, but relatively easy, once you know what to do. In my opinion, it’s completely worth moving your DTOs into a seperate assembly like this, if for no other reason than it will be more conducive to performing Unit Tests later.

This does leave us with one major problem, namely, how do we keep our service references up to date as part of our build process? I haven’t quite figure that out yet, but the procedure we are most likely going to use is as follows:

  1. Examine WCF ServiceContract Interface.
  2. Find all OperationContracts under the Interface, and generate Callback Events and ASync Call methods for all of them
  3. Write out source to reference file, to be included in Silverlight project

We’re investigating a few methods to accomplish this. We met a guy at the Seattle Code Camp who had written XSLT’s to convert a chunk of XML into the Interface files, and that’s not necessarily a bad way to go. I could even use this to generate my DTO classes. I am investigating the possibility of doing a simple compile on the code itself, but I suspect the XML route would be easiest. Plus, that way our Interface files in the WCF project will be auto0generated as well. Plenty of interesting possibilities there. Once I’ve got it written, I’ll likely be sharing the solution we arrived at.

Both Silverlight and WCF are interesting technologies. Personally, I’m likely to do more WCF, but that’s largely because I’m a back-end systems developer, and Silverlight is definitely aimed at the UI-set. I know my limitations.

As I often think when dealing with Microsoft technologies, I wish they integrated a little more cleanly. Still, Silverlight and WCF are very usable together, and if you’re still writing web services in ASMX files, you owe it to yourself to at least consider WCF. I suspect it may make your life a lot easier in the long term.

LINQ and Premature Optimization

| No Comments | No TrackBacks

s a Man, the word ‘Premature’ sends shudders down my spine. As a Developer, it does as well, for additional reasons. Every student of computer programming has been taught about optimization at some point. Whether it’s been learning assembler for the hand-tuning of certain methods, to moving variable declarations outside of loops to save cycles, we’ve all been taught it. And at least for the last several decades, we’ve had the words of Donald Knuth from the December 1974 issue of the ACM Journal Computing Surveys thrown at us.

Premature optimization is the root of all evil.

And he’s right (maybe). And a lot of people have pointed that out. Luckily, we live in a day where compilers can often do a better job of optimizing our code than we can. These days, if we’re having a performance problem, we probably have a problem in our algorithm, something that requires changing (not tweaking) the algorithm. Note: I’m not including performance problems relating to bugs here, that’s a different problem.

Unfortunately, sometimes optimization done by the compiler can be premature and broken. I have encountered such cases in LINQ, and needless to say, I’m not terribly pleased by it.

In our database, we have our permissions split up among three different tables (representing the three different types of permissions). I’m not going to argue about whether or not this is the best way to have done this, I’m probably going to be changing this behavior, but it’s what I have right now, and that small refactor isn’t important enough to change right this instant. It did, however, lead to the following problem. But first, the schema:

DBSchema.png

As you can see, each set of permissions requires just a bit more data to qualify it. However, I found (at least) one case where I wanted to combine the records from each of these tables into a single return from a web service, using the following structure:

For those unfamiliar with newer versions of C#, the ‘?’ after a variable type means that the type is ‘null-able’. Obviously this only works on primitives, which couldn’t be null before. Anyway, back onto the code. I wanted to fill in a List of these with records from PermissionsPrefix and PermissionsCourse. But, as is shown in the schema above, MinCourseNumber and MaxCourseNumber don’t exists is Permissions_Course and should be set to null. Sounds easy enough, right? That’s what I thought, which led to the writing of the following LINQ query.

Fairly straight forward union. Request all the relevant permissions out of PermissionsPrefix (setting the Mix and Max course values to null), and union them with the relevant records from PermissionsCourses. This looked to me like it should work, no problem. Unforunately, it produces the following T-SQL statement:

Take a close look at that query. Notice how in the outer select both MaxCourseNumber and MinCourseNumber are being set to value6? And that the first union select, has 9 items and the second has 10? Needless to say, this doesn’t work. Since both Min and Max Course Number are being set to the same value, LINQ decides to try to optimize the select by only selecting the value once and assigning the value twice. Oh, easy fix, I hear you say, just switch the two queries, and put the request from Permissions_Course first!

No dice. The outer select is correct now, but the second inner select (from PermissionsPrefix) still isn’t selecting value6 twice, and it’s saving it as value6, when clearly the outer select is expecting properties named MaxNumber and MinNumber. So, these unions are completely broken because LINQ is trying to optimize them independently of one another, which clearly doesn’t work. Not only that, but the optimizations are only half done. They’ll gladly try to combine values in the select part of the statement (if I were to change the ‘null’ to ‘1’ in the query against PermissionsPrefix, it would combine it with the Term value), but they insist on sending in multiple parameters with the exact same values in other parts of the query. For instance, the value for Term is the same in both the Where clause and the select clause, but it’s clear that the SQL generated is sending the parameter in with two different names. This happens in the same query, not just across the two queries.

Why is this such a big deal? Simply because I now am forced to separate this out into two distinct LINQ queries, which each ToList() inside of .NET. Once I’ve done that, I have to then append the results of the second query onto the first list, resort the list how I want it, and dump the data back across the wire. Essentially, I have to redo in .NET a lot of things that SQL is specially tuned to do. Now, in this case, the number of records we’re dealing with is trivially small, and as we know, everything is fast for small n.

I fail to understand why Microsoft has built some optimizations into the LINQ processor and not others. Admittedly there are times when optimization is difficult because it’s not always clear when you should optimize the SQL. Sometimes (as in the query above) you can optimize ahead of time. Other times, you’ll need to wait until runtime, but that can always be determined by code-analysis. And if you’re not sure, you should always err on the side of caution, and not combine my select elements simply because a cursory glance suggests it might work, because there is a very good chance it won’t.

Premature Optimization may be the root of all evil, as it can lead to a large amount of wasted developer time, but as a developer I should be able to trust my compiler to not change my code in a breaking fashion. LINQ is a great tool, but it still has some issues I really hope Microsoft corrects for .NET 4.0.

Minifying JavaScript and CSS with GNU Make

| No Comments | No TrackBacks

At Yahoo! the Exceptional Performance team, has posted a series of guidelines for scalable, performant websites. Unfortunately, this is the only major web company I’ve encountered to date who has codified these suggestions in this fashion, but if you look over the companies who’s primary business is the Web, you’ll see the majority of these practices. If you want to test your own sites, Yahoo! made available the excellent YSlow, which plugs directly into Firebug.

One of the key suggestions is to minify all your JavaScript and CSS. This serves the primary purpose of making the JavaScript as small as possible for sending down the wire. Additionally, it might improve the speed of interpretation of the JavaScript and CSS, but that difference will be negligible and hardly worth noting. Luckily, Yahoo! has also released a tool for this.

The YUI Compressor is a Java application built on top of Rhino. The Compressor processes the JavaScript and CSS files and produces a far smaller version for distribution over the network. Most of the time, I’ve seen between a 20 and 50% reduction in filesize, and that’s before applying gzip. Not bad at all.

The biggest problem I’ve had is that the YUI Compressor was not designed to batch together a bunch of files. I use a syntax-highlighter script for code samples on this site, but I found that it was larger than I needed. Needing to compress the JavaScript, I chose to use my familiar GNU Make to automate the process.

When I say familiar, I’m being a bit facetious. I’ve written Makefiles before, but GNU Make knows how to build certain types of files, and I’ve never had to told it how. Luckily, it’s fairly simple:

This runs the YUI Compressor (from the path saved in JSMIN), with a JavaScript file as it’s argument, and the file with a MINSUFFIX (I use -min, like YUI does). Now, when I build a rule like this:

MINS=${SRCS:.js=${MINSUFFIX}.js}

minify: ${MINS}

All the JavaScript files get minified, but only if they’ve changed. I pair this up with a method that concatenates the files after minification, but that’s optional. The rule for CSS is almost identical, just replace .js with .css actually.

It’s important in building applications to keep in mind the need for an automated build process. GNU Make works great for this, if you’re on Unix. Even though JavaScript is an interpreted language, a simple compilation step, like YUI Compressor, goes a long way to improving the performance of the website overall. Automating this process makes deployment much easier, and is therefore worth pursuing. The above Make rule should help, not only with ‘compiling’ JavaScript, but with using Make for other languages that it doesn’t support natively.

This is part four of my articles on writing Custom ASP.NET Authentication. The first article served merely as introduction, but the second delved into writing a Membership Provider and what that entails. The third described building Role-Based Authentication.

Role-Based Authentication is great for many people’s goals in handling authentication, but often, particularly as an application grows, you find that you also need to control access to specific resources and not just activities. This is where the need for Claims-based Authentication rears it’s head. What’s important to understand is that you’re often going to end up using a mix of the two, with a leaning toward one or the other.

With .NET 3.0 and Windows Communication Foundation (WCF), Microsoft has finally released a Claims-based authentication mechanism. To be honest, I hate it, but it’s there. Like with many Microsoft technologies, I feel it’s unnecessarily complex, so while I’ll be talking about Microsoft’s Claims-based authentication, I’ll be talking about the one we’re using as well. I’ll hold my judgement on code-name Zermatt, but what’s currently available in System.IdentityModel is too much for me.

Essentially, you begin by declaring a Claim in your code. The claim is a data-type which represents a resource you want to control access to. The object is simple:

public class Claim {
  public string ClaimType;
  public object Resource;
  public string Right;
}

The ClaimType is a URI, which tells you what kind of Claim is being made. The Resource property identifies the resource being requested, and the Right is either custom defined or from the System.IdentityModel.Claims.Rights class to determine what the user wants to do, but we’ll get there in a minute. So far, fairly simple.

Next we, move into ClaimSets (this is where I feel things fall apart)

public class ClaimSet : IEnumerable<Claim>, IEnumerable {
  public abstract ClaimSet Issuer { get; }
  public abstract Claim this[int index] { get; }
  public static ClaimSet System { get; }
  public static ClaimSet Windows { get; }
}

Okay, the System and Windows ClaimSets are provided by Microsoft, Windows being Windows Security, and System being the OS level Claims. Depending on your application, these sets may or may not be important, but it’s the Issuer that’s most likely to be important. The Issuer can be used to determine the source of a claim, for instance a Web Application versus a Web Service could be different Issuers.

Since the above class is Abstract, you either have to derive a new class from it, or create a default Claim Set to test against. Ultimately, this is going to require a fairly complex custom structure to ensure that your claim sets are accurate to whatever you’re trying to accomplish in your application.

In order to test your claims, you call FindClaims against your ClaimSet with a claim you want to test for, and you can use that information to handle authentication. The complexity, and it’s painful complexity, is in building the ClaimSet. I’m not wholly convinced it’s worthwhile, which is why I went a slightly different route to solve this problem. If you are interested in Microsoft’s Claims-based Authentication, MSDN Magazine has an article on it this month.

For our purposes I built Claims-based Authentication into our Role-Based code, buy adding methods to our custom Principal. For us, we need to control access to Courses, Prefixes, and Terms, as well as determine if the user is authorized for a given action for that given Course, Prefix, or Term.

I’m not going to bother with code for this, as it was implemented purely by adding new methods to our implementation of IPrincipal. It works great, allowing us to verify our permissions, as well as a check those permissions to send that permission set to our client. The only downside is that we need to explicitly cast our Principal object in order to access our custom methods. Still, it provides the ability to test claims, without diving into the complexity of the ClaimSet implementation Microsoft is currently providing.

Authentication and Authorization are incredibly important steps in any web application, and Microsoft has done a pretty good job of providing a framework that is very customizable, while being fairly hard to break in an incredibly dangerous manner. However, I had been unable to find very many resources for doing this work, which I suspect many people will find themselves requiring. I hope that this series helps someone, as I know it would likely have helped me.

This is part three of my articles on writing Custom ASP.NET Authentication. The first article served merely as introduction, but the second delved into writing a Membership Provider and what that entails.

Now that you have a Membership Provider written, and you now have a method to authenticate and manage users. However, being able to authenticate the user is only half the problem. If you’re had to customize the login process, odds are you also are going to need to customize the authorization process as well.

The most common means currently to do this is to separate the concerns out into “Roles”. For instance, some users are Administrators, some users are Customers, some users are Salespeople, etc. Users can fit into multiple roles, but ultimately what they’re allowed to access is based on the Roles they’ve been assigned. This works well for authenticating users against certain activities, but it doesn’t really define what resources they have access to. We’ll get to that later, besides, for many cases, basic Role-based Authentication will work fine.

In ASP.NET this process is driven primarily by two Interfaces: IPrincipal and IIdentity.

The Identity is the interior class, so we’ll start there. The Interface is simple, including merely three Read-Only Properties. The first, a string representing the Name, the second a string representing AuthenticationType, and the final being a boolean IsAuthenticated. For us, this was not enough, as the Name field (which ASP.NET generally uses as the user name), is not what we use internally to identify the user. Luckily, we can freely add new Properties, since the rest of the API only requires it to be a IPrincipal.

So, what do these values mean? IsAuthenticated is generally set to true anytime a user has given a valid username and password. The reason for the property appears to act as sort of a gatekeeper into the rest of the class. In our Application, before I cast the IPrincipal into our application specific type, I test IsAuthenticated, because I know that if it’s false, then I’ve not set up the user with the correct Principal.

As for the AuthenticationType, I typically leave it as whatever the base authentication mechanism was. For our purposes we’re using Forms-based authentication, so we end up saving this as “Forms”. I never use this variable for anything, and I’m unclear if the framework does, but I’m fairly sure it’s important to leave this value as what it’s defined as in the Web.config. If nothing else, consistency is king, particularly in a system as dense and opaque as ASP.NET.

The name, I set to the Username for the user, but only because that better matches the name (and datatype) of the property. Internally, I still use the numeric ID which we use to uniquely identify our users, and that is what the Identity takes in the constructor. The name is merely calculated on each access of the property.

The second interface, and arguably more important is the Principal. It’s even simpler, as it only contains the Identity (again, Read-Only), as defined above, and an “IsInRole” method, which takes a string and returns a boolean. This makes using the class very easy. Need to know if the user is an admin?

if (User.IsInRole("administrators")) {
 // Do stuff for Admins
}

That simple. How you determine if a user is in a role or not is up to you. Active Directory Authentication checks AD groups for membership, for our purposes, we look into a database to determine if a user fits a certain role or not. You can define as many roles as you’d like.

This interface can be extended as well (obviously), but that discussion will wait until next time, where we talk about Claims-based authentication. Right now, there is one very, very important caveat regarding using your custom Principal and custom Identity. Namely, ASP.NET will not remember them between page loads. The ASP.NET login cookie doesn’t contain information about the principal for the user, so the next time the user hits your page, the system will view them as nothing more than a simple forms-authenticated user with a basic Principal and Identity that fails to give you access to the methods you’ve defined.

This is simple enough to work around, in your Global.asax file.

protected void OnPostAuthenticateRequest(object sender, EventArgs e)
{
    if (User.Identity.IsAuthenticated && User.Identity.AuthenticationType == "Forms")
    {
        var ident = (FormsIdentity)User.Identity;
        var userInfo = Membership.GetUser(ident.Name);
        var principal = new CustomPrincipal(
            new CustomUserIdentity(int.Parse((string)userInfo.ProviderUserKey), 
                User.Identity.IsAuthenticated, User.Identity.AuthenticationType));
        HttpContext.Current.User = principal;
        Thread.CurrentPrincipal = principal;
    }
}

Since ASP.NET so helpfully recasts your Identity into one of the base types, you’re basically stuck doing this on every page load. First we take the current Identity, which has been helpfully made a FormsIdentity, then we get their UserId from the Membership (remember, we made that the providerUserKey), then we declare our new Principal, giving it a new Identity as an argument. Since we did use Forms authentication, we use the values defined in the current Identity object to fill in parts of our new Identity object. If I wanted to allow non-forms based authentication, that should be possible as well, just don’t check the Authentication type, and leave the Identity an IIdentity, and you’ll be fine. For my purposes, non-Forms based authentication could be a problem, so I simply disallow it.

Once you’ve declared the new Principal, replace the default Principal with your custom one and you’re done. The only potential caveat is that any attempts to use your custom methods will require a type-cast into the Custom type, since the Interface doesn’t define your custom stuff, but if all you want is the IsInRole method, the cast is basically pointless.

This system isn’t horrid, my only real complaint with it is that ASP.NET fails to remember what I’ve done between pageloads. I know that the web is stateless, but with all the other work Microsoft did in trying to make ASP.NET seem state-full, this seems like quite the oversight.

New Releases in Web Technologies

| No Comments | No TrackBacks

This week saw two major releases in Web Technologies. First, YUI released 2.6.0, which brought eight tools out of Beta, and hundreds and improvements to the YUI libraries. One of my favorite features is that the YUI Loader, which I tend to use on all my pages, can automatically combine files into a single download. Fewer HTTP requests is a huge win, which should overrule the cache miss performance hit. In addition, there are a lot of accessibility issues added to the system, which having a state job is an important consideration.

Unfortunately, it doesn’t appear that any of the issues that I’ve submitted code for have been addressed, but several of them came up after the 2.6.0 pre-releases were made available (ie, post-code freeze), and I suspect my issues are somewhat fringe cases.. I’d still like to see some movement on them from Yahoo!, if nothing else to show that they’ve thought about the issue and made a decision on it.

But, in all I’ve been pleased with YUI 2.6. On the WSU Catalog upgrading was as simple as importing the newer version of YUI Loader. That simple. Of course, I’m only using a few different libraries, like the Menu and Connection Manager, so none of my modules were heavily affected, but I was pleased with the ease. I am most looking forward to YUI3 though, which will make YUI much easier to use and integrate.

Moving from the JavaScript side to the Plugin side, Microsoft finally released the first Release Candidate of Silverlight 2. Unfortunately, it’s developer only with no go-live license, but it implies that the final is really close. I’m suspecting the end of the month at Microsoft’s PDC. The conference release is consistent with how Microsoft has handled all Silverlight releases to date.

The release is a good one. It broke many things, but it’s far faster, the default style looks better, and they finally added some controls we pretty badly needed. One of these is the dropdown box that is finally available, but still many things are lacking. We’re having to use an external Rich Text Display, the dropdown box doesn’t fit all our needs, so we’re having to use a different one in a few places.

Mostly though, I’m not convinced the plugin route is wholly necessary. Sure, we’re using one in our current project, but we could do most of that in DHTML and JavaScript, and the browser requirements wouldn’t be much different. There has been so much work over the last six months in next-generation JavaScript interpreters which further makes me question if a proprietary plugin is necessary. The only reason Silverlight may catch on is for those users who simply don’t want to learn JavaScript. It’s an unnecessary technology today, and will become more so over the future.

Custom ASP.NET Authentication Part 2 - Membership

| No Comments | No TrackBacks

The first step in authorizing a user is authenticating them. There are any number of ways this could be accomplished, from basic Username/Password authentication against a database, to LDAP authentication, to biometrics, to the lowly Yubikey (which desperately needs more love). However, Microsoft only provides a small handful of authentication mechanisms, primarily based around Active Directory. For the RONet, we use a hybrid approach. We authenticate our users against Active Directory, but then verify that the AD user is authorized for our system. Admittedly, we could work this into the authorization step (discussed next week), but we don’t want to let un-authorized users do anything, so we simply deny them at authentication.

Unfortunately, this means we needed to write a custom MembershipProvider, which can be found in the System.Web.Security namespace. .NET does do quite a bit of the work for Membership for us, but interface demanded by the MembershipProvider is pretty heavy. For our purposes this was a fairly easy step, we manage very little of the user’s directory information and we can’t do anything with their password, so for us this class is pretty light-weight. Unfortunately, this does mean that we have a lot of methods that do nothing.

First, ther are a series of required Properties: 1. ApplicationName - The name of the Application you’re authenticating for. We don’t use this, but it’s set in the Web.config 2. EnablePasswordReset - Notes if the user can reset their password through our system. They can’t 3. EnablePasswordRetrieval - Notes if hte user can retrieve their password through our system. If this is ever anything other than false, you’re doing something wrong. Passwords should always be hashed, and preferably salted before hashing. Never, ever store plain-text passwords. 4. MaxInvalidPasswordAttempts - The number of times that a user can mess up their password before locking out their account. We don’t use this. 5. MinRequiredNonAlphanumericCharacters - Pretty straight forward. Only used when accepting new passwords. Not useful for us. 6. MinRequiredPasswordLength - Same as above. 7. PasswordAttemptWindow - How long, in minutes, to lock out a users account for when they mess up their password more than MaxInvalidPasswordAttempts. We don’t actually lock out user accounts, so we don’t really use this. We do use logic in the login page to prevent brute-forcing through our login system. 8. PasswordFormat - Returns a MembershipPasswordFormat value noting how the password is stored. Again, never use the value Clear. 9. PasswordStrengthRegularExpression - A regular expression (stored as a string) to match a password against to make sure it’s acceptably strong. In my opinion any password fitness methods used should probably be stronger than a simple RE, but this is probably better than nothing. 10. RequiresQuestionAndAnswer - Requires that you post a question and get an answer from the user before doing things like resetting their password. 11. RequiresUniqueEmail - Tells the provider to ensure that no duplicate e-mails addresses exist for clients.

I’m not going to go through all the functions required in this class (go here for that) because based on the Properties, the functionality of the class is pretty straightforward. This class provides functions to do a fair amount of user management, from locking/unlocking accounts, to making new accounts or removing old ones. It allows Passwords to be recovered, or reset, and provides information necessary to facilitate the kind of security questions that we see all over the web. Most importantly, this class provides the mechanism for you to define how the data store is checked for user’s information.

For our purposes, we don’t care about User Management at this time (eventually, I will likely implement the functions to place user records in our local data store, but for the time being, that data is managed by a Classic ASP app). We will never likely care about Password Management, as that is a requirement for Central IT and the University Active Directory. Because of this, the functions which handle that functionality either return false (where appropriate), or throw exceptions (where appropriate). Sometimes the exception is a ProviderException, other times, it’s an InvalidOperationException, though I’m on the fence about whether or not the IOE’s should be replaced by ProviderExceptions.

It is important to note, that the only NotImplementedExceptions that I’ve left in the code are methods that I fully intend to implement. Like the Mono project, I believe that a NotImplementedException is the same as a TODO item. That’s just kind of an aside, but it makes the most sense to me.

Moving on, we’ve got methods to get an individual users’ MembershipUser.aspx) record. These are fairly straightforward, contaning the MembershipProvider Name, the user’s username, unique key, email, Password restore question, and description, if their account is locked out, creation/logon dates etc. Lot’s of information, but nothing too sensitive. You can search for a MembershipUser based on username or unique key. If you want their username based on their e-mail, you can either search for their username based on their e-mail, or get back a MembershipUserCollection (which only makes sense if RequiresUniqueEmail is false, obviously).

And the MembershipUserCollection comes up often. Internally, it appears to be a List which can only contain MembershipUsers, though it wasn’t implemented with Generics. These methods are harder to implement as they require the idea of ‘paging’, where a request is made for a certain page of records, or a certain pageSize. You return to the user the MembershipUserCollection based on the search for their their e-mail, or username, or a complete list of users, and an out parameter which contains the total number of records in the entire data set.

One really nice thing about this MembershipProvider system is that you can allow certain options to be set by the User if that makes sense. There is an Initialize() method for the provider class which takes a Dictionary as an argument. With that, the user can specify the values they want for every property you provide. Now, for us, we’re the only ones who will be using this class, and the options aren’t really negotiable, so I’ve hard-coded them. But, this is a level of flexibility that is nice to have if you aren’t implementing such a special purpose (albeit reusable within our unique problem space) MembershipProvider.

There is one thing I’d like to mention before I wrap this up, and that is some caveats I ran across in my authentication step. The method which validates a user’s credentials is the ValidateUser method, which takes in a Username and Password and returns a Boolean value to indicate if the user should be allowed in to the system. My first draft of the method looked like this:

  1. public override bool ValidateUser(string username, string password)  
  2. {  
  3.     try  
  4.     {  
  5.         DirectoryEntry de = new DirectoryEntry(“LDAP://ad.example.com/cn=” + username + “,OU=Users,DC=ad,DC=example,DC=com”,  
  6.             “ad" + username, password);  
  7.     }  
  8.     catch (Exception e)  
  9.     {  
  10.         return false;  
  11.     }  
  12.     var ronet = new RONetDataContext();  
  13.     return (from users in ronet.Users  
  14.                       where users.EmployeeId == (int)de.Properties[“employeeID”].Value  
  15.                       select (users.Enabled && !users.Cancel)).SingleOrDefault();  
  16. }  

The code is fairly straight-forward. We try to log-in to the Active Directory server as the user, and recover that user’s specific DirectoryEntry. We then check our local database (using LINQ) by finding a user with the given EmployeeID (I’d do an integer comparison, but the code wasn’t originally written to do that, and the refactoring project hasn’t begun), and then make sure that the user is Enabled, and not Cancelled. The call the SingleOrDefault will cause the statement to return false if no matching records are found.

Of course, I did say this was my first draft, so that fact that it didn’t work is likely apparent. I already knew that LINQ was a lazy-loading API. For instance, if I were to drop the call to SingleOrDefault and save the query into a variable, I would get an IQueryable object, which I could choose to apply more constraints to. No call to SQL would be made until SingleOrDefault (or any method that returns an actualy value, or set of values) is called. It’s fairly simple. It turns out, however, that DirectoryEntries are also lazy-loaders. If the username or password was invalid, this particular method would fail would throw an exception at the point I tried to access the Properties, not at the initialization of the DirectoryEntry object.

The revised code I settled on simply moved the LINQ into the try-block, since even a Database Query should result in a false return value. While I’m not doing any logging in the Catch block, certainly, I am not precluded from doing so.

That leaves only one final step to configuring a custom MembershipProvider, and that is defining that provider in the Web.config file for your site.

  1. <system.web>  
  2.     <membership defaultProvider=“CustomMembershipProvider” userIsOnlineTimeWindow=“20”>  
  3.       <providers>  
  4.         <add  
  5.           name=“CustomMembershipProvider”  
  6.           type=“CustomMembershipProvider” />  
  7.       </providers>  
  8.     </membership>  
  9. </system.web>  

And that’s it. Just refer to the Membership object in the HttpContext, and you’ll now be using your custom MembershipProvider. The userIsOnlineTimeWindow is used to set the timeout on the Cookie that the user is given when they login (Yes, ASP.NET uses separate Session and Authentication cookies), but this provides seamless integration with existing ASP.NET controls with your custom User store. Logging a user in via FormsAuthentication looks exactly the same as if you were using any other authentication mechanism, allowing you to easily swap out MembershipProviders with little to no impact on the rest of your application, which is probably my favorite part.

Next time I’ll talk about the next step of validating the user, Authorization. Including means to ensure that you can do more fine-grained control of a user’s access than simply checking their broad role definitions.

Custom ASP.NET Authentication

| No Comments | No TrackBacks

Microsoft's ASP.NET was an attempt to bring the Stateful Application Model to the Stateless Web. For a certain (admittedly common) type of Application it works pretty well. Provided, of course, that you don't want to do something outside of the 'normal' ASP.NET model. This is, of course, part of why I dislike ASP.NET so, but it is the technology our office has chosen to pursue, and it has led to some interesting challenges as we try to bend the technology to fit our needs.

The primary suite of Web Applications that we maintain, is what we call the RONet. The architecture on the RONet was done right around ten years ago, and the entire architecture was written in classic ASP/VBScript. The architecture, which this post will not go into, is pretty clean, but it was clearly designed at a time when the Internet, and a Web Application, was not what it is today. The existing Architecture, while sufficient for what has already been written, is not sufficient for moving forward, so we have been working on putting in to place a new Architecture to replace the old one in a piecemeal fashion.

Regrettably, Microsoft did not provide any good mechanism to integrate Classic ASP to ASP.NET. This makes the task of a piecemeal replacement of Classic ASP with ASP.NET far more difficult than it needs to be. There are a few methods to work around this. In Classic ASP, Authentication is typically verified using a Session variable. One solution, is to copy the correct Session variables from Classic ASP into ASP.NET. There are known methods (read: ugly hacks) to accomplish this.

The problem with reimplementing this sort of Session-based authentication in ASP.NET is that it's not terribly forward thinking. ASP.NET implements it's own Authentication model that exists beyond the session (that's not entirely fair, as the Authentication is tied to the Session Cookie, but bear with me), and by not taking advantage of the ASP.NET model, you lose access to things like the built-in Role-.aspx) or Claims-based Security.

This post represents the beginning of my adventures in customizing the ASP.NET Authentication mechanism. There will be several most posts over the next few weeks regarding how this is accomplished. We will be using ASP.NET Forms Authentication, since Forms authentication is best suited for the work that I've been doing.

  1. Custom MembershipProvider to customize the Authentication Step
  2. Custom User Principal to customize Role-based Authentication
  3. Custom Claims-based Authentication

The next post in the series will be posted next week, where I'll be going over writing a custom MembershipProvider, and particularly focusing on some of the challenges that I ran in implementing our particular system.

Dynamic Loading of Print Stylesheets with YUI

| No Comments | No TrackBacks
        <p>By and large, people don&#8217;t want to send to the printer the exact same thing as they see on the screen.  The screen display is often full of ads is difficult locations, has sidebar and navigation information that isn&#8217;t relevant to the printed page.  For this reason alone, it makes a lot of sense to offer a print-optimized stylesheet for users who opt to print your content, and luckily this has become pretty easy.  Virtually every browser in use today supports the &#8216;media&#8217; attribute on the link tag (the tag used to include remote stylesheets), which, if set to &#8216;print&#8217; will only be used when the user goes to Print, or Print Preview, one of your pages.</p>

The problem with this is that the CSS still follows the loading rules that all CSS pages are beholden to, meaning that if the print stylesheet is going to override anything it needs to be the last page loaded, even though it won’t be used to display anything. On a site like the new WSU Catalog, where we will display a different CSS based on the options for the page the user is visiting, specifically the Campus of interest, this leads to an interesting problem. Namely, Firefox 2 does not allow you to set the media attribute on a link tag dynamically, once the CSS has loaded.

So, what do I mean by this? Well consider the following code, using the Yahoo User Interface (YUI) Get Utility:

    var urls = [
        "http://designer.wsu.edu/template/css.aspx?key=11f14af0axx081",
        "http://www.wsu.edu/navigatewsu/gen2/print.css"
    ];

    YAHOO.util.Get.css(urls,
    { onSuccess: function(o) {
        for (var i = 0; i < o.nodes.length; i += 1) {
            if (o.nodes[i].href.indexOf('print') > 0) {
                o.nodes[i].setAttribute('media', 'print');
            }
        }
    }
    });

In the above JavaScript, I’m loading a WSU Dynamic CSS Template, as well as the official WSU Print template. Once the CSS is loaded, I find the print CSS, and set it’s media attribute to print. This works on IE 6/7, and Firefox 3. However, on Firefox 2, the Print CSS is displayed, even when out of printing mode. Not willing to stop there, I ran a test, where I build the <link> tag directly and inserted it with the media attribute already set, and sure enough it worked.

This implied to me, that YUI could be extended to support Firefox 2 in this manner. The question was how? I see two answers to that question.

First, would be to allow an optional object associated with each URL, which was an associative array of attributes to apply. The second would be to allow the object that Get.css takes to accept a set of attributes to apply. The first one is potentially confusing, the second requires more code. Ultimately, this probably means the second one is better. Also, both sets of changes requiring hosting the modified Get utility yourself, as you can’t simply replace the necessary code at run-time.

But, for the sake of example, let’s talk about what the first one would require. To the developer, the interface would look like this:

    var urls = [
        "http://designer.wsu.edu/template/css.aspx?key=11f14af0axx081",
        ["http://www.wsu.edu/navigatewsu/gen2/print.css", { "media": "print" }]
    ];

    YAHOO.util.Get.css(urls);

It’s not much of a change, and the code is fully backwards compatible with the old way, but it’s not quite as obvious what the intent is. For the second method the external interface would look like this:

    YAHOO.util.Get.css("http://designer.wsu.edu/template/css.aspx?key=11f14af0axx081");
    YAHOO.util.Get.css("http://www.wsu.edu/navigatewsu/gen2/print.css",
    { "attributes": { "media": "print" }
  });

Method 1: URLs with Attributes

The necessary code changes are visible in the following unified diff):

--- get-debug.js    2008-06-18 08:18:27.939931500 -0700
+++ get-debug-changed.js    2008-08-28 11:34:24.478309800 -0700
@@ -87,15 +87,15 @@
      * @return {HTMLElement} the generated node
      * @private
      */
-    var _linkNode = function(url, win, charset) {
-        var c = charset || "utf-8";
-        return _node("link", {
+    var _linkNode = function(url, win, custom_attrs) {
+           var attrs = custom_attrs || { };
+           attrs.charset = attrs.charset || "utf-8";
+        return _node("link", lang.merge({
                 "id":      "yui__dyn_" + (nidx++),
                 "type":    "text/css",
-                "charset": c,
                 "rel":     "stylesheet",
                 "href":    url
-            }, win);
+            }, attrs), win);
     };

     /**
@@ -106,14 +106,14 @@
      * @return {HTMLElement} the generated node
      * @private
      */
-    var _scriptNode = function(url, win, charset) {
-        var c = charset || "utf-8";
-        return _node("script", {
+    var _scriptNode = function(url, win, custom_attrs) {
+           var attrs = custom_attrs || { };
+           attrs.charset = attrs.charset || "utf-8";
+        return _node("script", lang.merge({
                 "id":      "yui__dyn_" + (nidx++),
                 "type":    "text/javascript",
-                "charset": c,
                 "src":     url
-            }, win);
+            }, attrs), win);
     };

     /**
@@ -245,12 +245,18 @@


         var url = q.url[0];
+        var custom_attrs = {};
+        if (lang.isArray(url)) {
+           custom_attrs = url[1];
+           url = url[0];
+        }
+        custom_attrs.charset = q.charset;
         YAHOO.log("attempting to load " + url, "info", "Get");

         if (q.type === "script") {
-            n = _scriptNode(url, w, q.charset);
+            n = _scriptNode(url, w, custom_attrs);
         } else {
-            n = _linkNode(url, w, q.charset);
+            n = _linkNode(url, w, custom_attrs);
         }

         // track this node's load progress

It’s a fairly small number of code changes, but it does change the internal structure fairly significantly. Some of these changes are unavoidable in trying to solve this problem, other may be.

Method 2: Attributes for All

The diff in question:

--- get-debug.js    2008-06-18 08:18:27.939931500 -0700
+++ get-debug-otherchanges.js   2008-08-28 12:41:30.457239000 -0700
@@ -87,15 +87,16 @@
      * @return {HTMLElement} the generated node
      * @private
      */
-    var _linkNode = function(url, win, charset) {
+    var _linkNode = function(url, win, charset, attrs) {
         var c = charset || "utf-8";
-        return _node("link", {
+        var a = attrs || { };
+        return _node("link", lang.merge({
                 "id":      "yui__dyn_" + (nidx++),
                 "type":    "text/css",
                 "charset": c,
                 "rel":     "stylesheet",
                 "href":    url
-            }, win);
+            }, a), win);
     };

     /**
@@ -106,14 +107,15 @@
      * @return {HTMLElement} the generated node
      * @private
      */
-    var _scriptNode = function(url, win, charset) {
+    var _scriptNode = function(url, win, charset, attrs) {
         var c = charset || "utf-8";
-        return _node("script", {
+        var a = attrs || { };
+        return _node("script", lang.merge({
                 "id":      "yui__dyn_" + (nidx++),
                 "type":    "text/javascript",
                 "charset": c,
                 "src":     url
-            }, win);
+            }, a), win);
     };

     /**
@@ -248,9 +250,9 @@
         YAHOO.log("attempting to load " + url, "info", "Get");

         if (q.type === "script") {
-            n = _scriptNode(url, w, q.charset);
+            n = _scriptNode(url, w, q.charset, q.attributes);
         } else {
-            n = _linkNode(url, w, q.charset);
+            n = _linkNode(url, w, q.charset, q.attributes);
         }

         // track this node's load progress

This diff is shorter, and the API is more consistent with the Get utilities old behavior, as well as the rest of YUI. This is probably the better answer to this problem. In fact the only downside is that a second call to Get.css is required, and is that really that negative?

Method 3: YUI ain’t Broken

Okay, there is actually a means to accomplish this without changing YUI, and I would be remiss to not mention it. It looks something like this.

In the Header:

    <link id="print_css" media="print" type="text/css" charset="utf-8" 
        rel="stylesheet" href="http://www.wsu.edu/navigatewsu/gen2/print.css" />

In the Script:

    YAHOO.util.Get.css("http://designer.wsu.edu/template/css.aspx?key=11f14af0axx081", { "insertBefore": "print_css");

This works fine. I only have two problems with it.

  1. I can not dynamically choose my print css with this method
  2. It does not future proof the Get utility for future optional attributes

Ultimately, I like Method 2. I think it’s the most flexible, while also the most compliant with current YUI standards. I’ve submitted these patches to Yahoo!, so we’ll see if they go anywhere, and I’m going to look into YUI 3 to see about extending this functionality there.

Fun with Internet Explorer and JavaScript

| No Comments | No TrackBacks
        <p>Last week, Adrian Reber (known in the <a href="http://fedoraproject.org/">Fedora</a> community), posted about why he feels <a href="http://lisas.de/~adrian/?p=189">Internet Explorer is important</a>.  The tone of the post is pretty snooty, but I find myself often in a similar position.  I use Firefox most of the time.  At work, where I have to use Windows, I have Internet Explorer available, but it&#8217;s pretty rare I fire it up.  Firefox is simply the better browser.</p>

But, IE is the more common browser on the web, by a pretty significant margin. Surely, Firefox has made significant progress on the marketshare front, but it’s still definitely a minority share. But it has some great tools for web development. By using a combination of the Web Developer Toolbar, and Firebug I’m able to put out CSS and JavaScript far faster than I would be able to without the tools, particularly when it comes to the JavaScript automation, but these tools are only available on Firefox, and can’t really emulate the issues that are encountered when trying to run with IE.

Yesterday, I published a new backend for the Washington State University Catalog, which is based on the ASP.NET MVC Framework. It’s not 100% bug free, but it works well, and I’m actively monitoring it to fix the issues that arise. However, before I published it yesterday, I had to work through a series of issues to make the site work correctly in Internet Explorer. Below is a description of several of those JavaScript issues, and the resolution.

Form Element Detection

The DOM makes handy references for parts of a Form available based on the name attribute of the input element of the form. For instance the following HTML:

    <form name="test_form" id="test_form">

        <input name="text1" type="text" />
        <input name="button" type="submit" />
    </form>

This create a simple form, with two input elements. If you hold a reference to the form (either by getElementById, or document.forms, or whatever), you can reference the sub elements by their names. For instance

    var frm = document.getElementById("test_form");
    frm.text1.value = "Fill in the Form";

Will place the text “Fill in the Form” into the text1 element of the test_form. Only one problem with this, IE doesn’t add such references for dynamically created input elements. On the General Catalog Academic Calendar, I allow users to select a campus that they’re interested in. This is because we have Calendar data for campuses which do not have full Catalog data prepared yet, so it’s a reasonable compromise. However, to build that option, I dynamically create the campus select box. In Firefox, when I set the name attribute of the input element, and insert the code, it just works. I ran into an issue, however, where the function which performs the JavaScript manipulation of the function was getting called twice. Here is the basic code as I’d originally wrote it:

var OnFormLoad = function() {
    if (form.AC_Select) {
        form.removeChild(form.AC_Select);
    }

    if (catalog.campus === "General" && !form.CampusSelect) {
        var cs = document.createElement('select');
        cs.setAttribute('name', "CampusSelect");
        form.insertBefore(cs, form.YearTermSelector);
        connect.asyncRequest('GET', catalog.base_url + "/AJAX/ValidCalendarCampuses",
            { success: function(o) {
                try {
                    var campuses = YAHOO.lang.JSON.parse(o.responseText);
                } catch (e) {
                    form.removeChild(cs);
                    return;
                }
                var option;
                for (var i = 0; i < campuses.length; ++i) {
                    option = document.createElement('option');
                    option.appendChild(document.createTextNode(campuses[i]));
                    option.setAttribute('value', campuses[i]);
                    cs.appendChild(option);
                }
                event.addListener(cs, "change", OnYearTermSelector_Change);
            },
            failure: function(o) {
                form.removeChild(cs);
            } }, null);
        }
    }
};
event.addListener(yts, "change", OnYearTermSelector_Change);
event.onAvailable(form, OnFormLoad);

This uses the YUI to register the onAvailable event to the form, and call the function, which simply removes the Select button, registers the onChange event for the YearTermSelector box, and creates the Campus select box, before using AJAX to get the contents and fill in the box. Simple enough, right?

Unfortunately, it doesn’t work in IE. Internet Explorer does not add form child elements to the form object when they are created dynamically like this. Not only that, but it doesn’t remove references in the form, when the child element is removed from the form. Which means that form.AC_Select will always evaluate as truthy, because IE never nulls it out, and form.CampusSelect will always be falsy, since IE never initializes it. In order to make this work, I had to create a boolean variable outside the scope of the function, and set it in the function to make sure that it worked. Like this:

var OnFromLoadRan = false;
var OnFormLoad = function() {
    if (!OnFormLoadRan) {
        form.removeChild(form.AC_Select);
        if (catalog.campus === "General") {
            // Build Campus Select box
            // removed for brevity.
        }
        OnFormLoadRan = true;
    }
};
event.onAvailable(form, OnFormLoad);

Since the OnFormLoad function is located within a function, this puts the OnFormLoadRan variable in a function-level closure, which means nothing outside of the function which contains OnFormLoad can touch it. This is kind of hacky, but it works, and one could argue that the lower level of de-reference is more performant. It may be, but the code is less clean, and that’s my big problem with it.

Inserting Options into a Select List

Another UI trick I use pretty heavily on a few of my forms is the creation of a “dummy” record in a select box, that is set as the default, which allows me to take advantage of the “OnChange” event of those select boxes more effectively. The example page I’ll use for this is the Academic Unit selector. This page will create the “* Select an Academic Unit * option, and append it to the top of the list, setting it as the default option. Now, whenever the OnChange event fires, I can be reasonably sure that the user has selected something valid.

I was initially doing the addition of this special element as follows:

var OnFormLoad = function() {
    if (form.AU_Select) {
      form.removeChild(form.AU_Select);
      form.AU_Select = null;
      var no_select = document.createElement('Option');
      no_select.appendChild(document.createTextNode("** Select an Academic Unit **"));
      form.AU_ID.add(no_select, form.AU_ID.firstChild);
      if (unit_info.textContent === '') {
            form.AU_ID.selectedIndex = 0;
      }
    }
};

The add function is the one in question. The W3C standard for the DOM declares that the add function takes the option element to add to the select box, and, optionally, the option element that you wish the new element to precede. Generally speaking you’ll either omit the second argument, to append to the end, or you’ll use the firstChild reference as I have to insert at the beginning of the list. Actually, this might be somewhere where IE’s API is a bit more sensible, but it is against the standard and it does require special coding around.

In IE there are two methods to fix this, both surrounding that add function call. You can either use add the way IE declares it, where the second argument is the index of the option you want to insert before, as follows:

try {
    form.AU_ID.add(no_select, form.AU_ID.firstChild);
} catch (ex) {
    form.AU_ID.add(no_select, 0);
}

Or, you can use the more general DOM manipulation method, insertBefore:

form.AU_ID.insertBefore(no_select, form.AU_ID.firstChild);

Which you choose is dependent of which you prefer, and I’m not sure what the best answer is. insertBefore is more direct, but if you’re using insertBefore to insert children, I’d suggest using appendChild to add new elements to the end of the list, for consistencies sake. That’s really the more important part is being consistent.

But there was one more bug in first version of the function that you may or may not have seen.

Default Values for Contents

Yep, when I make that comparison of the unit_info.textContent to the empty string, I am depending on browser specific behavior.

So, to review, the code is this:

if (unit_info.textContent === '') {
    form.AU_ID.selectedIndex = 0;
}

Which works great in Gecko and Webkit-based browsers. However, IE does not default the value of textContent to the empty string for empty divs. I suspect this is related to the fact that IE doesn’t treat white space as their own DOM elements, but the point is that on IE, unit_info.textContent is null, so it does not absolutely equal the empty string, like I’m checking. Plus, even if I allow type coercion by not using the tripe-equals operator, null and the empty string are not equal. Luckily they are both falsy, so changing the if statement to the following works fine:

if (!unit_info.textContent) {
    form.AU_ID.selectedIndex = 0;
}

JavaScript is a poorly defined language, with a lot of implementation level details that we need to be aware of. It would be fantastic to have a more standardized platform, and we’re slowly working our way there, but somehow I doubt we’ll even be truly free of these sorts of niggling implementation details.

About this Archive

This page is an archive of recent entries in the Programming category.

Politics is the previous category.

RHA is the next category.

Find recent content on the main index or look in the archives to find all content.

Once You Know, You Newegg

μ-updates

  • No Updates!
OpenID accepted here Learn more about OpenID
Powered by Movable Type 4.21-en