11 March 2013

codeless: temporary variables

/TECH
One of the problems I ran into in January was that the userName() function in InfoPath returns something different when used on a web form in a claims-based environment. This post will walk you through two things: creating "temporary variables" in InfoPath and sanitizing the userName() result.

Temporary variables are wonderful in programming and I missed them dearly when I started working with InfoPath. Typically I'd just make a field in some obscure part of the form and not publish it, but there was always a chance that someone with some know how could find that data. It became even more prudent when I started experimenting with a service that retrieved a list of the current user's SP security groups. So I finally searched for a solution. I don't remember who's blog I read first, but there are lots of results out there that all say the same thing: use an XML file.

It's a pretty simple and clever solution. Since data connections can either be "read" OR "write", when you change the data in a secondary connection that's a read-only connection it doesn't save the data. Hey, that's kind of like a temporary variable! Constructing the XML file is pretty simple. Here's one that I've used:
<?xml version="1.0" encoding="utf-8"?>
<currentuser>
 <username />
 <preferredname />
</currentuser>
You can't specify type--as far as I can figure out--but most of the time strings are just fine. The advantage of this system is that you can get info about the current user, store it in a field for use, but not have to worry about purging the data before saving the form. This became a huge advantage with our recent userName() debacle.

In January, we launched a new web application on our SharePoint farm that utilized single sign-on and a claims-based authentication. Two major things broke when we tried using a form: accessing web services and the userName() function returned a string I'd never seen. Normally the function would return "jdoe", but in the claims-based environment it returned "i:0#.w|domain\jdoe". This was a huge issue because a lot of our forms compare the current user to some kind of list to determine access. Changing every single rule that used userName() to some unwieldy expression was not sounding fun either. So I devised a new method.

Instead, I used a temporary field and two form load rules. Using the XML example above, I then created two rules in my form load rules.

Click here to return to my listing of "codeless" blog entries. The underlined username is referring to the field in the secondary XML resource.

Rule #1 - current user has slash
Condition: contains(xdUser:get-UserName(), "\")
Action:
  Set a field's value: username = substring-after(userName(), "\")

Rule #2 - current user no slash
Condition: not(contains(xdUser:get-UserName(), "\"))
Action:
  Set a field's value: username = userName()

Now I have a field that will always contain only the username of the current user. The disadvantage of this is where you have fields that set their default value once and used the userName() function. To overcome this problem all you have to do is add a third form load rule that I like to call "First Load".

Rule #3 - First Load
Condition: FormName is blank
Action:
  Set a field's value: FormName = concat(now(), "_", username)

And that's all there is to it. Click here to return to my listing of "codeless" blog entries.

Until next time:
Work smart. Live free.