Search code examples
xpages

Domino xAgent gives 500 Command not handled exception - $$viewid ID not present


Dear domino cognoscenti,

I've just written a simple xAgent using an xpage which works for GET requests but when I submit a POST request I get an Error 500 HTTP Web Server: Command Not Handled Exception with the following detail CLFAD0384E: Page instance not found. The $$viewid ID was not present in a POST request (thanks Per for the hint).

Here's the code. What am I doing wrong? Do xpages not handle POST requests by default? Do I have to enable this or something?

Thanks very much for your time! 😊

<?xml version="1.0" encoding="UTF-8"?>

<xp:view xmlns:xp="http://www.ibm.com/xsp/core" rendered="false">
    <xp:this.resources>
    </xp:this.resources>

    <xp:this.afterRenderResponse>
        <![CDATA[#{javascript:      
            var exCon = facesContext.getExternalContext(); 
            var requestMethod = exCon.getRequest().getMethod();
            var response = exCon.getResponse();
            var writer = facesContext.getResponseWriter();

            response.setContentType("text/plain");
            response.setHeader("Cache-Control", "no-cache");
            
            writer.write(requestMethod);
            writer.endDocument();
        }]]>
    </xp:this.afterRenderResponse>
</xp:view>

Edited 16 October 2022 I've tried the following:

  • Added viewState="nostate" to xp:view. (thanks Mark for that)
  • Had no code in the afterRenderResponse other than logging - still get the same problem.
  • Used code in the beforeRenderResponse - same problem.
  • Tried the restService - same.

The only thing that appears to fix it is:

  • Introduce a field called $$viewid and set this to the value '!!' or '!0!' or similar.
  • Use the FormData Web API on the browser to build the request body.
  • Send it as Content-Type:multipart/form-data.

Sending it as plain text, application/json etc doesn't work. For some reason the xpage won't accept other encoding types.

Any ideas anyone?


Solution

  • The issue is with CSRF protection as detailed in this blog post. When creating an xpage, in xsp.properties, the setting xsp.csrf.protection=true needs to be set to false (annoyingly it's not part of the UI, you have to go to the source tab).

    The explainer from the blog post is as follows.

    If you look in a new NSF the xsp.properties contains a setting xsp.csrf.protection=true .

    This enables a built-in framework for CSRF protection 😊 and was very easily retrofitted to our existing NSFs.

    When this feature is enabled every XPage contains a token such as

    <input type=”hidden” name=”$$viewid” id=”view:_id1__VUID” 
    value=”!1to6ah3iyy1uc2gquai14d7ik!”>
    

    If the returned XPage does not have this same token then an error is generated. The error will be CLFAD0253E: Cannot find a page instance corresponding to the ID: $$viewid=!aaaaaaaaaa!. It may have expired. Try loading the web page

    Setting this to false prevents this from occuring and the code works as expected (however see here for the multipart/form-data) Obviously there are risks so this isn't ideal but it's the cause of the problem seen. Setting this from true to false stops this from occurring.

    Thanks to Sean Cull at Focul for pointing this out. If following this path, we'd have to code our own CSRF token handler.

    Thanks to everyone else who contributed above. I appreciate your time.