« Wheee! | Main| Parsing formulas on the fly via @Eval and @While »

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}
   );
}

Comments

Gravatar Image1 - Good work…but, what about if i add a field to upload a file?
How will be modified the ‘messageBody’?

Thanx in advance

Andrea

Gravatar Image2 - I haven't used this approach for uploading files yet... Javascript is subject to security restrictions that limit its effectiveness when dealing with local files.

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 }

Gravatar Image3 - Tim, I posted a more thorough example tonight, including a downloadable demo database that illustrates not only creation of documents, but editing and deletion as well:

http://www.timtripcony.com/blog.nsf/d6plinks/GUIN-6S585P

Gravatar Image4 - Fredrik, you're quite right - the URL commands you mentioned produce the same result, as far as I can tell (there may be differences in field evaluations, but I doubt it). When I have time, I'll try both side by side in Firebug to see if there is a performance advantage to either approach.

Gravatar Image5 - Why not use the good old ?CreateDocument and ?SaveDocument url command arguments? I use them all the time and it works perfectly

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?

Gravatar Image6 - Do you have anything that gives the full details of this solution? I am looking to create "profile" documents to store some information based on choices made on a web page.

Thanks in advance.

Contact Me

Hire Me

Elsewhere

What the Quote?

"$3.50 for a 1 GB MicroSD card with SD adapter? That's cheaper than tuna!"

Laura Tripcony

"Mmm... translucent bear..."

Brent Bowers

"But... that would make me helium."

Adam Slagle

"I'm sure one of these days you'll get a break.... just don't hold your breath, I don't think you'd look good in blue"

Steven Rodgers

"Microsoft is as simple as the church. You cannot be a little bit Catholic."

Volker Weber

Apparel

Lotus Rocks

I write the code that makes the young girls cry

Current Terror Alert Level

Assorted Linkage

ClustrMap