2

I'm new to the Valence API and D2L(Brightspace) and I'm currently having issues with sending API Requests through my WordPress Enrollment form. Below are some steps as to what I am trying to achieve:

  1. A Student Signs up/enrolls in a course through an enrollment form on my WordPress site
  2. The enrollment passes the new student information to the Valence API doAPIRequest function in sample.js
  3. The Ajax call in sample.js contains an action called 'example_wordpress_action' which is defined in functions.php. This is where the API requests are made.
  4. The main problem is that when I try to use a post request, there is always a 400 Bad Request returned. However, I am able to apply a GET/ whoami request with out any issues. Is there a chance that the issues are with the way the user information is being entered?

Below is a copy of the format that is being used to send the created users information (The RoldId is being used on the D2L site and I am using method 'POST' and API request of '/d2l/api/lp/1.4/users/'):

{
  "OrgDefinedId": "SBoateng",
  "FirstName": "Samuel",
  "MiddleName": "",
  "LastName": "Boateng",
  "ExternalEmail": "daerdocta@gmail.com",
  "UserName": "SBoateng",
  "RoleId": 103,
  "IsActive": true,
  "SendCreationEmail": false
}

This is what is returned from the request:

Unexpected non-JSON response from the server: 
Array
(
    [headers] => Array
        (
            [cache-control] => private
            [content-length] => 0
            [server] => Microsoft-IIS/7.5
            [x-powered-by] => ASP.NET
            [x-xss-protection] => 0
            [date] => Tue, 23 Jun 2015 18:35:05 GMT
            [connection] => close
        )

    [body] => 
    [response] => Array
        (
            [code] => 400
            [message] => Bad request
        )

    [cookies] => Array
        (
        )

    [filename] => 
)
massi
  • 31
  • 3
  • Welcome to stackoverflow. Maybe you could edit the question to more explicitly tell us what the problem is and give possible error / debug output? – Jörn Hees Jun 09 '15 at 17:12
  • Hello, I've added a few changes to the original post. the main problem I am having is that I'm not able to send the API request. – massi Jun 09 '15 at 17:36
  • Added desire2learn tag as recommended by D2L's support guidelines. This doesn't look like its a straightforward question and answer, but more of an attempt to debug your code or get started; maybe you'd be better off visiting D2L's dev community forums. Also, providing them with a network trace of your exact HTTP request/response would likely help them assist you better. – Viktor Haag Jun 16 '15 at 23:01
  • It would be very helpful to see the exact HTTP Request, but the right place for this back and forth debugging is the Brightspace developer community forums, not here. – Viktor Haag Jun 24 '15 at 12:24

2 Answers2

1

According to the documentation for the create-user route, a 400 status code as a response indicates one of two things: you've provided invalid data for your new user record somehow, or the back-end service was (for some reason) unable to create the new user record (very rare, but it does happen). In the second of those cases, you'd get a more detailed message in the error description indicating the failure to create. As you didn't get this, the most likely reason is one of these:

  • You're not sending what you think you're sending; it's somehow badly formatted.

  • You're providing an invalid RoleId -- it was valid in the environment you tested under, but in the production environment, that RoleId doesn't exist. This happens sometimes, but in this case, I suspect not. To verify, try fetching back the RoleId by Id first, and view those results.

  • You're providing a UserNamethat already exists in the system: this property is the ID you use to identify yourself when you log in to the Brightspace system, so it has to be unique. Occasionally clients will find that the "temporary test" UserName they're using already exists in their back-end service, for whatever reason, and this can cause surprising failures. You can try validating by fetching back a user by that UserName first to validate you don't already have a record for that user.

Viktor Haag
  • 3,253
  • 1
  • 15
  • 21
  • I tested this same json string in the API test tool but it was able to send through and create the user with out any issue. I also checked to make sure that the username that I am specifying is not in use. The roleId of 103 is also being used in the live system. – massi Jun 24 '15 at 16:31
  • If the API test tool works sending through the JSON structure as you expect, and you've verified that your back-end service (a) doesn't have a UserName of that value already, and (b) does indeed have the RoleId (and your use of the API test tool with your own LMS does seem to support both these claims), then the problem almost certainly lies with the fact that your code is not sending what you _think_ it is sending. A wirelog that shows the exact HTTP request you're sending would be very helpful here to ensure that your code is behaving how you think it is. – Viktor Haag Jun 25 '15 at 18:38
  • You were correct. The code wasn't sending a properly formatted JSON structure. It was sending through a string with the escape characters still in place. I have since corrected the issue. Thanks for your assistance. – massi Jun 26 '15 at 22:09
1

I have since been able to solve this issue with some help. below is the code that I used, in case there are others who come across this in the future.

  1. excerpt PHP where the form is kept:

                            <input class="required textInput" id="name_first" name="name_first"  size="35" maxlength="255" placeholder= "First Name"  type="text" value="<?php echo $_SESSION["student_profile"]["name_first"]; ?>" required />
                            <label class="required_lables" for="name_first"><em></em></label>
    
                            <!--  Middle Initial  -->
                            <label for="name_middle"><em></em></label>
                            <input class="textInput optional" id="name_middle" name="name_middle" size="35" maxlength="255" placeholder= "Middle Name (optional)" type="text" value="<?php echo $_SESSION["student_profile"]["name_middle"]; ?>" />
    
                            <!--  Last Name  -->
                            <input class="required textInput" id="name_last" name="name_last"  size="35" maxlength="255" placeholder= "Last Name" type="text" value="<?php echo $_SESSION["student_profile"]["name_last"]; ?>" required/>
                            <label class="required_lables" for="name_last"><em></em></label>
    
  2. Form submission page. The Ajax call is made in here:

    $_SESSION['student_profile'] = $_POST;

    $first_name=$_SESSION['student_profile']['name_first'];

    $middle_name =$_SESSION['student_profile']['middle_name '];

    $last_name =$_SESSION['student_profile']['last_name '];

    $email =$_SESSION['student_profile']['email '];

    echo '<script>';
    echo 'var data = {"OrgDefinedId": "'. $orgDefinedId .'",  "FirstName": "'. $first_name .'",  "MiddleName": "'. $middle_name .'",  "LastName": "'. $last_name .'",  "ExternalEmail": "'. $email .'",  "UserName": "'. $uName .'",  "RoleId": 103,  "IsActive": true,  "SendCreationEmail": false};';
    echo 'var type = "CREATE";';
    echo 'window.$vars = {dataField : data};';
    echo 'window.$vartype = {typeField : type};';
    echo 'doAPIRequest();';//direction to js file with the ajax call
    echo '</script>';
    
    ?>
    
  3. Ajax that is used in wordpress: The action used is called example_wordpress_action and it is defined in functions.php

    function doAPIRequest() {
     var host = "myHostSite.com";
     var port = "443";
     var scheme = "https";
     var req = "/d2l/api/lp/1.4/users/";
     var method =  "POST";
     var typeAPI = window.$vartype.typeField;
     var ajaxurl = "/wp-admin/admin-ajax.php";  
     var data = window.$vars.dataField;     
     var userName = window.$varsUname.useNameField;
     var anon = "";
     var appId = myAppID;
     var appKey = myAppKey;
            $.ajax({
                url: ajaxurl,
                data: {
                    action : 'example_wordpress_action',
                    host: host,
                    port: port,
                    scheme: scheme,
                    anon: anon,
                    apiRequest: req,
                    typeapp: typeAPI,
                    apiMethod: method,
                    appUser: userName,
                    data: data,
                    appId: appId,
                    appKey: appKey
                },
                success: function(data) {
                    var output;
                    if(data == '') {
                        output = 'Success!';
                        return;
                    } else {
                        try {
                            output = JSON.stringify(JSON.parse(data), null, 4);
                        } catch(e) {
                            output = "Unexpected non-JSON response from the server: " + data;
                        }
                    }
                },
                error: function(jqXHR, textStatus, errorThrown) {               
                },
            });
    

    }

  4. Funcions.php where the request is made using wp_remote_request:

function example_wordpress_action_function() {

    $host = $_GET['host'];
    $port = $_GET['port'];
    $scheme = $_GET['scheme'];
    $data = $_GET['data'];
    $apiMethod = $_GET['apiMethod'];
    $appId = $_GET['appId'];
    $appKey = $_GET['appKey'];
    $appRequest = $_GET['apiRequest'];
    $appUserName = $_GET['appUser'];

    $data_string = json_encode($data);

    $userId = $myUserId;
    $userKey = $myUserKey;

    $authContextFactory = new D2LAppContextFactory();
    $authContext = $authContextFactory->createSecurityContext($appId, $appKey);
    $hostSpec = new D2LHostSpec($host, $port, $scheme);
    $opContext = $authContext->createUserContextFromHostSpec($hostSpec, $userId, $userKey);

    $uri = $opContext->createAuthenticatedUri($appRequest, $apiMethod);
    $headers = array( 'authorization' => 'basic ', 'accept' => 'application/json', 'content-type' => 'application/json', 'content-length' => strlen( $data_string ) ); 
    $post = array( 'method' => $apiMethod, 'headers' => $headers, 'body' => $data_string );
    $createResponses = wp_remote_request($uri, $post);
    die();
}
add_action( 'wp_ajax_example_wordpress_action', 'example_wordpress_action_function' );
add_action("wp_ajax_nopriv_example_wordpress_action", "example_wordpress_action_function");
massi
  • 31
  • 3