Use dynamically created InfoPath form instance to pre-fill form


If you want to pre-fill InfoPath form before user gets his/her hands to it... you have two ways to do that:

  1. Call Web Services from InfoPath
    • It normally takes quite long
  2. Dynamically create InfoPath form instance
    • Fast and there isn't any limitations where to get data

Both methods have been mentioned many times in different sites but I still decided to create a demo about the "Dynamically create InfoPath form instance" to make this crystal clear... and give some code to get you started on this if you're interested.

So I created really simple InfoPath Request Form:

I added submit rule to the button (I just used fixed url for the form library).

Then I created following UI for my solution:

Here is the code behind the astonishing UI (a.k.a. button inside web part):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
using System;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using System.Web.UI.WebControls;

namespace InfoPath_Creator
{
  [Guid("16ba4e60-d230-45d3-9966-da959d20a90b")]
  public class InfoPath_Creator : System.Web.UI.WebControls.WebParts.WebPart
  {
    public InfoPath_Creator()
    {
      this.ExportMode = WebPartExportMode.All;
    }

    protected override void CreateChildControls()
    {
      Controls.Clear();
      base.CreateChildControls();
      this.ChildControlsCreated = true;

      Button createRequestForm = new Button();
      createRequestForm.Text = "Create request";
      string url = this.Page.Request.Url.ToString();
      if (url.IndexOf('?') == -1)
      {
        url += "?";
      }
      else
      {
        url += "&";
      }
      url += "CreateRequest=true";

      createRequestForm.OnClientClick = "document.location.href='" + url + "'; return false;";
      this.Controls.Add(createRequestForm);
    }

    protected override void Render(HtmlTextWriter writer)
    {
      this.RenderChildren(writer);

      if (string.IsNullOrEmpty(this.Page.Request["CreateRequest"]) == false)
      {
        string requestType = "Request for dynamic request forms";
        string requestTitle = "My dynamically created request";
        string estimatedCost = "123";
        string user = SPContext.Current.Web.CurrentUser.Name;
        string costCenter = "999888777"; // TODO: get cost center from UserProfile
        int classification = 54321;

        string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
          "<?mso-infoPathSolution solutionVersion=\"1.0.0.8\" productVersion=\"12.0.0\" " + 
          "PIVersion=\"1.0.0.0\" href=\"" + 
          "http://demo1:1000/PressReleases/Request%20forms/Forms/template.xsn\" " +
          "name=\"urn:schemas-microsoft-com:office:infopath:" +
          "Request-forms:-myXSD-2007-11-07T19-32-12\" ?>" +
          "<?mso-application progid=\"InfoPath.Document\" " +
          "versionProgid=\"InfoPath.Document.2\"?>" + 
          "<my:myFields xmlns:my=\"" +
          "http://schemas.microsoft.com/office/infopath/2003/myXSD/2007-11-07T19:32:12\" " +
          "xml:lang=\"en-us\">" +
          // Here I fill the fields:
          "<my:RequestType>" + requestType + "</my:RequestType>" +
          "<my:RequestTitle>" + requestTitle + "</my:RequestTitle>" +
          "<my:EstimatedCost>" + estimatedCost + "</my:EstimatedCost>" + 
          "<my:User>" + user+ "</my:User>" + 
          "<my:CostCenter>" + costCenter + "</my:CostCenter>" + 
          "<my:Classification xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + 
          classification + "</my:Classification>" +
          "</my:myFields>";
        this.Page.Response.Clear();
        this.Page.Response.AppendHeader("Content-Disposition", "attachment;filename=Request-" + 
          DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") );
        this.Page.Response.ContentType = "application/ms-infopath.xml";
        this.Page.Response.Write(xml);
        this.Page.Response.Flush();
        this.Page.Response.End();
      }
    }
  }
}

In lines 54 to 73 I created the XML for the form (it looks like real mess and I'm sorry about it!). Most important stuff happens between lines 66 and 72 where the actual field values are stored. Of course you could use some magic code to get the correct values to the variable at lines 47 - 52. And you can also probably see the URL of the XSN file (line 57) and as well as the namespace (line 63). It looks like this when user clicks the Create request button:

And when user presses the button in InfoPath the form data is submitted to the form library:

So hopefully after this post you'll remember that this method is powerful (and not the messy XML πŸ™‚ if you want fill InfoPath with data. You have much more possibilities than just simple web service request in InfoPath.

By the way... Why do I always end up with titles with word "dynamic*" in it πŸ™‚ (see my previous post for example)

Anyways... Happy hacking!

J

Comments (10)

  1. Jari says:

    Nice post.. but in a real world you probably want to publish the infopath form to MOSS more than once. With each publish the timestamp in the namespace changes, doesn’t it?

    So, is there a nice way to retreive the new namespace, other than blowing up the xsn-file and start digging?

    It would be cleaner to retrieve an empty form from Forms Services with correct namespace and everything. But how can I do that in code?

  2. Hi Jari!

    If you do it the correct way => don’t start from InfoPath πŸ™‚ Then you actually define your namespace yourself. The problem is that people normally start by launching InfoPath… and don’t think about the schema. But you should first create schema and then start building your form on top of it. Then your namespace stays as you have defined.

    Anyways… Happy hacking!

    J

  3. Jari says:

    Hmm.. you’re right. My form is imported from excel, so the schema is a bit reverse engineered.. But now when I have version 1.0 ready I can get the schema out, fix the namepace and continue from there. Cheers!

  4. mnice says:

    Holy Cow dude πŸ™‚ Do you ever sleep ? what ever pills you are taking, i want those too :))

    πŸ™‚

  5. Anpassung Liam Cleary MOSS2007 – Link Lists and the Content Query Web part Adding "OpenInNewWindow" option

  6. PC says:

    I am interested on whether you can build an InfoPath form dynamically. For instance, I have InfoPath form 1, which has two fields:  1) Request Title – a TextBox field.  2) User – a DropDownList. In addition, I have another InfoPath form 2. It has three fields: 1) Estimated Cost – a TextBox field. 2) Center Name – a CheckBoxList. 3) Site – a DropDownList. Now, I want to create a generic InfoPath component, which can build form 1 or form 2, depending on pass-in properties. The dynamically built stuff is actually the different fields on the form. Once these fields have been built, they are presented on an InfoPath form. Using this way, I don’t need to hard code the form 1 and form 2 using Office InfoPath. I just create a generic component to build whatever InfoPath form I need. Do you think it is possible to build this component? I know ASP.Net web page/web part has no problem to do this job.

  7. Dharmin says:

    I tried the about example with an aspx page. However, when I try running it, I get an error saying:

    The element ‘{http://schemas.microsoft.com/office/infopath/Test5/myXSD/2008-06-20T18:52:11}myFields’ is used but not declared in the DTD/Schema.

    As you can see, I have changed the lines:

    66, 72 , 47 – 52 and 57, 63.

    Can you advise, what is wrong, or can you kindly post your code for me to donwload.

  8. Rohit says:

    Hi,

    i tried above example but it gives me

    following error

    Infopath cannot open following file http://rohidsag-2k3:49064/default.aspx?CreateRequest=true

    the file is not valid xml.

    The form contains XML that cannot be parsed:

    A string literal was expected, but no opening quote character was found.

    Line 19, Position 38

     <TABLE class="ms-main" CELLPADDING=0 CELLSPACING=0 BORDER=0 WIDTH="100%" HEIGHT="100%">

    ————————————-^

    can you advice

  9. Rohit says:

    Hi,

    Is it possible to fill submitted infopath form clicking on it and filling data and submit it?

    If Yes then How?

    Thanks in advance

  10. Stephan Onisick says:

    Love your blogs. Can’t print them out. The first Page comes out right The rest don’t print.

    Any suggestions.

    thanks,

    Stephan

Skip to main content