Creating documents in Domino without using a form or an agent
Category show-n-tell thursday
God bless Prototype, and God bless AJAX. For reasons I won't go into at the moment, I found myself earlier tonight wanting to create documents in a Domino database externally from an actual Domino form. With no page refresh. So I had a little conversation with myself:
"No problem. I'll just use AJAX to post the form data to an agent, and have the agent create the new document."
"But you don't want to use an agent."
"Why not?"
"Because the intent of this application could cause that agent to be invoked semi-constantly. Performance nightmare."
"Oh yeah, I forgot. Crap."
"Never fear, there's another way."
"There is? How?"
"Just post all the form fields to what the form action would have been if you were using the real form."
"Really, that works?"
"Hell, I dunno. Give it a try."
So I tried it, and it didn't work. Oh well. Back to the agent approach... but first I decided I'd check to see if there was something I was missing, and there was: __Click.
Assuming you have the database setting enabled to use Javascript when rendering pages, Domino automatically includes a _doClick function in the page source of any standard form that, when called, sets the value of a hidden field called __Click (note the double underscore), then submits the form to the server. The value of __Click tells the server whether or not a document is being saved or merely "refreshed". This is what allows various @Functions to work properly from the web, as well as enabling features like auto-refresh on combo boxes. As it turns out, if form data is submitted to the action URL corresponding to a valid Domino form without including a value for __Click, it doesn't know what to do, so it ignores the submitted data and redirects the browser to the URL for creating a new document using the specified form, i.e. "DBPath.nsf/FormName?OpenForm". If __Click has a value of 0, however, it tries to save a new document using the specified form and field values and runs any QuerySave agents defined on that form. The only caveat is that the form has to exist in the target database; any fields defined on that form that aren't assigned values in the posted data evaluate to their default (including computed fields), and any that are assigned a value but aren't defined on the form are simply ignored.
The implications of this are intriguing: although in my case I'm wanting to create documents in a Domino database from a design element within the same database, this approach would allow Domino data to be posted from anywhere... come to think of it, that might explain the recent rash of comment spam. But in any case, I set Anonymous to Depositor in my little test database, and tested posting to it from a Notepad file. Works like a charm.
Enough babble... here's some sample code:
function postMessage (strSendTo, strContent) {
// NOTE: in this example, strMyName, strServerName, and strDbPath are defined elsewhere
var messageBody = "__Click=0&From=" + strMyName + "&SendTo=" + strSendTo + "&Content=" + strContent;
var AJAXPost = new Ajax.Updater(
"PostResponse",
"http://" + strServerName + "/" + strDbPath + "/Message?OpenForm&Seq=1",
{postBody: messageBody}
);
}
God bless Prototype, and God bless AJAX. For reasons I won't go into at the moment, I found myself earlier tonight wanting to create documents in a Domino database externally from an actual Domino form. With no page refresh. So I had a little conversation with myself:
"No problem. I'll just use AJAX to post the form data to an agent, and have the agent create the new document."
"But you don't want to use an agent."
"Why not?"
"Because the intent of this application could cause that agent to be invoked semi-constantly. Performance nightmare."
"Oh yeah, I forgot. Crap."
"Never fear, there's another way."
"There is? How?"
"Just post all the form fields to what the form action would have been if you were using the real form."
"Really, that works?"
"Hell, I dunno. Give it a try."
So I tried it, and it didn't work. Oh well. Back to the agent approach... but first I decided I'd check to see if there was something I was missing, and there was: __Click.
Assuming you have the database setting enabled to use Javascript when rendering pages, Domino automatically includes a _doClick function in the page source of any standard form that, when called, sets the value of a hidden field called __Click (note the double underscore), then submits the form to the server. The value of __Click tells the server whether or not a document is being saved or merely "refreshed". This is what allows various @Functions to work properly from the web, as well as enabling features like auto-refresh on combo boxes. As it turns out, if form data is submitted to the action URL corresponding to a valid Domino form without including a value for __Click, it doesn't know what to do, so it ignores the submitted data and redirects the browser to the URL for creating a new document using the specified form, i.e. "DBPath.nsf/FormName?OpenForm". If __Click has a value of 0, however, it tries to save a new document using the specified form and field values and runs any QuerySave agents defined on that form. The only caveat is that the form has to exist in the target database; any fields defined on that form that aren't assigned values in the posted data evaluate to their default (including computed fields), and any that are assigned a value but aren't defined on the form are simply ignored.
The implications of this are intriguing: although in my case I'm wanting to create documents in a Domino database from a design element within the same database, this approach would allow Domino data to be posted from anywhere... come to think of it, that might explain the recent rash of comment spam. But in any case, I set Anonymous to Depositor in my little test database, and tested posting to it from a Notepad file. Works like a charm.
Enough babble... here's some sample code:
function postMessage (strSendTo, strContent) {
// NOTE: in this example, strMyName, strServerName, and strDbPath are defined elsewhere
var messageBody = "__Click=0&From=" + strMyName + "&SendTo=" + strSendTo + "&Content=" + strContent;
var AJAXPost = new Ajax.Updater(
"PostResponse",
"http://" + strServerName + "/" + strDbPath + "/Message?OpenForm&Seq=1",
{postBody: messageBody}
);
}
Comments
One hint at how Domino would handle this shows up when an upload control is added: the form element's enctype attribute is automatically set to "multipart/form-data". This implies that we cannot use the fieldname=value approach described above. Here's an example of one alternate approach I found: { Link }
Posted by Tim Tripcony At 01:37:37 PM On 11/25/2006 | - Website - |
How will be modified the ‘messageBody’?
Thanx in advance
Andrea
Posted by Andrea At 05:45:13 AM On 11/22/2006 | - Website - |
Thanks in advance.
Posted by Tim Nolan At 02:17:07 PM On 07/26/2006 | - Website - |
Create a new document:
/<server>/<db>/Form?CreateDocument
Update an existing document:
/<server>/<db>/0/<unid>?SaveDocument
Are there any advantages by using your approach that I haven't considered?
Posted by Fredrik Stöckel At 04:53:33 AM On 01/16/2007 | - Website - |
http://www.timtripcony.com/blog.nsf/d6plinks/GUIN-6S585P
Posted by Tim Tripcony At 02:36:03 AM On 07/28/2006 | - Website - |
Posted by Tim Tripcony At 02:00:20 AM On 01/19/2007 | - Website - |