One of the nice things of being a trainer at Info Support, is that you get the chance to help graduate-students in their final internship. At this moment Mark is working at Info Support building a nice CV solution using MOSS and InfoPath. He encountered a few problems while creating an admin-approved form template.
I asked him to write a blogpost about it, here's what he came up with
Mark:
The usual way to deploy an admin-approved form template is to use "Upload form template" from the 'Central administration – Application Management'. Select the form that you want to upload and activate it to a site collection.
Personally I don't like this way of distributing form templates. It's slow and sometimes you'll have to wait minutes before the new template is available.
Wouldn't it be nice if we can deploy an admin-approved form template as a solution? This way we can install and activate it with stsadm.exe and we'll be able to create an installer for the form template using the SharePoint Solution Installer. Sounds good, doesn't it?
The only problem is that there isn't much information available about this topic. So that's why I started a little research and my findings are posted in this blog.
What really happens when you upload an admin-approved form template
What happens on the background when you upload a form template is that SharePoint creates a solution (.wsp). This solution can be activated on the different site collection. 'Manage Form Templates' takes care of this.
I'll demonstrate how this works.
Upload a Form template and extract the generated solution
I've uploaded a form template called SimpleForm.xsn. Under 'Operation – Solution management' a new solution showed up:
This solution is created by SharePoint. You cannot download the solution by using the web interface, so we'll have to use the object model.
SPFarm farm = SPFarm.Open("Data Source=<YourServer>;Initial Catalog=SharePoint_Config;Integrated Security=SSPI;"); SPSolutionCollection sc = farm.Solutions; foreach (SPSolution so in sc) { SPPersistedFile file = so.SolutionFile; file.SaveAs("C:\" + file.Name); Console.WriteLine(so.Name); } Console.ReadLine();
This little piece of code extracts all the solutions that are stored in the config database of the farm. Now that we have the solutions, let's explore the generated solution.
Explore the generated solution
First of all you have to extract the solution. A .wsp file is just a zip file and you can extract it with your favorit archiver. Once you have extracted the solution, you'll see a manifest file and a directory.
The manifest file doesn't contain anything special, a solution id and the location of feature.xml
Manifest.xml:
<?xml version="1.0" encoding="utf-8" standalone="yes"?> <Solution SolutionId="f425ff7d-f5d3-4b04-b21e-fcc480710672" ResetWebServer="FALSE" >="http://schemas.microsoft.com/sharepoint/"> <FeatureManifests> <FeatureManifestLocation="FT-01-db017eec-9ba7-5863-9727-62c13b2414b5Feature.xml" /> </FeatureManifests> </Solution>
So let's take a look at the feature.xml located in the "FT-01-db017eec-9ba7-5863-9727-62c13b2414b5" directory. The name of this directory is based on the id of the feature.
Feature.xml:
<?xml version="1.0" encoding="utf-8" standalone="yes"?> <Feature Id="db017eec-9ba7-5863-9727-62c13b2414b5" Title="SimpleForm" Description="$Resources:ipfscore,XsnFeatureDescription;" Version="1.0.0.0" Scope="Site" DefaultResourceFile="ipfscore" ReceiverClass="Microsoft.Office.InfoPath.Server.Administration.XsnFeatureReceiver" ReceiverAssembly="Microsoft.Office.InfoPath.Server, Version=12.0.0.0, Culture=neutral,PublicKeyToken=71e9bce111e9429c" >="http://schemas.microsoft.com/sharepoint/"> <ElementManifests> <ElementManifest Location="Elements.xml" /> <ElementFile Location="solution.xsn.1.0.0.3SimpleForm.dll" /> <ElementFile Location="solution.xsn" /> <ElementFile Location="solution.xsn.1.0.0.3solution.xsn" /> </ElementManifests> <Properties> <Property Key="FeatureName" Value="FT-01-db017eec-9ba7-5863-9727-62c13b2414b5" /> <Property Key="OriginalFileName" Value="SimpleForm.xsn" /> </Properties> <ActivationDependencies> <ActivationDependency FeatureId="C88C4FF1-DBF5-4649-AD9F-C6C426EBCBF5" /> </ActivationDependencies> </Feature>
There are some special elements in the file:
- Description="$Resources:ipfscore,XsnFeatureDescription;"
A reference to the description in the Form Template. You are free to place your own description - DefaultResourceFile="ipfscore"
ipfscore stands for InfoPath Form Services Core. This attribute isn't required. - ReceiverClass="Microsoft.Office.InfoPath.Server.Administration.XsnFeatureReceiver" ReceiverAssembly="Microsoft.Office.InfoPath.Server, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
XsnFeatureReceiver is based on the SPFeatureReceiver class and used to trap the activation, deactivation, installation, or uninstallation of a SharePoint feature containing an InfoPath form template. For more information see: http://msdn2.microsoft.com/en-us/library/microsoft.office.infopath.server.administration.xsnfeaturereceiver.aspx - <ElementManifests>
Contains the links to the InfoPath files. There are two .xsn files defined. This is done for versioning. A form template can be upgraded by using the Upload Form function. The .xsn file in the root directory of the feature is the current version, the older versions are in subdirectories. The older versions are saved for backward compatibilty with already filled in forms (.xml) that still use an older form template version. - <ActivationDependencies>
The feature needs the XsnFeatureReceiver. This is the feature id of the receiver.
The only file left is Elements.xml
Elements.xml:
<Elements >="http://schemas.microsoft.com/sharepoint/"> <Module Name="XSN" Url="FormServerTemplates" RootWebOnly="TRUE"> <File Url="solution.xsn" Name="SimpleForm.xsn" Type="GhostableInLibrary"/> </Module> </Elements>
Nothing special here, except the url. Every sitecollection has a Form Template library: http://<server>/<sitecollection>/FormServerTemplates/. So when the feature is activated on a site collection, the form template will be saved in this library.
Something to notice is that there aren't any columns defined. When you design your form template you can chose fields that will be used as colums within Sharepoint or Outlook folders. So how does Sharepoint know if it should add extra columns? Well, XsnFeatureReceiver will take care of that.
Conclusion
With this information it's possible to create your own form template from scratch and deploy/activate it with stsadm.exe.
2 comments
Is there any way to specify the ID of the Content Type generated but the XsnFeatureReceiver class? I need to design in schema.xml that reference fields that will be promoted from the form template…
string fakeEmail = “jim.spam.duncan%sharesquared.spam.com”;
string realEmail = fakeEmail.Replace(“%”, “@”).Replace(“.spam”,””);
Thanks!
Jim Duncan
Hi,
In your element manifest, you define SimpleForm.dll. What’s this for? I thought the dll should be embedded in the xsn, although it’s not working if I dont have the dll in my feature folder
Thanks
Rob
Rob Nowik