Archive for the 'InfoPath' Category

InfoPath forms with file attachments: one potential solution, for all InfoPath forms?

InfoPath is a pain in the backside to me and my colleagues. Our users knock up a variety of forms and then ask us to support them when they go wrong, or don’t do what they need. Just to add a little more to that, we only have InfoPath 2003 on the client machines, which means we are working with legacy forms. Currently, our production systems run SharePoint 2007.

We had one such problem arrive on my desk a few weeks back. It seemed that a form was put together by another department that had around 20 (yes twenty!) file attachment controls on it. Each instance of this form would be a ‘case’, that would be under version control in it’s destination form library. I was shown some examples, and we had some InfoPath forms reaching upwards of 100MBs in size. We weren’t all that surprised that the more remote locations that my company occupies had issues reading these forms over our aging network infrastructure. They also have thousands of cases, so we would be looking at version controlling large files, and lots of them. We needed to avoid this, just to ensure we are being sensible with our backups!!

How to fix this? Well, you could add code to the InfoPath form template that uploads attached documents to a SharePoint document library. An excellent approach is devised here: How to upload a document to SharePoint from an InfoPath form. There are numerous others dotted around the internet similar to this… but what if you want to leave the novice users get on with it, without having to train them on how to hack code behind the templates?

I think there may be a solution to this, but believe me, it makes your eyes water when you look at how we have achieved it. It does look like an abomination… but it works, so I thought I’d blog about it and get some opinion from others who may have this issue in their organisation.

Why this solution is different:

  1. No code is required behind the InfoPath template
  2. Works with InfoPath 2003/2007 (untested with 2010)
  3. Works with any InfoPath template with only minor modifications required (as explained in this article)
  4. Uses the HTTP submission method
  5. Destination of file attachments is dynamic, users can alter this using standard InfoPath rules
  6. It requires a custom web handler (deployed to the GAC, deployed as a solution in the SharePoint farm)
  7. Removes attached files and replaces them with a URL file, to allow the user to click on it and open the file from the SharePoint document library
  8. I’ve only tried this in SharePoint 2007, but it should work with SharePoint 2010.
  9. This is a deploy and forget solution – no costly maintenance overhead, just some very simple guidance.

Known limitations:

  1. Only works with HTTP submit, with the built in submit button (if you know how to remove this limitation let me know!)
  2. Doesn’t permit folders inside the Form Library [it will always submit to the root folder]
  3. Users are told that they are likely to be opening a virus when they click on a URL link inside InfoPath – annoying!

Before I begin, acknowledgements must go to:

  • My fat blog – validation of allowed file extensions
  • Adis Jugo – validation of filenames to ensure SharePoint compatibility
  • Microsoft KB892730 – decoding, and encoding InfoPath attachments
  • Cyanwerks – creating URL files using the URL file format
  • … the man with the plan [who came up with this hair brained scheme in the first place, because it wasn’t me!]

The rest of the code is purely draft, non-production level stuff.

How it works:

  1. InfoPath form is submitted to a web handler [I have coined it the InfoPath file extractor (IFE)] (ashx) that is running in the SharePoint application pool with full trust
  2. InfoPath form uses query string arguments to tell it where to look for fields required.
  3. InfoPath form has a field group and a number of field to configure the extraction process
  4. Web handler traverses the submitted InfoPath for looking for base64 encoded attachments
  5. Each attachment is decoded and uploaded to SharePoint Document Library (with folder creation) based upon the configuration set in InfoPath
  6. Each attachment is replaced with a URL file linking to the uploaded file
  7. InfoPath form (with attachments replaced with URL files) is then persisted in a form library

Running Example [code available to download at the end of this article]:

First, use stsadm to deploy the wsp file (it generates this when you build it in Visual Studio, see the post build events, by default it uses c:\wsp at the destination). As shown in Figure 1

stsadm -o addsolution -filename c:\wsp\ife.wsp

imageFigure 1 – STSADM successful deployment 54

Add the solution to your web farm using SharePoint Central Administration. When you open Solution Management, it will be shown as not deployed. See Figure 2.

imageFigure 2 – Solution not yet deployed

Click on ife.wsp. And then deploy it to the all content web applications (or perhaps you wish to be selective?)

 imageFigure 3 – Deploy the solution

The web handler has now been deployed to your web farm. The code will now be in the GAC, and the web handler access will be from the 12 hive: TEMPLATE\LAYOUTS\SC\DEMO\SERVICES\IFE.ashx for all websites.

An example URL would be: http://moss/_LAYOUTS/SC/DEMO/SERVICES/IFE.ashx

Create a demo SharePoint site. Create it with one document library and one form library. I used a blank site as the template for this example and did the rest by hand.

My example demo site looks like:

imageFigure 4 – Demo site

I need to reference these URLs later in this working example:

The site URL is:  http://moss/ifetest
Form library URL is: http://moss/ifetest/FormLibrary
Document library URL is: http://moss/ifetest/ExtractedFiles

Now create an InfoPath form…

I used the Asset Tracking example form (as supplied with InfoPath 2007) and slightly modified it to include a file attachment control in the repeating group.

image Figure 5 – updated the Asset Tracking example form to include file attachment

Now modify the submit options for the form by selecting submit options from the tools menu (as shown in Figure 6)

imageFigure 6 – Updating submit options

The IFE handler requires two query string arguments

  • RootGroup = which is the root field in the form. For the asset tracking example, this is ‘assetTracking’
  • IFEGroup = which is the root field for the IFE configuration fields. In this worked example, I am going to call this root field ‘IFE’.

This means the HTTP submission will look like: http://moss/_LAYOUTS/SC/DEMO/SERVICES/IFE.ashx?RootGroup=assetTracking&IFEGroup=IFE

Now we need to set up the configuration fields in the InfoPath form. Create a new group. As shown in Figure 7.  We call this IFE, as this is how we defined it in the query string.

image Figure 7 – Creating IFE group of field for configuration of the web handler.

In this group we now need to set up a number of fields. These fields should match those in your configuration. The ones here are only set to match my server.

  • SiteURL – SharePoint Site URL
    image
  • FormLibraryURL – InfoPath form library URL
    image
  • DocumentLibraryURL – SharePoint Document library URL
    image
  • DocumentLibraryFolder – the folder inside the document library where extracted files will go (I’ve concatenated two fields together from the Asset Tracking form)
    image
  • InfoPathSaveAsFileName – the name that the form will be called (I’ve concatenated two fields together, and added ‘.xml’ to the end for it to be a valid InfoPath filename.
    image
  • OverwriteFiles – whether the handler should overwrite existing files if they have the same name. This is a boolean string {“True” or “False”}.
    image

You then set the value by setting the ‘default value’ on the InfoPath forms. Fields such as DocumentLibraryFolder and InfoPathSaveAsFileName should be dynamically driven by content on the InfoPath form, as shown above.

You should now have a InfoPath data source like this:image
Figure 8 – The asset tracking Form, with the configuration fields in place

You can now demo this setup by previewing the form.

imageFigure 9 – Preview the form

Enter a name, and department (since these a now required to produce the folder and InfoPath save filename). Add an asset with a file attachment, and hit the submit button, as shown in figure 10.

image  
Figure 10 – form filled in

When submit is hit, you may get a security warning. Hit ‘Yes’ to continue if you do.

imageFigure 11 – Ignore the security warning

When the form is submitted, you should see a dialog like the one in Figure 12.

 image
Figure 12 – successful submission dialog

If you select the ‘Show Details’ button, you will see feedback messages from the web handler. As shown in Figure 13.

image
Figure 13 - Feedback window

Now lets see if it worked!

The form library should have updated with the new form, and the document library should have a new folder, and an extracted file!

image

Figure 14 – Form library will our new form!

image
Figure 15 – Document library with new folder

image
Figure 16 – Extracted document now exists in the folder

In order for forms to be updated from the form library, we now need to publish it to the Form Library in the standard way.

image
Figure 17 – Publish the form to the Form Library

We can now click on the form we created earlier to reveal the attachments have been replaced with URL files.

image 
Figure 18 – click on form in form library

image
Figure 19 – Document has been replaced with a link to the document in the Document Library!!!

The web handler will handle updates to this form by ignoring the already converted attachments, meaning we have created a self managing solution that will stop the InfoPath forms from becoming an unmanageable size, and we don’t even have to train the users to write code behind their forms!

Lets update the form with a few more different attached files.

image
Figure 20 - Adding more assets to the asset tracking form means more opportunities to add file attachments

And the Document Library now looks like:

image
Figure 21 – more extracted files

OK, so you now want to give it a go for yourself:

Download the source code: here.

If you do use this in your production environment, or make improvements/modifications to it, I’d like to hear from you! Also, please credit my involvement if it has saved you time, money or effort :-)

I make it available free of charge, with no warranty provided or implied. If you can’t work out how to build/deploy it, please ask on the various forums around the internet – I am not a SharePoint complete beginner support service :-D

Enjoy.

SC



InfoPath and SharePoint verses ASP.NET and a Traditional Database verses ASP.NET and using SharePoint as a database technology

I was recently asked by a colleague

“I’ve got to build a new application to support x (an anonymous set of requirements that I cannot divulge here!), I’ve not got long to do it, and my developer resources are thin on the ground. I’ve heard you talk about SharePoint and InfoPath, and need to call on your experience, do you think I could develop my application using those two technologies? It requires a complex interface layer and needs to be able to provide neat looking reports.”

Okay I said, I’ll give you my experiences in the form of some potential solutions and potential pros and cons. I realise by posting this I’m likely to anger the gods and provoke some really large debate… but that was my plan all along :-)

 

So your decision basically is between three development strategies/options

  1. InfoPath and SharePoint 2007 (MOSS)
  2. ASP.NET and MOSS
  3. ASP.NET and SQL Server 2005

This means the first step is to consider the requirements for the interface layer (IL)… ask yourself: will the user want to do anything fancy on the front end? e.g. sorting data grids, combo boxes, interface with external system. If the answer to that is yes, then you’ll probably want to consider an ASP.NET front end.

If the user really only requires a simple form, then InfoPath is a good choice for the IL… but to make the waters even more murky you’ll need to consider the storage/reporting requirements as InfoPath on it’s own will only offer XML based storage, either on disk, email or SharePoint forms library. ASP.NET forms are more flexible and can enable you to store the data in a SharePoint list, database or if you really wanted, and XML file.

InfoPath pros and cons
Pros

  • Forms can be produced by pretty much anyone with no training
  • Simple to build prototypes (quick and cheap)
  • Easy for user’s to use and understand
  • Allows offline editing (by saving the form to local hard drive)
  • Doesn’t need to be designed in detail before development can be started

Cons

  • Which version of InfoPath does your corporate desktop/laptop build support? InfoPath 2003 is getting a little tired now (this means it’s old, and wont support newer controls, and will limit the ‘code behind’ that you can produce)
  • InfoPath does not allow you to build flexible, custom interfaces
  • Can’t reuse rules from other forms without having to recreate them
  • Rules are difficult to navigate/debug
  • Difficult to migrate (without reworking the forms)
  • If used in conjunction with an SharePoint form library, the coupling is very tight, so if you move the site/rename it you might have to alter the form

ASP.NET pros and cons
Pros

  • Can do whatever you like (within reason) as you have access to .NET 3.5. [this includes things like sending email etc.]
  • Can produce flexible interfaces
  • Easy to debug using Visual Studio
  • Can reuse code and layouts using classes and master pages
  • Can interface with SharePoint, SQL Server, Oracle, XML and lots of other ODBC compliant technologies

Cons

  • Requires that the developers have ASP.NET training
  • Prototypes take longer to build than in InfoPath
  • Does not allow offline use, without extensive development of a side by side offline system
  • Users may require training if something is ’specialised’
  • You need to design the pages (if you want a sensible solution)

You can also have a read of my blog: http://blog.mgallen.com/?p=206, where I’ve linked to Jason Apergis’ blog who explains the pros and cons in a workflow context, but he decides that InfoPath is better for his organisation.

Now you can compare traditional databases and SharePoint

SharePoint pros and cons
Pros

  • Easy to build sites and site collections (quick and cheapish)
  • Has plethora of web parts that can be dragged and dropped by novice users to create dynamic content
  • Links well with InfoPath
  • List items can be produced via MOSS API and Web Services from other technologies such as ASP.NET
  • Sites can be generated through the MOSS API
  • Does rudimentary version control (albeit not in the best possible way… perhaps this isn’t a pro after all :-))
  • Can create production level sites/storage facilities without a detailed design

Cons

  • It should not be used like a traditional database (… and can’t really be used like one either as it can’t do joins between lists)
  • Difficult to report from MOSS lists and libraries, although you can used Reporting Services to query lists it is generally more difficult compared to SQL queries
  • Uses lots of hard drive space (the MOSS database grows quite large)
  • It is not straight forward to migrate from a dev environment to a live environment

Traditional Database (e.g. SQL Server 2005)
Pros

  • Very flexible
  • Can use proper joins, sorts
  • Links very well with Reporting Services to produce powerful outputs
  • Links very well with ASP.NET and other .NET technologies

Cons

  • Requires a detailed design (or not… but don’t do that to yourself!)
  • Can’t be used directly with InfoPath
  • Requires a production and dev server in an ideal world

Okay, so if you read between the lines… I think you should go for options 2 or 3… preferably 3.

The perception is that as its quick and cheap to use InfoPath and SharePoint… and that perception is right 90% of the way…. You’ll find that once you’ve done 90%… The last 10% will take you an absolute age, and will probably consist of workarounds, squirming out of meeting requirements and swearing at the computer.

The decision is yours, so be pragmatic, and assess the requirements in front of you, and ask difficult questions to try to ascertain whether any potential requirements creep puts you in the ASP.NET frame or the InfoPath frame. If reporting is a major player, I would urge you to think about using SQL Server and Reporting Services.

I hope this has helped you a little bit anyway, good luck :-)

SpittingCAML



K2 [BlackPoint] - A simple meeting agenda review process in InfoPath… that can even store the completed InfoPath form

Well, I say simple… It is simple to me, as I’ve knocked it up using the Meeting Agenda template (free with InfoPath 2007) with a slight addition of a task action field, and I’ve then knocked together a simple approval and rework based workflow.

k2blackpointdemoprocess_001 
Figure 1: The finished workflow (I’m not going to teach you guys how to suck eggs by going through the creation of it… unless you’d like me too … another time perhaps?)

Figure 1 shows the finished article… I’m not suggesting that this is perfect example of an approval and rework workflow…  it is simply here to demonstrate a point.

k2blackpointdemoprocess_002
Figure 2: Destination Form Library for the creation of the InfoPath form that starts the workflow

I’m using a standard MOSS 2007 form library to store my InfoPath forms as shown in Figure 2. When ‘New’ is clicked, you see Figure 3.

k2blackpointdemoprocess_003
Figure 3: The InfoPath form created when ‘New’ is clicked in Form Library (FormLibrary001)

k2blackpointdemoprocess_004  
Figure 4: The K2 Worklist (which just happens to be in the Process Portal (K2 Management)) showing the new task for destination user ‘Administrator’

As you can see in Figure 4, a task is added to the administrator user task list.

k2blackpointdemoprocess_005 
Figure 5: Clicking on Open will take the user back into InfoPath, or the Actions option will allow the user to action the task bypassing InfoPath - this might be useful if you want people to bulk action things. In this example I should really disallow this option. You can do this as part of the InfoPath client event outcomes.

k2blackpointdemoprocess_006
Figure 6: Shows the opening of the InfoPath form from the K2 BlackPoint runtime services… I’ve configured this on port 8080 (just so you know). This gives me a clue that unlike K2 BlackPearl, InfoPath forms only exist in K2 Server, and not in the form library… which confused me somewhat… or perhaps I’ve got the wrong end of the stick on that.

k2blackpointdemoprocess_007 
Figure 7:  User is able to select an outcome from the task action field as you’d expect

k2blackpointdemoprocess_008
Figure 8: Shows the final resting place of the InfoPath form - this is because of the SharePoint document event I placed in the final activity. I assumed the form would be saved by default, but it doesn’t seem to work that way… but it certainly did in K2 BlackPearl.

So how did I get the InfoPath form to be stored in the Library at the end… well the next screen shots and explanations will tell you how! I must admit, I thought it would do this automatically, but both the Beta 2 and RC versions of K2 [BlackPoint] behave in this way…

As you may have noticed in Figure 1, I added a SharePoint document event to the end of my workflow. This is also shown in Figure 9.

k2blackpointdemoprocess_009
Figure 9: Shows the SharePoint document event on the final activity that saves the InfoPath form. I’m using the Upload Document Event Action.

k2blackpointdemoprocess_010
Figure 10: Shows that I’m going to be creating this uploaded file from a K2 Field. This is very important, as K2 BlackPoint is now being told that the file stream is not from a disk, but from the database

k2blackpointdemoprocess_011
Figure 11: When selecting the K2 Field, be sure to select the Root node of your InfoPath form. The Root node will be the name of your Template (in most cases). My Template XSN was called MeetingAgenda001.xsn before it was integrated into the workflow.

k2blackpointdemoprocess_012
Figure 12: I am building the Filename of the output file using the meetingTitle field from my InfoPath template

k2blackpointdemoprocess_013
Figure 13: To ensure an unique filename, I utilise the Process Instance ID

k2blackpointdemoprocess_014
Figure 14: Be sure to space out your dynamic fields, I’ve used a hyphen. Also be sure to add the extension to the end. For InfoPath, the extension required is ‘.xml’ (well, of course it is!)… You then end up with files named like they are shown in Figure 8

Of course, you may not have to do all this stuff… I might have an incorrectly set-up version of K2 [BlackPoint], but thinking about it, it does make sense to me.

  1. InfoPath forms are ‘protected’ from unauthorised modification as they are stored in the database
  2. InfoPath forms are only stored in the library when they are in a complete state (because you decided when they would be stored!)

This is definitely an improvement on how BlackPearl handles them, as they are editable (through other means… e.g. text editor) when they are mid workflow, and it was a concern of the customer.

Anyways, I hope this helps others understand how to do this sort of thing. Post a comment if you want more explanation on anything, but of course, check out K2 Underground first!

SpittingCAML



InfoPath, K2 InfoPath or ASP.NET as your workflow forms technology?

Jason Apergis has done an excellent comparison on his blog: here

In my organisation we hit the limits with InfoPath 2003 pretty soon after starting to use it with K2 Workflows, mainly because of complicated user requirements that could not be implemented using InfoPath due to the lack of ability to code behind it and control every aspect of the form… K2 InfoPath brings in the tightly coupled SmartObject integration that creates a rule for each SmartObject method…. this is a real nightmare when you have ten or more of them to manage…. and then there’s the rules that go with them, that you can only edit by clicking through each one. I know which platform I’d choose, for my development team’s sanity! ASP.NET

Still, have a read of Jason’s blog, he’s opted for InfoPath as his organisation are very comfortable with using it.

SpittingCAML



Modifying the contents of a SmartObject using the SmartObject event, and then loading the SmartObject into InfoPath

This blog post is really a little tutorial that I’ve been working on to help people understand how to utilise SmartObjects as part of their InfoPath forms. I, like many, just think it’s more logical to store data in the SQL database (SmartBox) rather than to store it as XML (in the InfoPath form itself. This tutorial should help you get an idea of how to use SmartObjects to persist your data, while keeping the familiar InfoPath front end for your users.

First you need to create your SmartObjects using the Visual Studio SmartObject project. This tutorial wont cover that as it’s covered in the K2 [blackpearl] 101 guides. Make sure that when you do create them that you give them a Load and Save method in order to follow what I’ve done here.

tutorial1
Figure 1: K2 [blackpearl] SmartObject Event wizard

Figure 1 shows a SmartObject event wizard. I am using this wizard to set some values of the SmartObject. I will be calling the ‘Save’ method of my SmartObject ‘cmmiDocumentDetail’.

tutorial2
Figure 2: K2 [blackpearl] SmartObject Event wizard (2) 

Figure 2 shows the values of my SmartObject that I will be populating outside of InfoPath. I’m populating ‘currentAuthor’ with the Activity Instance Destination User (how to get this particular value is explained on this blog too :-)) and current role with a string "Review" and the ‘documentAutoNumber’ with a value from a previous InfoPath form. Populating this field is a key requirement, as this is the index of my SmartObject. If you do this sort of thing you will need to populate this value to make sure you are updating the correct instance of your SmartObject.

tutorial3
Figure 3: K2 [blackpearl] InfoPath Integration wizard

If you haven’t already done so, integrate your SmartObjects with your InfoPath form using the edit mode provided by the InfoPath integration mode. You may encounter issues if you’ve added your own datasources before integrating your SmartObjects. See K2 Underground. After you’ve integrated each of the SmartObject methods that you want to use (Yes, you need to integrate each method separately!) you can carry on with this tutorial.

Figure 3 shows the ‘design’ mode that you will need to enter in order to make any changes to an InfoPath form that is already integrated with your workflow. You really shouldn’t modify the InfoPath form outside of Visual Studio once you’ve integrated… it’s just not worth the risk ;-).

tutorial4
Figure 4: InfoPath form options selection

Figure 4 shows the form options mode that we’ll need to go into in order to invoke the SmartObject methods that we will require.

tutorial5
Figure 5: InfoPath open and save rules selection

Figure 5 shows the open and save rules that we need to get to to invoke the SmartObject methods on form load event.

tutorial6
Figure 6: InfoPath open and save rules

You’ll now need to add an action to invoke the load method of your SmartObject. If you require to load multiple SmartObjects you’ll need to add actions for each one separately. Figure 6 shows two Queries, one a ‘Get List’ and one a Load method on two separate SmartObjects. If you invoke a SmartObject method that has an input parameter, you’ll need to add another action that sets a field value on the relevant data source (See Figure 7 below)

tutorial7
Figure 7: InfoPath data source window showing the load method and it’s required input 

Figure 7 shows a required input parameter to the load method. This is the field that you will need to set before you query the SmartObject. If you look at Figure 6, you’ll see that I set ‘docAutoNumber’ to be equal to a value before I invoke the Query. This is important as the SmartObject method will error if no input parameter is provided.

Now that you know that when the form opens you will be automatically executing the SmartObject methods you can set about assigning your SmartObjects to controls on your InfoPath form.

tutorial8
Figure 8: InfoPath data source window showing the return values for the load method 

Figure 8 shows the set of values that can be bound to existing InfoPath controls or dragged and dropped onto your InfoPath form to automatically create controls. Once controls are bound or created you need to ensure you call the ‘Save’ method on your SmartObjects.

tutorial9
Figure 9: InfoPath submit rule options

Figure 9 shows a rule that is executed on form submit that calls the Save method on my SmartObjects. ‘Set Workflow Task Action 1′ and ‘Submit Workflow’ are automatically added by K2 [blackpearl] when you have performed a K2 [blackpearl] InfoPath integration wizard.

I know this is sparse in places… but I hope it helps some of you.

SpittingCAML



Setting an InfoPath field value outside of InfoPath in a K2 [blackpearl] workflow

The following code shows how to set an XML field on an InfoPath form in a server code event. The example uses ’smartObjectID’ as the variable that I am using as the input to the InfoPath field. ‘form2Name’ is the name of the InfoPath form as it appears in the K2 Object Browser in Visual Studio. ‘hiddenSmartObjectID’ is the name of the text box control that I’ve placed on my InfoPath form. Once the code has completed execution, the form form will load with the value already set allowing the utilisation of it at a later time in the workflow.

This is useful when you are providing more than one form to the user via Infopath client events, and the data needs to be linked in some way.

smartObjectID =
    <whatever value you need from either K2 or previous forms> 

// we need to get the xml from the K2 state datastring k2xmlString =
    K2.ProcessInstance.XmlFields["form2Name"]    .Value.ToString();

// get stuff from form2
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(k2xmlString);

// create a namespace manager for InfoPath
XmlNamespaceManager nsMgr =
    new XmlNamespaceManager(xmlDoc.NameTable);
nsMgr.AddNamespace("my",
    xmlDoc.DocumentElement.GetNamespaceOfPrefix("my"));

// set the value of a hidden field to be equal to the id 
// required for retrieving the correct smartobject
// NOTE: I've got a hidden text box on my infopath form
// called 'hiddenSmartObjectID' that I'll be using later
xmlDoc.SelectSingleNode
    ("//my:Form2Fields/my:hiddenSmartObjectID", nsMgr).Value =
          smartObjectID;

//Now set the value back into the XML Field
K2.ProcessInstance.XmlFields["form2Name"].Value =
     xmlDoc.OuterXml;

Let me know how you get on with this. :-D

SpittingCAML



Disabled File Name entry

You may wonder when and how the file name options are ever disabled. Well I found one special case when you cannot specify a file name - when you upload from an XML attachment (InfoPath attached document field)

 
Figure 1: SharePoint Upload Documents (from XML attachment) wizard


Figure 2: Document destination page, with disabled file name edit control

Here’s the proof

SpittingCAML



Getting the file name of an InfoPath attachment

There will be a time, let me tell you :-) that you’ll want or need the file name of the document that one of your users has attached to your InfoPath form.

You’d think that this functionality would come out of the box… but no!

There’s no easy way of doing this, as I’ve had to knock up some simple C# code to go behind my InfoPath forms. See below:

 
    // THIS IS A FUNCTION I HAVE CREATED MANUALLY
    public void RetrieveFilename()
    {
        try
        {
            // TODO: Verify correct XPath for this InfoPath form
            IXMLDOMNode opnXN =
              thisXDocument.DOM.
                 selectSingleNode("/my:myFields/my:attachedDoc");

            byte[] attachmentNodeBytes =
               Convert.FromBase64String(opnXN.nodeTypedValue
                   .ToString());

            // Position 20 contains a DWORD indicating the length of the
            // filename buffer. The filename is stored as Unicode so the
            // length is multiplied by 2.

            int fnLength = attachmentNodeBytes[20] * 2;
            byte[] fnBytes =new byte[fnLength];

            // The actual filename starts at position 24 . . . 
            for (int i = 0; i < fnBytes.Length; i++)
            {
                fnBytes[i] = attachmentNodeBytes[24 + i];
            }

            // Convert the filename bytes to a string. The string 
            // terminates with \0 so the actual filename is the 
            // original filename minus the last character ! 

            char[] charFileName =
                System.Text.UnicodeEncoding.Unicode.GetChars(fnBytes);
            string fileName =new string(charFileName);
            fileName = fileName.Substring(0, fileName.Length - 1);        

            // TODO: Verify correct XPath for this InfoPath form
            thisXDocument.DOM.
                selectSingleNode("/my:myFields/my:docOSFileName").text
                = fileName;

            /*
            // USE THIS CODE TO UPLOAD TO A SHAREPOINT LIBRARY
            // The file is located after the header, which is 24 bytes
            // plus the length of the filename. 
            byte[] fileContents = 
             new byte[attachmentNodeBytes.Length - (24 + fnLength)];
 
            for (int i = 0; i < fileContents.Length; ++i)
            {
            fileContents[i] = attachmentNodeBytes[24 + fnLength + i];
            }

         
            // TODO: Add correct MOSS site URL
            string SiteURL = "http://my/sites/newse/newdoclib/" 
               + fileName;
            SPWeb site = new SPSite(SiteURL).OpenWeb();
            site.Files.Add(SiteURL, fileContents);

            //END OF COMMENTED OUT SECTION
            */

        }
        catch (Exception e)// TODO: Write better error handler
        {
            System.Diagnostics.Debug.WriteLine(e.ToString());
        }
    }

        // THIS FUNCTION IS GENERATED BY INFOPATH
        // The following function handler is created by Microsoft Office. 
        // Do not modify the type or number of arguments.
        [InfoPathEventHandler(MatchPath = "/my:myFields/my:attachedDoc",
           EventType = InfoPathEventType.OnAfterChange)]
        public void attachedDoc_OnAfterChange(DataDOMEvent e)
        {
            // Write your code here to restore the global state.

            if (e.IsUndoRedo)
            {
                // An undo or redo operation has occurred 
                // and the DOM is read-only.
                return;
            }

            // A field change has occurred and the DOM is writable.
            // Write your code here.
            RetrieveFilename();
        }

Thanks should go to Pranab Paul for providing me the initial idea for this code snippet. Also note that you’ll need to add the various using statements for the XPath and XML classes to be available.

SpittingCAML



K2 [blackpearl] InfoPath Integration

My organisation likes InfoPath, as it is available on everyone’s client machine (Corporate Office 2003) it makes it a useful tool for filling in forms and the like.

I’ve been trying (and failing) to use InfoPath to enable users to upload a document (e.g. Excel, PowerPoint, Word or even CAD drawings etc.) and coax them into filling in some metadata as part of the process.


Figure 1: The InfoPath form in question

Figure 1 shows the first knockup of the type of form the management will be expecting the users to be filling in.

K2 [blackpearl] however, seems to have other ideas… K2 [blackpearl] allows me to specify a ‘K2 field’ which in this case is an InfoPath field containing the Unicode attachment [the document], and it will enable me to be uploaded to a SharePoint library without having to write any code!


Figure 2: The K2 [blackpearl] SharePoint documents wizard 

My workflow is started when the user submits the form shown in Figure 1 and Figure 3 in action. It is then supposed to take the attachment and add it to a SharePoint document library.


Figure 3: A user filling in my form and attaching a document


Figure 4: The error message! 

I am however, greeted with an error in my error log as shown in Figure 4.

I have no idea why it thinks my path is too long, or what I could have done to cause it to create this error message. Does anyone out there know what could cause this?

I’ll keep playing, and submit a support ticket with K2

SpittingCAML




You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.