Save Content using REST API - Documentation topics on: ajax,api,binary fields,building and using forms,categories,content,contentapi,contentlet,creating forms,custom forms,files on content forms,form building,forms,jquery,json,rest,rest api forms,sample form code,uploading files,using categories in web forms,.

Save Content using REST API

The Content REST API allows you to search and render dotCMS content, and allows you to save and update dotCMS content via JSON, XML and Form UrlEncoded data formats.

Usage

Base URL

The base URL for saving content is http[s]://[host]:[port]/api/content.

HTML Methods (PUT/POST)

You can submit content to dotCMS using either HTML PUT or POST methods. By convention, POST is used for inserting new content and PUT is used for updating existing content; however the API calling conventions for both are identical.

Header Fields

The following Request header fields are recognized. Which headers are required and which are optional depends on the operation being performed.

Content Type Identification

The header for ever content submission must include either an stInode or stName field to identify the Content Type of the content to be added or modified.

FieldDescription
stInodeThe inode of the Content Type (not the inode of the individual content item).
stNameThe Velocity variable name of the Content Type.
(Human readable alternative to stInode).

Content Type Fields

The data for each field of the Content Type is defined using the Velocity variable name of each field in the Content Type as the header field name/key, and the value of the field (as a string) as the header field value.

Field Value Formats

All field values are passed in the POST or PUT header as strings. Below is a list of field types in dotCMS and the supported formats for each type:

Field TypeSupported Formats
BinaryPlease see Binary Fields, below.
CategoryA string containing a comma separated list of Category ids, Category keys, or Category variable names.
(e.g. "investing,research,wealthManagement").
Please see Categories, below.
Checkbox,
Multi-Select
A string containing a comma separated list of selected values (the strings to the right of the pipe (\
Constant Field,
Hidden Field
Should not be submitted with the content item.
(These are filled in automatically by dotCMS).
Custom FieldA string containing the field value (as formatted by your Custom Field code).
Date,
Time,
Date and Time
yyyy-MM-dd HH:mm, d-MMM-yy, MMM-yy, MMMM-yy, d-MMM, dd-MMM-yyyy, MM/dd/yyyy hh:mm aa, MM/dd/yy HH:mm, MM/dd/yyyy HH:mm, MMMM dd, yyyy, M/d/y, M/d, EEEE, MMMM dd, yyyy, MM/dd/yyyy, hh:mm:ss aa, HH:mm:ss, yyyy-MM-dd.
Note: You may use formats that only include the date or time for Date and Time fields, but you may not use a format which includes both the date and time for Date fields or Time fields.
File,
Image
The path to the related file, starting with the hostname (e.g. "//demo.dotcms.com/images/photos/The-Gherkin-London-England.jpg").
Key/ValuePlease see Key/Value Pair Fields, below.
Radio,
Select
A string containing the selected value for the field (the string to the right of the pipe (\
RelationshipPlease see Relationships, below.
Site or FolderA string representing the host (e.g. "demo.dotcms.com"), a folder (for the host the user is on) (e.g. "/images/photos"), or a combination of host and folder (e.g. "demo.dotcms.com:/images/photos/".
TagA comma separated list of tag values (e.g. "investment,banking,europe").
TextA string containing the field value.
TextareaA string containing the field value.
Non-printing characters should be escaped using HTML escape codes (e.g. %0D%0A for carriage-return line-feed).
WYSIWYGA string containing the field value, containing HTML formatting.
Non-printing characters should be escaped using HTML escape codes (e.g. %0D%0A for carriage-return line-feed).

Files / Multipart Form Data

Sending multipart/form-data is supported, and is required in order to send file content for Binary fields.

Binary Field Order

Every body type with a Content-Disposition header is interpreted as a Binary field value following the order of the Binary fields in the Content Type. For example, if there are two binary fields in the Content Type, the first Binary body type is assigned to the first Binary field and the second body type is assigned to the second Binary field.

Important: It is not possible to skip a binary field value and continue assigning to other, later binary fields in a Content Type. If you wish to update a single Binary field in a content item, you must first retrieve the contents of all the Binary fields, and then submit the content item with all Binary fields included, in order.

Language ID

You may specify the language version of the content item you wish to add or update by setting the languageId field in the header, with the value equal to the id number of the language for the content item (e.g. 1 for the default language, 2 for the first added language, 3 for the next configured language, etc.). If the language_id field is not set, the default language will be used.

Content Type Header

The format of the content should be specified in the Content-Type header. Supported Content-Types include:

  • application/json
  • application/xml
  • application/x-www-form-urlencoded

For more information on submitting content using these content types, please see Data Formats, below.

Operations

You may save and update content via the REST API in several different ways. The URL used to perform the operation specifies what operation you wish to perform. A URL which does not include an argument specifying the operation will throw an error (e.g. just /api/content/ without a save, publish, workflow action name, etc.).

Save or Publish (Working vs. Publishing Versions)

The URL you use to submit content must specify whether you wish save the content (submit a working version of the content without publishing) or publish it (which both saves the working version and then publishes it). To select save or publish, add /save/1 or /publish/1 to the URL after the /content/ portion of the base URL (e.g. /api/content/save/1 or /api/content/publish/1).

Execute a Workflow Action

You may execute a Workflow Action on a piece of content instead of directly saving or publishing it. If the argument following the /content portion of the URI matches a Workflow Action which is currently available for the content item (based on the Workflow Scheme attached to the Content Type and the current Workflow Step the content item is in), then the action is executed.

If the Workflow Action allows comments or allows the user to assign the Workflow Task, you may pass 'wfActionComments' and/or 'wfActionAssign' parameters in the URI.

Note: Since the Workflow Action Name and comments must be passed in the URI, you must use appropriate URL percent encoding in place of any characters which are not appropriate to be passed in a URL (e.g. use %20 in place of a space, %21 in place of an exclamation point, etc.).

Example

The following executes the “Assign for Review” Workflow Action with the comment “Hey, take a look”, and assigns it to the user with id “dotCMS.org.7575”:

PUT /api/content/Assign%20for%20Review/1/wfActionComments/Hey%2C%20take%20a%20look/wfActionAssign/dotCMS.org.7575

Other API Endpoints

For more information on addition endpoint methods available via the Content REST API, please see the REST API Endpoints documentation.

Response Headers

When the content item is successfully created or updated, 3 headers are returned:

HeaderDescription
LocationA pointer to where the content can be obtained using the Content REST API.
InodeThe inode of the content version just saved.
IdentifierThe identifier of the content object just saved.

Authentication

This API supports the same REST authentication infrastructure as other REST APIs in dotCMS. There are 4 different methods to login; however, only 2 of these methods are recommended for normal use, for security reasons.

Secure Authentication

  • Basic http authentication (base64 encoded).
  • Session-based for frontend or backend logged in user.

Insecure Authentication

The following additional methods can be used for authentication. However both of these methods send both the user name and password “in the clear” (unencrypted), and it is strongly recommended that you do not use these methods in any environment which is exposed on an external/public network (such as any public-facing production server).

  • URI Arguments: Add /user/xxx/password/yyy to the URI.
  • DOTAUTH header: similar to basic authorization and base64 encoded, e.g. setHeader(“DOTAUTH”, base64.encode(“admin@dotcms.com:admin”))

Saving by Non-Authenticated Users

By default, only authenticated users may save content via the REST API. However you can enable saving of content by non-authenticated (front-end) users, for example to allow front-end users to submit forms which save content using the REST API.

Configuration

To allow non-authenticated users to save content via the REST API, you must perform all of the following configuration steps:

  1. Set REST_API_CONTENT_ALLOW_FRONT_END_SAVING=true in the dotmarketing-config.properties file.
    • Note: It is strongly recommended that all changes to the dotCMS configuration files be made through a properties extension file.
  2. Set permissions to allow the CMS Anonymous user to save content of the appropriate Content Types.
    • Grant Add to permissions to the CMS Anonymous role on the Site where the content will be saved using the REST API.
    • Grant Edit permissions to the CMS Anonymous role on each Content Type which will be added or updated via the REST API.

Data Formats

You may submit data via the Content REST API using several different data formats. The following examples demonstrate ways to submit content via the REST API using JSON, XML, and Form UrlEncoded formats, both to create new content and to update existing content.

Note: Examples Using curl

The following examples use the curl command, which is a command line utility (available for Linux, OS X, and Windows) which allows you to easily perform the HTTP PUT and POST methods required to create and update dotCMS content.

Note:

  • The curl command provides two different methods for submitting REST API calls using JSON format (using the curl -H option and using the curl -F option).
    • The examples below demonstrate both methods.
  • The format for submitting header names is different for each method.
    • See the below examples, and make sure to specify the header names appropriately for the method you use.

JSON

The following curl command creates content of the “Content (Generic)” Content Type (on the dotCMS starter site or demo site) using basic authentication:

curl -v -u admin@dotcms.com:admin -XPUT http://localhost:8080/api/content/publish/1 -H "Content-Type:application/json" -d '{
    languageId:1,
    stInode:"2a3e91e4-fbbf-4876-8c5b-2233c1739b05",
    title:"test content",
    contentHost:"demo.dotcms.com",
    body:"test body"
}'

Using the Content Type variable name (stName) instead of the Content Type inode (stInode) has the same result:

curl -v -u admin@dotcms.com:admin -XPUT http://localhost:8080/api/content/publish/1 -H "Content-Type:application/json" -d '{
    stName:"webPageContent",
    languageId:1,
    title:"test content",
    contentHost:"demo.dotcms.com",
    body:"test body"
}'

Creating and then Updating an EXISTING piece of content

curl -v -u "admin@dotcms.com:admin" -XPUT http://localhost:8080/api/content/publish/1 -F 'json={
   "stName":"webPageContent",
   "contentHost":"demo.dotcms.com",
   "title":"Test 001 - Created through curl",
   "body":"<b>Created through curl</b>"
};type=application/json'

< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
* Server Apache-Coyote/1.1 is not blacklisted
< Server: Apache-Coyote/1.1
< Location: http://localhost:8080/api/content/inode/3227c025-4bb5-4947-843e-9dd2cb95a9dd
< inode: 3227c025-4bb5-4947-843e-9dd2cb95a9dd
< identifier: 699c969c-4be3-4f8d-9d80-da8ff0ab7c7d
< Content-Type: text/plain
< Content-Length: 0
< Date: Wed, 22 Jul 2015 20:42:24 GMT
<
* Connection #0 to host localhost left intact

(some of the output is omitted)

curl -v -u "admin@dotcms.com:admin" -XPUT http://localhost:8080/api/content/publish/1 -F 'json={
   "identifier":"699c969c-4be3-4f8d-9d80-da8ff0ab7c7d",
   "stName":"webPageContent",
   "contentHost":"demo.dotcms.com",
   "title":"Test 001 - Created through curl",
   "body":"<b>Updated through curl</b>"
};type=application/json'

< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
* Server Apache-Coyote/1.1 is not blacklisted
< Server: Apache-Coyote/1.1
< Location: http://localhost:8080/api/content/inode/644c5d16-e0b0-4d1e-a53d-16777197d73f
< inode: 644c5d16-e0b0-4d1e-a53d-16777197d73f
< identifier: 699c969c-4be3-4f8d-9d80-da8ff0ab7c7d
< Content-Type: text/plain
< Content-Length: 0
< Date: Wed, 22 Jul 2015 20:45:44 GMT
<
* Connection #0 to host localhost left intact

(some of the output is omitted)

XML

curl -v -u admin@dotcms.com:admin -XPUT http://localhost:8080/api/content/publish/1 -H "Content-Type:application/xml" -d '
<content>
    <stInode>2a3e91e4-fbbf-4876-8c5b-2233c1739b05</stInode>
    <languageId>1</languageId>
    <title>test content</title>
    <contentHost>demo.dotcms.com</contentHost>
    <body>test body</body>
</content>'

< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Set-Cookie: JSESSIONID=3806974B823401EEDCB1916FF0469719; Path=/; HttpOnly
< Location: http://localhost:8080/api/content/inode/534c547e-dba9-458b-aef0-b977c7fc2a7e
< inode: 534c547e-dba9-458b-aef0-b977c7fc2a7e
< identifier: 52c81804-e789-48b3-b5c1-0de73a8cacea
< Content-Type: text/plain
< Content-Length: 0

Form UrlEncoded

curl -v -u admin@dotcms.com:admin -XPUT http://localhost:8080/api/content/publish/1 -H "Content-Type:application/x-www-form-urlencoded" -d 'stInode=2a3e91e4-fbbf-4876-8c5b-2233c1739b05&languageId=1&title=test%20content&contentHost=demo.dotcms.com&body=test%20body'

< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Set-Cookie: JSESSIONID=9589AC9A470E506BC3ED3D779ABF9DF4; Path=/; HttpOnly
< Location: http://localhost:8080/api/content/inode/25942273-57c2-4aa3-bbad-710b7bf3b1bf
< inode: 25942273-57c2-4aa3-bbad-710b7bf3b1bf
< identifier: 11840c4a-57b7-4618-995d-dc935b2fe53b
< Content-Type: text/plain
< Content-Length: 0

Field Types

The following examples demonstrate how to send content for several additional types of Content Type fields.

Categories

Categories can be specified using a comma separated list. Each item in the list will be checked first to see if it matches a Category inode, then to see if it matches a Category key, and finally to see if it matches a Category variable name. If any of these are matched, the appropriate Category will be set for the content item.

The following example adds a News content item on the dotCMS demo site (uploading categories variable names):

curl -v -u admin@dotcms.com:admin -XPUT http://localhost:8080/api/content/publish/1 -H "Content-Type:application/json" -d '{
   stInode:"28039964-5615-4ccf-bb96-ded62adbcc6a",
   languageId:1,
   urlTitle:"a-new-news-item",
   hostfolder:"demo.dotcms.com",
   title:"A new news item",
   byline: "this is a new story",
   sysPublishDate: "2013-07-01 00:00:00",
   story: "this is a new story uploaded from cURL",
   topic: "investing,banking,research"
}'
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Set-Cookie: JSESSIONID=350BB6A31730E2EC3EF5B0A963B38F5E; Path=/; HttpOnly
< Location: http://localhost:8080/api/content/inode/b5b468f8-f304-4312-a566-5a294786a5a6
< inode: b5b468f8-f304-4312-a566-5a294786a5a6
< identifier: f5a13b1a-d0fc-4934-a6a5-9dc80aaf768d
< Content-Type: text/plain
< Content-Length: 0

Binary Fields

Files can be uploaded into Binary fields using multipart/form-data.

  • Portions of the API call using JSON, XML or Form UrlEncoded data are interpreted as normal field values.
  • Portions of the API call using a Content-Disposition header are added as Binary field values.

Binary Files Must be Submitted in the Same Order as the Content Type Fields

You must submit Binary field data in the same order as the fields appear in the Content Type. If we have two Binary fields named binary1 and binary2, and binary1 is before binary2 in the Content Type field order, then the first file to be sent in the API call will be assigned to the binary1 and the second file sent will be assigned to binary2.

Note that you can not skip Binary fields when submitting content via the REST API. So in our example, you can not submit content for the binary2 field without also submitting content for the binary1 field. If you wish to update the value of a single Binary field in a piece of content using the Content REST API, you must first retrieve all existing Binary field values, and then resubmit all Binary fields, changing the value of only the Binary field you wish to update.

Example: Uploading a File Asset

The following curl command submits a File Asset using the REST API. Note the JSON portion of the API call to set the regular field values, and the file included using @ (which will submit the specified file to the first Binary field in the Content Type).

curl -v -u admin@dotcms.com:admin 
  -XPUT http://localhost:8080/api/content/publish/1 
  -F "json={
    stName:'fileAsset',
    hostFolder:'demo.dotcms.com:/images',
    title:'nice.jpg',
    fileName:'nice.jpg'};
    type=application/json" 
  -F "file=@nice.jpg;
    type=application/jpg"


< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Set-Cookie: JSESSIONID=1008EEB589168054CAF7C9E9C3D678A3; Path=/; HttpOnly
< Location: http://localhost:8080/api/content/inode/197c5b4c-417a-4ba5-98e6-12f5cda1889b
< inode: 197c5b4c-417a-4ba5-98e6-12f5cda1889b
< identifier: fc2816da-107a-4c01-b404-bd552503f0f4
< Content-Type: text/plain
< Content-Length: 0

Key/Value Pair Fields

In the following example, a Key/Value pair field on a Content Type called “Television” has the Velocity variable name of “productSpecifications”. As shown in the example below, keys and values can be sent via REST API using the following form: fieldVelocityVariableName:{"mykey1:"myValue1","mykey2:"myValue2",... etc.}. Note the handling of the “productSpecifications” key/value pair field.

curl -v -u admin@dotcms.com:admin -XPUT http://demo.dotcms.com/api/content/publish/1 -H "Content-Type:application/json" -d '{
   stName:"Television",
   languageId:1,
   contentHost:"demo.dotcms.com",
   brandAndModel:"Samsung UN65JS9500",
   resolution:"Ultra HD",
   screenSizeinches:"65",
   productSpecifications:{"Refresh Rate":"240 CMR (Effective)","Backlight":"LED","Smart Functionality":"Yes - Built in Wifi","Inputs":"2 HDMI, 2 USB"}
}'

Relationships

To specify that a piece of content is related to another piece of content, you must pass the Relationship name as the header field name/key and a Lucene query as the value.

Example: Blog-Comments Relationsip

For example the Content Types “Blog” and “Comments” found in the dotCMS starter site and demo site have a one to many relationship between them called “Blog-Comments”.

A new comment matching the parent News post can be added by:

  1. Adding a “Blog-Comments” field in the JSON data.
  2. Adding a Lucene query to the field to identify the Blog content item the comment will be linked with.

The header field would have a format similar to the following:

 "Blog-Comments", "+identifier:12321-123-123123"

Important Notes:

  • The Lucene query must return a single content item for the relationship to be saved properly.
    • To relate a piece of content to multiple pieces of content, you must add a relationship field/value header for each content item you wish to create a relationship to.
  • When updating content using the REST API, you must submit all relationships for a piece of content each time you update the content.
    • If you wish to add a new relationship but maintain all existing relationships, you must first find all existing relationships so that you can include them when updating the content.
    • Any relationships which are not included when you update a content item via the REST API will be removed from that content item.

The following curl command submits a new comment and relates it to a Blog content item:

curl -v -u admin@dotcms.com:admin -XPUT http://localhost:8080/api/content/publish/1 -H "Content-Type:application/json" -d '{
   stName:"Comments",
   languageId:1,
   title:"test comment",
   email:"myemail@mydomain.com",
   comment:"this is my cool comment",
   Blog-Comments:"+contentType:Blog +title:picks"
}'

The comment should appear in the post “Bill Ackman's Top Stock Picks” that comes by default in the starter. Note that some fields will be left empty as this example only sends the fields required by the Content Type.

Please also see the Example Employee Profile form with Relationship and Binary field below.

Code Examples

The following examples demonstrate how to use the content REST API using scripting and code within dotCMS (such as to submit forms using the REST API).

Using jQuery

Ajax content can be sent to dotCMS, making it possible to create rich Ajax applications within dotCMS. The following example uses jQuery.ajax to create content in a custom Content Type.

Consider the following Blogpost Content Type:

Example Blogpost Content Type

The URL Map Pattern is configured as /Blogpost/{title}. (Note that in a real world application a custom “Url Title” field would be used instead, to convert the title to a URL-friendly string).

The below example page uses jquery to post data to dotCMS. This is the page in its entirety, and this code can be cut and pasted into a blank template, for example purposes. The form data is first captured as a JSON object, then that data is PUT to the dotCMS server via an $.ajax call. If the Blogpost Content Type has been configured as displayed above, this will create a new content item with the values that passed via the $.ajax call.

<html>
  <head>
    <title>dotCMS REST Content Save</title>
    <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet">
    <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script type="text/javascript" src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>

    <script type="text/javascript" >

      $(document).ready(function() {

        $("#newPost").submit(function(e) {
          e.preventDefault();

          var dataObj={'title': $('#title').val(),
          'publishDate': $('#publishDate').val(),
          'body': $('#body').val(),
          'categories': $('#categories').val().join(','),
          'tags': $('#tags').val(),
          'stName':'Blogpost'};

          $.ajax({
            url: '/api/content/publish/1',
            type: 'PUT',
            cache:false,
            data: dataObj,          
            beforeSend: function (request){
              // This sends the user who authenticates against the dotCMS server
              // In a real world example, you could use session based authentication
              request.setRequestHeader("DOTAUTH", window.btoa("admin@dotcms.com:admin"));
            },

            success: function(data,status,xhr) {
              alert("Success: "   );
              window.location = "/Blogpost/"+$('#title').val();
            },
            error: function(data,status,xhr) {
              alert("fail: " + data );
            console.log(data );
            },
          });
        });
      });

    </script>
  </head>
  <body>
    <div class="container">
      <div class="row">
        <form id="newPost" action="">
          <label for="title">Title</label>
          <input type="text" name="title" id="title"/>

          <label for="publishDate">Publish Date</label>
          <input type="text" name="publishDate" value="2013-07-28 10:34" id="publishDate"/>

          <label for="categories">Categories</label>
          <select id="categories" name="categories" multiple="multiple">
            <option value="design">Design</option>
            <option value="development">Development</option>
            <option value="frontEndDevelopment">Front End Development</option>
            <option value="nosql">NoSQL</option>
            <option value="projectManagement">Project Management</option>
          </select>

          <label for="mainimg">Main Image</label>
          <input type="file" name="mainImage" id="mainImage"/>

          <label for="tags">Tags</label>
          <input type="text" name="tags" id="tags"/>

          <label for="body">Body</label>
          <textarea id="body" name="body"></textarea>
          <div>
          <input type="submit" class="btn" id="Post" name="Post" value="Post"/>
          </div>
        </form>
      </div>
    </div>
  </body>
</html>

Note that the option list for categories can be generated automatically using Velocity and the Categories viewtool.

This page creates the content and then redirects to the URL Map detail page to display the newly created content.

Note that we allow jquery to encode the data as application/x-www-form-urlencoded, which is the default jquery encoding.

Sending Binary Fields Using jquery

In order to send a file to the Binary field we need to construct a FormData object in javascript. This API can be found in all modern browsers and is generally safe to use.

$(document).ready(function() {
    $("#newPost").submit(function(e) {
        e.preventDefault();

        var dataform=new FormData();

        var json={
            'title': $('#title').val(),
            'publishDate': $('#publishDate').val(),
            'body': $('#body').val(),
            'categories': $('#categories').val().join(','),
            'tags': $('#tags').val(),
            'stName':'Blogpost'
        };
        dataform.append('json',JSON.stringify(json))

        dataform.append('file', document.getElementById('mainImage').files[0]);


        $.ajax({
            url: '/api/content/publish/1',
            type: 'PUT',
            data: dataform,
            processData: false,
            contentType: false,
            success: function(data,status,xhr) {
                window.location = "/Blogpost/"+$('#title').val();
            }
        });
    });
});

Notes:

  • In order to ensure that a multipart/form-data request is sent to the server, processData and contentType must be disabled in the call to jquery.ajax.
  • The json data is added to the dataform with the name “json”.
    • This enables the dotCMS server to recognize that the value is JSON encoded data.
    • Due to limitations in the FormData interface the content-type of the body part can't be set to JSON, and it is instead set to text/plain by default.
    • However the dotCMS server will process it as JSON if either the content-type is set to JSON (application/json) or if the name of the body part is 'json'.
    • The same process is used for 'xml' and 'urlencoded' formats.
      • These formats must be added using the name “xml” and “urlencoded” to notify the dotCMS server of the format being used.

Important: When sending several Binary fields in the FormData object make sure to respect the Binary field order in the Content Type.

Employee Profile form with Relationship and Binary field

<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<script type="text/javascript" >
    $(document).ready(function() {
        $("#submitEmployee").submit(function(e) {

            e.preventDefault();

            var dataObj={        
                'ipAddress': "$request.getRemoteAddr()",
                'stName':'Employee',
                'Department-Employee': '+structureName:Department +identifier:' + id
            };

            if($('#department').val() != undefined && $('#department').val().length > 0 && $('#department').val() != 'Select your Department'){
                dataObj.identifier = $('#department').val();
            } else {
                alert("Please select a department");
                $( "button" ).removeClass( "disabled" ).addClass( "btn-primary" );
                return;
            }
            //How to use the FormData() - https://developer.mozilla.org/en/docs/Web/API/FormData    
            var dataform=new FormData();

            if($('#firstName').val() != undefined && $('#firstName').val().length > 0){
                dataObj.firstName = $('#firstName').val();
            }
            if($('#lastName').val() != undefined && $('#lastName').val().length > 0){
                dataObj.lastName = $('#lastName').val();
            }
            dataObj.gender = $('input[name=gender]:checked').val();

            if($('#jobTitle').val() != undefined && $('#jobTitle').val().length > 0){
                dataObj.jobTitle = $('#jobTitle').val();
            }
            if($('#phone').val() != undefined && $('#phone').val().length > 0){
                dataObj.phone = $('#phone').val();
            }
            if($('#email').val() != undefined && $('#email').val().length > 0){
                dataObj.email = $('#email').val();
            }
            if($('#mobile').val() != undefined && $('#mobile').val().length > 0){
                dataObj.mobile = $('#mobile').val();
            }
            if($('#fax').val() != undefined && $('#fax').val().length > 0){
                dataObj.fax = $('#fax').val();
            }
            if($('#userId').val() != undefined && $('#userId').val().length > 0){
                dataObj.userId = $('#userId').val();
            }
            dataObj.seniorManagement = $('#seniorManagement').is(':checked')

            //convert the dotObject map to a json object
            ##Create a json key using json as value map and something already expected
            dataform.append('json',JSON.stringify(dataObj))

            //append the binary file to the json object - If more than one binary field is present on the Content Type, files should be appended ***in order that the binary fields occur on the Content Type**
            ## Append files as photo, photo(1), photo(2), etc., in order
            dataform.append('file', document.getElementById('photo').files[0]);

            $('requestBtn').attr('disabled', true);
            $('requestBtn').prop('disabled', true);
            $( "button" ).removeClass( "btn-primary" ).addClass( "disabled" );
            $.ajax({
                url: '/api/content/publish/1',
                type: 'PUT',
                cache:false,
                data: dataform,
// see article here http://www.mattlunn.me.uk/blog/2012/05/sending-formdata-with-jquery-ajax - on avoiding non-strings being sent thru jQuery.param() by setting processData and contentType to false
                processData: false,
                contentType: false,

                beforeSend: function (request){
                    //This sends the user who authenticates against the dotCMS server
                    //In a real world example, you could use session based authentication
                    request.setRequestHeader("DOTAUTH", window.btoa("admin@dotcms.com:admin"));
                },       

                success: function(data,status,xhr) {
                    console.log("works!");
                    var a = xhr.getAllResponseHeaders();
                    var id = a.substring(a.indexOf('identifier: ') + 'identifier: '.length , a.indexOf('\n', a.indexOf('identifier: ') + 'identifier: '.length));
                            //redirect to thank you page, passing identifier of employee                    
                            window.location="/about-us/our-team/success?id="  + id;
                },

                error: function(data,status,xhr) {
                    $('requestBtn').attr('disabled', false);
                    $('requestBtn').prop('disabled', false);
                    $( "button" ).removeClass( "disabled" ).addClass( "btn-primary" );
                    console.log(data);
                    alert("Uh Oh, your request failed. Please check your entries and try again");
                }
            }); //End $.ajax
        }); // End $("#submitEmployee").submit
    }); // End $(document).ready

</script>

<div class="form-container">

    <!-- Form Name -->

    <hr>

    <form class="form-horizontal"  role="form"  id="submitEmployee">
        <input type="hidden" name="stName" value="Employee">
        <input type="hidden" name="languageId" value="1">
        <input type="hidden" name="contentHost" value="demo.dotcms.com">

        <div class="form-group">
            <label class="col-sm-3 control-label" for="firstName" class="required">First Name: <span class="required">*</span></label>
            <div class="col-sm-8">
                #if($user)
                    <input id="firstName" class="form-control" type="text"  name="firstName"  value="$user.firstName">
                else
                    <input id="firstName" class="form-control" placeholder="Enter your first Name" type="text"  name="firstName"  value="">
                #end
            </div>
        </div>

        <div class="form-group">
            <label class="col-sm-3 control-label" for="lastName">Last Name: <span class="required">*</span></label>
            <div class="col-sm-8">
                #if($user)
                    <input id="lastName" class="col-sm-12" name="lastName" type="text" placeholder="$user.lastName" value="$user.lastName" required>
                #else
                    <input id="lastName" class="col-sm-12" name="lastName" type="text" placeholder="Enter your last name" value="" required>
                #end
            </div>
        </div>

        <div class="form-group">
            <label class="col-sm-3 control-label" for="gender">Gender: </label>
            <div class="col-sm-8">
                <input type=radio id="genderMale"  name="gender" value="male" checked="true"> <label for="genderMale">Male</label> &nbsp;&nbsp;
                <input type=radio id="genderFemale"  name="gender" value="female" > <label for="genderFemale">Female</label> &nbsp;&nbsp;
            </div>
        </div>

        <div class="form-group">
            <label class="col-sm-3 control-label" for="jobTitle">Job Title: </span></label>
            <div class="col-sm-8">
                <input id="jobTitle" class="col-sm-12" name="jobTitle" type="text" placeholder="Job Title" value="">
            </div>
        </div>

        <div class="form-group">
            <label class="col-sm-3 control-label" for="email">Email: </span></label>
            <div class="col-sm-8">
                #if($user)
                    <input id="email" class="col-sm-12" name="email" type="text" value="$user.emailAddress">
                #else
                    <input id="email" class="col-sm-12" name="email" type="text" placeholder="Email" value="">
                #end
            </div>
        </div>

        <div class="form-group">
            <label class="col-sm-3 control-label" for="phone">Phone: </span></label>
            <div class="col-sm-8">
                <input id="phone" class="col-sm-12" name="phone" type="text" placeholder="Phone Number" value="">
            </div>
        </div>

        <div class="form-group">
            <label class="col-sm-3 control-label" for="mobile">Mobile: </span></label>
            <div class="col-sm-8">
                <input id="mobile" class="col-sm-12" name="mobile" type="text" placeholder="Mobile" value="">
            </div>
        </div>

        <div class="form-group">
            <label class="col-sm-3 control-label" for="fax">Fax: </span></label>
            <div class="col-sm-8">
                <input id="fax" class="col-sm-12" name="fax" type="text" placeholder="Fax" value="">
            </div>
        </div>

        <div class="form-group">
            <label class="col-sm-3 control-label" for="seniorManagement">Management: </span></label>
            <div class="col-sm-8">
                <input type="checkbox" class="col-sm-12" name="seniorManagement" id="seniorManagement" type="text" value="">
            </div>
        </div>

        <div class="form-group">
            <label class="col-sm-3 control-label" for="photo">Photo: </span></label>
            <div class="col-sm-8">
                <input type="file" class="col-sm-12" name="photo" id="photo" type="text" placeholder="photo" value="">
            </div>
        </div>

        ## Select the related Department data
        <div class="form-group">
            <label class="col-sm-3 control-label" for="fund">Department: </label>
            <div class="col-sm-8">
                <select class="form-control col-sm-12" id="department" name="department" required>
                    <option>Select your Department</option>
                    #foreach($department in $dotcontent.pull("+structureName:Department +(conhost:48190c8c-42c4-46af-8d1a-0cd5db894797 conhost:SYSTEM_HOST)",0,"Department.departmentName"))
                        <option value="$department.identifier">$department.departmentName</option>
                    #end
                </select>
            </div>
        </div>

        #if($user)
            <input type="hidden" name="userId" id="userId" value="$user.userId">
        #end

        <hr>

        <!-- Button -->
        <div class="text-center">
            <button id="requestBtn" name="singlebutton" class="btn btn-primary btn-large">Submit Profile</button>
        </div>

    </form>
</div>  ##end <div class="form-container">