Tuesday, July 21, 2009

Submitting The InfoPath From to the Current From Library Folder

Have you ever faced the case that you want to organize your form library items to folders , you may be using a submit data connection to submit your form to the library including the meta data and also to benefit from the overwrite check in the submit data connection to enable or disable overwriting forms with the same name ?. if this the

case you will face to problems.


  1. Submit using data connection sumbits only to the root folder

  2. Overwrite check can only check for dublicated forms in the current directory (so you can't guarantee uniqunuess in the form library entierly)

Solution


The solution for the first problem is to handle the submit event and update the url for the Main Submit data connection with the current working directory.


The Solution for second problem is to search all the folders inside the the form library for the field you want to be unique which will be shown in the Title Field, if it exists before cancel submittion.


The Code


1- Add New Submit Data Connecntion to your form library
2- From Submit Options Choose to run custom code when sumbiting the form.
3- This will open the code behind project for this form template, Add the following variables to the FormState dictionary




private string RootFolder
{
get { return FormState["RootFolder"].ToString(); }
set { FormState["RootFolder"] = value; }
}
private Guid SiteID
{
get{return (Guid)FormState["SiteID"];}
set{FormState["SiteID"] = value;}
}
private Guid WebID
{
get{return (Guid)FormState["WebID"];}
set{FormState["WebID"] = value;}
}

private Boolean ProjectExist
{
get{return (Boolean)FormState["ProjectExist"];}
set{FormState["ProjectExist"] = value;}
}


4- You need to handle the load event to read the current folder.
Note that you should handle the two cases if the form is opend in the browser or usnig the infopath client




void FormEvents_Loading(object sender, LoadingEventArgs e)
{
XPathNavigator xnDoc = this.MainDataSource.CreateNavigator();
if (this.New) // New Request
{
char[] splitter = new char[] { '/' };
// Read The Root folder from the url if form shown in browser
if (Application.Environment.IsBrowser)
{
string[] all = e.InputParameters["SaveLocation"].Trim(splitter).Split(splitter);
RootFolder = all[all.Length - 1];
}
else // if the form shown in the infopath read the folder from the uri
{
string strUri = this.Template.Uri.ToString();
string strPath = strUri.Substring(0, strUri.IndexOf("Forms") - 1);
RootFolder = strPath.Substring(strPath.LastIndexOf("/") + 1);
}
XPathNavigator isNew =
xnDoc.SelectSingleNode("/my:myFields/my:New", this.NamespaceManager);
isNew.SetValue("1");
XPathNavigator root = xnDoc.SelectSingleNode("/my:myFields/my:root", this.NamespaceManager);
root.SetValue(RootFolder);
}
else // Modification To Existing Item
{
XPathNavigator isNew =
xnDoc.SelectSingleNode("/my:myFields/my:New", this.NamespaceManager);
isNew.SetValue("0");
}
}


5- Before sumbitting the form you will need the following:


  • Get the current folder.

  • Loop inside all the fodler in our form library to search for the choosen field to be unique if it is existing before.
    Note that you should run the search method with elavated privilages to get the results regardless of the current logged user permissions.

  • Concatenate the current folder to the Main Submit connention folder.

  • Then Submit your form.




public void FormEvents_Submit(object sender, SubmitEventArgs e)
{
SPWeb contextWeb = SPContext.Current.Web;
SiteID = contextWeb.Site.ID;
WebID = contextWeb.ID;
// Invoke the CheckAvailablity method with elavated privilage to
// get the search results regardless the privilages of the logged user
// becuse we search subfolders that may include special permissions
SPSecurity.CodeToRunElevated codeToRunElevated = new SPSecurity.CodeToRunElevated(CheckAvailablity);
SPSecurity.RunWithElevatedPrivileges(codeToRunElevated);
try
{
FileSubmitConnection dc =
(FileSubmitConnection)this.DataConnections["SharePoint Library Submit"];
if (ProjectExist)
{
throw new Exception("The Project Name Exists before, It must be unique.");
}
if (dc != null)
{
string listName = "listname";
if (RootFolder != listName)
{
dc.FolderUrl = dc.FolderUrl + "/" + RootFolder;
}
else
{
dc.FolderUrl = dc.FolderUrl;
}
dc.Execute();
e.CancelableArgs.Cancel = false;
}
}
catch (Exception ex)
{
e.CancelableArgs.Message = @"There was a problem submitting the
form: " + ex.Message;
e.CancelableArgs.Cancel = true;
}
}




///


/// This Method Used to search for the filed that should be unique inside all the folders
/// for the form library because of the limitation for the (built in overwrite check)
/// that can gurantee uniquiness only in the current folder
///

void CheckAvailablity()
{
// Read The Current List by opening the web explicitly
// to get rid of "Operation is not valid due to the current state of the object"
// if we used SPContext.Current.Web directly
SPSite site = new SPSite(SiteID);
SPWeb web = site.OpenWeb(WebID);
SPList list = web.Lists["listname"];
XPathNavigator xnDoc = this.MainDataSource.CreateNavigator();
XPathNavigator pName =
xnDoc.SelectSingleNode("/my:myFields/my:project_name", this.NamespaceManager);
string projectName = pName.Value;
SPQuery q = new SPQuery();
q.Query = @"" + projectName + "";
// Search in the root folder first
bool found = false;
SPListItemCollection outerColl = list.GetItems(q);
if (outerColl.Count > 0)
{
found = true;
}
else
{
// then search inside subfolders
foreach (SPListItem flder in list.Folders)
{
q.Folder = flder.Folder;
SPListItemCollection coll = list.GetItems(q);
if (coll.Count > 0)
{
found = true;
break;
}
}
}
ProjectExist = found;
}



I hope this helps, and Appreciate any comments

No comments:

Post a Comment