In the previous walkthrough for the SubmitToSharePointList changes, we submitted data to three lists, all with a single mapping, a single submit connection, and the new, much simplified command syntax. If you didn't hang onto your form template from last time - here's one that you can start with - mind you, the form is pointed to my development SharePoint sites, so just about everything will need to be repointed to your environment, but at least you won't have to start all over. Also, this form is injected with a qRules trial - so if you download it after 9/15/2012, you'll want to re-inject it to enable qRules again.
First, we will need to add a field to our form data source for attachments. I think I'm going to add that to my Customer - it seems like I may want to attach a filled out credit application, or some other file related to the customer:
I've set the field to be repeating, since I want the user to be able to add multiple files.
Now, I have a decision to make. There are two options when adding attachments to my list item - I can keep the file in my form XML and add it to the list item in SharePoint or I can simply upload the file to my list item and remove it from the XML. Since I don't want to keep the file in two places, I'm going to take the second option - I want qRules to remove the file from my form after saving it to my list item.
To do that, all I have to do is add two attributes to my attachment node - qRulesLink and qRulesFilename:
The presence of these attributes on the attachment node indicates to qRules that you want to have the file removed after it has been uploaded (like the functionality of the SaveToSharePoint command, only for a list instead of a library).
Next, we need to modify our list mapping file to indicate that we have an attachment field. Now, if you have worked with the SubmitToSharePointList command before, you may have had to re-do your mapping each time you wanted to make a change. We've improved that experience in qRules 4.2 - we can now import our mapping into the mapping form.
So, first save your changes to your form template. Then, from the Data tab of the Ribbon, select Resource Files:
From the Resource Files dialog, click on your mapping.xml file:
And click the Export button to save the file.
Open the mapping tool from the Start menu:
Select the Define Mapping tab. There is a button toward the bottom - Import Existing qRules Mapping - click that:
You'll get a warning about the form deleting existing mappings, which you can click OK on, and then select the mapping file you just exported from your form. Your existing mapping will be imported - all that remains is to attach your template to the Source XSN field - much better than remapping every time, don't you think?
In the mapping to the Customers list, select Add mapping:
Select the new Files node that was added earlier for the Form Field and click the Show button in the Options column:
Select the Attachment checkbox for the Files node mapping:
And click the Save as qRules Mapping button at the bottom of the form to save the mapping.xml. If you maintain the same name as the original file you exported, you can simply re-add the file as a resource file - no need to walk through the data connection wizard again. From the Data tab of the Ribbon, select Resource Files again to open the Resource Files dialog. Click Add and navigate to the mapping file you just saved. InfoPath will prompt you:
You want to replace the existing file, so leave the default selection and click OK. You shouldn't have to modify your mapping data connection - the schema of the XML file will not have changed at all, simply the data. As an aside, you can always verify what file is used by your data connection in the Data Connection dialog:
Add a Data Connection
We need to add a Receive data connection to the AddAttachment method of the SharePoint Lists web service. On the Data tab of the Ribbon, select From Web Service --> From SOAP Web Service:
The URL for the Lists web service is: http://YourServer/_vti_bin/lists.asmx - replace "YourServer" with your actual server name. If in doubt, test your URL in a browser, making sure you get a page that looks like this:
After entering the URL in the Data Connection Wizard, click Next and select the AddAttachment method:
Click Next - no need to set any of the query parameters, so click Next again, then one more time - in the final screen of the dialog, deselect the "Automatically retrieve data when form is opened" checkbox and leave the default name for the data connection - you can name it something else if you like, but keep track of the name, because we will need it when we modify our command.
Add Controls to the Form
Add controls to your form to allow the selection of files. I like to add a file picker and a hyperlink, with the file picker inside a section, and set to hide if the qRulesLink attribute is not blank. Here's a copy of my work in progress, if you'd like to check it out. For the hyperlink, I am using the qRulesLink attribute for the link, and the qRulesFilename attribute for the display:
Modify the Command
In the first walkthrough, we added a submit button to our form with the qRules command:
Now, we need to modify this command to include our attachment files when we submit to the Customer list:
SubmitToSharePointList /submit=ShPList /dsname=AddAttachment
If you named your AddAttachment data connection something different, you need to modify the command above to use the name of your data connection:
SubmitToSharePointList /submit=ShPList /dsname=MySuperSpecialAttachmentDataConnection
Remember, case cOunTs - you need to use the exact same spelling and casing.
Test the Form
As always, be sure you have the QdabraRules Error node somewhere you can see it prior to testing. Preview your form, add a new customer, and add some files for the customer. Click the Submit button:
If everything is set up correctly, you'll now have links in your form instead of files - and in your list item:
You will have attachments.
Extra - Add Delete Logic!
So - this is all well and good. Provided your users never ever make mistakes.
But every now and again, someone may attach and save the wrong file. It would certainly be nice to allow the user to delete the file from the form, wouldn't it?
No qRules required for this - just add another data connection to the DeleteAttachment method of the SharePoint Lists web service - exactly the same way as you added the AddAttachment method above:
Don't bother filling out any of the query parameters, and deselect the option to automatically execute the data connection on load (just like we did for the AddAttachment data connection).
Add a button to your form next to your hyperlink control:
Add a conditional formatting rule to the button to hide it if the qRulesLink attribute is blank:
Add an action rule to the button. There are three fields we need to set in the DeleteAttachment data source queryFields:
I like to get the listName from the mapping file. MSDN states that the listName parameter can be the list GUID or name. We have the GUID in our mapping file - it is in the Customers mapping:
So, I'll set that field to the ListCollection node in my mapping file where the mappingName is equal to Customers:
Next, I set the listItemID parameter to the field I am storing my SharePoint item ID in - in this case, that would be /my:myFields/my:Customer/my:ShpId:
Then I set the url parameter to the qRulesLink attribute:
Don't forget, we need to actually execute the query (I always forget that rule action, leaving myself perplexed when my what-ever-it-is doesn't work):
In a perfect world, our web service method would return some useful information to us - sadly, it doesn't (or at least not anything that InfoPath is going to tell us about). If the query fails, any rule actions after it won't run, so I generally work on the assumption that if my query succeeds, my attachment will have been deleted, and add two more rule actions to clear out the qRulesLink and qRulesFilename attributes.
However, you do have some options for error handling.
Use the qRules QueryData command to execute the DeleteAttachment query - it will handle any errors and return them to the QdabraRules QueryDataError node - you could then add some conditions around clearing the qRulesLink and qRulesFilename attributes
Or, after executing the data connection, you could query the GetAttachmentCollection method of the Lists web service - check the value of the /dfs:myFields/dfs:dataFields/tns:GetAttachmentCollectionResponse/tns:GetAttachmentCollectionResult and see if it contains the value of the qRulesLink attribute
My final ruleset looks like this:
I've simply chosen to let InfoPath return a query error in this case - and I added a condition to only run if the SharePoint ID field is populated.
So, now our form submits to three related SharePoint lists. It can include attachments. The user can delete attachments. Here's the final form, in case you want to take a look at any of the logic. Next up - submitting just specific mappings. Hang onto your form and your test site!
Submitting a Single Mapping / Updating Existing Data