views:

550

answers:

1

I've got an InfoPath form in a forms library on MOSS 2007. I think that the InfoPath browser toolbar with it's save (manually enter filename) and close rather overcomplicates the process of filling in a form. What I'm trying to do is simply have a button with some code behind that saves the form to the library where it was opened with a automatically generated filename and closes back to the library. To do this I've written the following code:

public void SaveForm(string formXml, string fileName, Dictionary<string, string> extraColumns)
{
    SPFolder formsLibraryFolder = SPContext.Current.List.RootFolder;

    string lowerCaseFilename = fileName.ToLower();
    if (!lowerCaseFilename.EndsWith(".xml"))
        fileName += ".xml";

    web.AllowUnsafeUpdates = true;
    SPFile file = formsLibraryFolder.Files.Add(fileName, Encoding.UTF8.GetBytes(formXml));

    if ((extraColumns != null) && (extraColumns.Count > 0))
    {
        foreach (KeyValuePair<string, string> column in extraColumns)
        {
            file.Item[column.Key] = column.Value;
        }
        file.Item.Update();
    }

    web.AllowUnsafeUpdates = false;
}

The problem with this code as it turns out, is that SPContext.Current.List is null in the situation where I want to save the form to the library in which it was opened. I assumed obviously incorrectly that as the form is going to be completed inside the browser that the context of the list would be valid. I can however access the SPWeb that contains the list but this mean's I would need to hardcode the list name for each type of form and of course know in advance the list name that each form goes into. This code is part of a helper library I've written and reference in many forms over different projects so I really can't be hard coding values. I could of course pass the list name as a argument and hard code the list name in the form itself but that still means I have to know in advance where the form will be deployed. Is there any way I could work out in which library new was clicked to initiate the filling in of the form?

+2  A: 

I've figured out how to do this so I'll post it for anyone else.

When you close a browser form InfoPath redirects you back to the list. You can get the URL to the list thanks to method 2 in the following article:

http://www.bizsupportonline.net/blog/2010/01/2-ways-retrieve-sharepoint-site-collection-infopath-browser-form/

When my own save button is clicked I pass the URL to my updated save function. I should point out this isn't fool proof code and there are a few places it could break. It does however work for the specific cases where I need to use it.

public void SaveForm(string formXml, string fileName, string url, Dictionary<string, string> extraColumns)
{
    SPWeb web = SPContext.Current.Web;
    string webUrl = web.Url;
    if (!webUrl.EndsWith("/"))
        webUrl += "/";

    string relativeUrl = url.Replace(webUrl, string.Empty);
    string listName = relativeUrl.Substring(0, relativeUrl.IndexOf('/'));
    SPList destinationList = web.Lists[listName];
    SPFolder destinationFolder = destinationList.RootFolder;

    string lowerCaseFilename = fileName.ToLower();
    if (!lowerCaseFilename.EndsWith(".xml"))
        fileName += ".xml";

    web.AllowUnsafeUpdates = true;
    SPFile file = destinationFolder.Files.Add(fileName, Encoding.UTF8.GetBytes(formXml));

    if ((extraColumns != null) && (extraColumns.Count > 0))
    {
        foreach (KeyValuePair<string, string> column in extraColumns)
        {
            file.Item[column.Key] = column.Value;
        }
        file.Item.Update();
    }

    web.AllowUnsafeUpdates = false;
}
Dan Revell