Pass in any parameter to an InfoPath form with one piece of code

One thing that’s lacking in Microsoft InfoPath 2007 is the ability to simply map input parameters to the main data source (which is most likely where you want them to go). 

Unfortunately there’s no getting around the need to write code to ‘receive’ your input parameters, but with a thought you’ll be able to pass
in parameters with the same name as the fields in your form and have one block of code to paste into the code behind all forms – that will work for all. 

This includes a couple of utility functions that make life a bit easier when coding around fields in the form.
The ‘DeleteSelf’ line around the nil attribute is something that apparently gets around data type errors if you’ve got fields that aren’t just ‘string’ – e.g. ‘number’ etc.  I found this worked in the InfoPath client, but not in a browser (and had to change my field data type back to string, and add some regexp validation).

        public void FormEvents_Loading(object sender, LoadingEventArgs e)
        {

            //Try and identify any input parameters and put them into their requisite places in the main data source
            foreach (string parameter in e.InputParameters.Keys)
            {

                //Try and find in the main data source, then set the value
                XPathNavigator formNode = SelectSingleNode(String.Format("//my:{0}", parameter));
                if (formNode != null)
                {
                    if (formNode.MoveToAttribute("nil", "http://www.w3.org/2001/XMLSchema-instance"))
                        formNode.DeleteSelf();

                    formNode = SelectSingleNode(String.Format("//my:{0}", parameter));
                    formNode.SetValue(e.InputParameters[parameter]);
                }
            }
        }
        
        /// <summary>
        /// Select a single node from the Main data Source
        /// </summary>
        /// <param name="xpath"></param>
        /// <returns></returns>
        private XPathNavigator SelectSingleNode(string xpath)
        {
            string ns = LookupNamespace("my");
            XPathNavigator navigator = MainDataSource.CreateNavigator();
            return navigator.SelectSingleNode(xpath, NamespaceManager);
        }
 
 
        private string LookupNamespace(string ns)
        {
            return NamespaceManager.LookupNamespace(ns);
        }

Embedding InfoPath forms in SharePoint WebPart pages using the XmlFormView control

I recently needed to take a simple InfoPath form and surface that through a ‘themed’ SharePoint page.  It’s possible to load the form in a browser without needing a specific page, but this effectively eliminates your master page from the equation.

Nick Grattan wrote an excellent paper on using the XmlFormView control to contain InfoPath forms on SharePoint webpart pages.

This is all great until you then need to send in input parameters to the form.  I looked around for quite a while before I found the (rather obvious) Initialize event allows you to set the Input parameters of the form.  All other methods of loading the form (InfoPath client, FormServer.aspx) use a querystring-style format.

The following code should do the trick in the case where you’re passing information from a current ‘list item’ to the form:
 

    private SPList requestList = null;
    private int requestID;
    private SPListItem currentItem = null;

    protected void Page_Load(object sender, EventArgs e)
    {

        XmlformView1.Initialize    += XmlformView1_Initialize;
        //Get ID and List Item information (passed into this page)
        requestList = SPContext.Current.Web.Lists["My List"];        
        if (requestList != null && Request.QueryString["ID"] != null)
        {
            if (int.TryParse(Request.QueryString["ID"].ToString(), out requestID))
            {
                //Get Item
                currentItem = requestList.GetItemById(requestID);

                if (currentItem == null)
                    throw new ArgumentException("The specified ID does not exist");

            }
            
        }
        
    }

    protected void XmlformView1_Initialize(object sender, InitializeEventArgs e)
    {
        //Set input parameters for embedded Form
        e.InputParameters["foo"] = currentItem["foo"].ToString();
        e.InputParameters["bar"] = currentItem["bar"].ToString();

    }

I discovered that in order to write code in a WebPart page (using SharePoint Designer)
you’ll need to add a PageParserPath to the web.config as follows – otherwise you’ll get an error saying something like ‘code not allowed in this page’.  I’ve got a folder called ‘WebPages’ that houses the page.  The standard web.config already has the PageParserPaths element:

    <SafeMode MaxControls="200" CallStack="true" DirectFileDependencies="10" 
TotalFileDependencies="50" AllowPageLevelTrace="false">
<PageParserPaths>
    <PageParserPath VirtualPath="/WebPages/*" CompilationMode="Always"
AllowServerSideScript="true" IncludeSubFolders="true" />
</PageParserPaths>
</SafeMode>


NOTE:
If you’re showing/hiding the form based on a flag/checkbox etc in the page (I’m doing this), then make sure you wrap the XmlFormView in a container Panel/div that you show/hide server-side, rather than showing/hiding the XmlFormView itself.  For some reason this doesn’t seem to work properly (at least in FireFox).

LINQ to SQL Connection Strings with Class Library and Web.Config

Most Microsoft technologies that you can operate with a GUI come with some tradeoffs.  Things have certainly improved over the years and now something like the LINQ to SQL designer is pretty trouble free – unless of course you have something like this fairly common scenario:

I had a class library (Data Access), and decided to add LINQ to SQL classes for a new database that was being introduced.
This class library is also ultimately being consumed by WCF web services.  I have dev, test, prod environments, so I use ASP.NET Web Deployment projects to change configuration per environment for things like appSettings and connectionStrings.

It therefore followed that I wanted to configure the LINQ DataContext connection properties in web.config.  Out of the box you’ll find your connection properties go into your Settings properties class, which gets a little bit in the way.

If you start playing around with the generated classes to change where you’re getting the connection info from then any changes in the designer will wipe them out, so a (relatively) pain free approach to setting your connection safely is the following:

Go to your LINQ to SQL designer and remove the Connection String, and set Application Settings to False

Create a new partial class to mirror your DataContext, and set the constructor to retrieve from your alternative source…

using System;
using System.Linq;
using System.Configuration;
using System.Data.Linq;

namespace CodeBureau.Services.DataAccess
{
    public partial class MyDataContext : DataContext
    {
        public MyDataContext()
            : base(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString, 
mappingSource) { OnCreated(); } } }

This will leave all your generated code intact, but will sort out your configuration woes.