John Liu .NET

View Original

Automatic Relink InfoPath Forms Event Receiver

I’ve been working on an InfoPath solution that requires both Offline and Online capabilities.

Problem and Background

An InfoPath form has two components – the XML describing the data in the form, and the template, describing the layout of the form.

In the Offline scenario, when a user opens an InfoPath form – it looks for a template definition that’s stored offline (in a file server). 

In the Online scenario via Forms Services, the Form template is stored in SharePoint (as the template of a document library / content type).  InfoPath Forms Services then renders the form as a web page to the user.

In the MIXED scenario, where you fill out a form offline, then submit and store it Online, we have a situation where the Offline form is submitted to the Forms Library, but it still wants the template that’s stored in the Network Share.

Manual Solution

SharePoint provides a manual solution, in the form of a Relink page that’s available on all Form Libraries. 

image

Figure: Form2’s template link is still pointing to the file system.  Not SharePoint.

Select and choose Relink from the Ribbon to fix this.

image

 

The Automatic Way…

 

Enter the SharePoint Gurus Relink Forms Template sandbox solution.

The idea is simple:

  1. Build an Event Receiver, listen to Add/Update events on the Forms Library. 
  2. Fix the form’s template URL to that of the Form library.
  3. Bonus: Sandbox solution so you don’t need to be administrator.

 

Installation:

  1. Grab SharePoint Gurus Relink Forms Template sandbox solution
  2. Upload to Solutions Gallery

    image

  3. Activate Sandbox Solution
  4. Activate Web Feature

    image

Test

 

Upload files to Forms Library

image

Fixed!

 

Code Below

 

public override void ItemAdding(SPItemEventProperties properties)
{
    base.EventFiringEnabled = false;
    RelinkFormTemplate(properties);
    base.ItemAdding(properties);
}


public override void ItemUpdating(SPItemEventProperties properties)
{
    base.EventFiringEnabled = false;
    RelinkFormTemplate(properties);
    base.ItemUpdating(properties);
}
private string GetTemplateURL(SPContentTypeId contentTypeId, SPList spList, SPWeb spWeb, string strSolutionURL)
{
    // this code is mostly modified from Microsoft.SharePoint.ApplicationPages.SubmitRepair, repackaged as an Event Receiver

    SPContentType type = spList.ContentTypes[contentTypeId];
    if (type == null)
    {
        return strSolutionURL;
    }
    string documentTemplate = type.DocumentTemplate;
    if (documentTemplate.StartsWith("http://", StringComparison.Ordinal) ||
documentTemplate.StartsWith("https://", StringComparison.Ordinal))
    {
        return SPHttpUtility.UrlPathEncode(documentTemplate, true);
    }
    if (documentTemplate.StartsWith("/", StringComparison.Ordinal))
    {
        return SPHttpUtility.UrlPathEncode(spWeb.Site.MakeFullUrl(documentTemplate), true);
    }
    return SPHttpUtility.UrlPathEncode(spWeb.Url + '/' + spList.RootFolder + '/' + documentTemplate, true);
}

public void RelinkFormTemplate(SPItemEventProperties properties)
{
    // this code is mostly modified from Microsoft.SharePoint.ApplicationPages.SubmitRepair, repackaged as an Event Receiver

    SPList spList = properties.List;
    object property = properties.AfterProperties["ContentTypeId"];
    if (property == null)
    {
        // publishing template from InfoPath?
        return;
    }
    string contentTypeId = property.ToString();

    SPWeb spWeb = properties.Web;
    SPDocumentLibrary spLibrary = (SPDocumentLibrary)spList;
    string strSolutionURL = SPHttpUtility.UrlPathEncode(spWeb.Url + "/" + spLibrary.DocumentTemplateUrl, true);

    string newTemplateUrl = this.GetTemplateURL(new SPContentTypeId(contentTypeId), spList, spWeb, strSolutionURL);
    if ((properties.AfterProperties["TemplateUrl"] != null) &&
(!string.Equals(newTemplateUrl, properties.AfterProperties["TemplateUrl"].ToString(), StringComparison.CurrentCultureIgnoreCase)))
    {
        properties.AfterProperties["TemplateUrl"] = newTemplateUrl;
    }
}