CSOM – ContentType and CAML Queries

To retrieve the ContentType of a ListItem from the ListItemCollection using the GetItems method, there are two approaches that work.

  1. If you are not specifying ViewFields in your CAML query then in your Load method you need to Include the ContentType. e.g.

clientContext.Load(listItems, items => items.Include(item => item.ContentType));

  1. If you CAML query includes ViewFields then two modifications are required. The ViewFields needs to include the ContentTypeId field and the Load method needs to include the ContentType. e.g.
<ViewFields><FieldRef Name='ContentTypeId' /></ViewFields>

clientContext.Load(listItems, items => items.Include(item => item.ContentType));

Advertisements

Azure (not so) Logic Apps

As with any (relatively) new Azure  app there is always pain mixed in with the pleasure. The simplicity of the Logic Apps Designer can throw in curve balls that can only be handled in the Code View.

A good example of this is the SQL -Get Row connector and what happens if the row is not found.

logic-app-get-row

The default logic here is to look for the row and then progress if the Row Id can be matched, and in the Designer view this is all handled for you. But what if you want a condition where you want to handle this failure.  The Designer allows us to put in a check for the failure, although you have to edit it in Advanced mode. The problem is that the Designer does not let you allow ‘Failed’ as a valid option.

logic-app-condition

In the Designer view this is not obvious (at the moment) so you need to switch to the Code view. The default runAfter option (for the Condition) is set to ‘Succeeded’

"runAfter" {
"Get_row" : [ "Succeeded" ]
}

So what we need to do is add ‘Failed’ as a valid option

"runAfter" {
"Get_row" : [ "Succeeded", "Failed" ]
}

The ‘Get row’ is then able to succeed by failure when no matching row is found and the Condition check will be evaluated correctly.

Google Recaptcha verification

Using the Google Recaptcha verification API should be fairly straight forward. The one thing the documentation does not make clear is how to POST to the SiteVerify endpoint. So after playing around with the various options in Postman, I have found the following code works from the server side using C#.

                HttpClient httpClient = new HttpClient();

                KeyValuePair<string, string> secret = new KeyValuePair<string, string>("secret", recaptcha.Secret);
                KeyValuePair<string, string> response = new KeyValuePair<string, string>("response", recaptcha.Response);

                List<KeyValuePair<string, string>> postData = new List<KeyValuePair<string, string>>();
                postData.Add(secret);
                postData.Add(response);

                using (var content = new FormUrlEncodedContent(postData))
                {
                    content.Headers.Clear();
                    content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");

                    var recaptchaResponse = await httpClient.PostAsync(RecaptchaAPIUrl, content);

                    var returnValue = recaptchaResponse.Content.ReadAsStringAsync().Result;

                    var vr = JsonConvert.DeserializeObject<VerifiedResponse>(returnValue);

                    return this.Ok(vr);
                }

Postman – Including the Header Date

I have found Postman to be a very useful tool for testing Web Api’s, but according to Postman’s documentation, sending certain restricted headers can be an issue. Using Postman Interceptor allows you to overcome this restriction but I came across one problem when setting the restricted Date header.

I had been using the Pre-requests scripts to set the Date dynamically using environment variables, again following the documentation. However, each time I submitted the request my Date header was coming through as null. The problem turned out to be the date format as this needs to be in GMT format and fortunately the fix turned out to be relatively simple.

Javascript has a toGMTString() method that works but the method is being deprecated so the toUTCString() works just as well so the environment variable becomes

postman.setEnvironmentVariable('timestampHeader',new Date().toUTCString());

CSS Specificity

Came across this very useful tool for comparing CSS Specificity.

Specificity Calculator

This is very useful for identifying why your CSS might be overridden by competing styles in other files.

SharePoint Client – Folder and Files

If you know the relative Url of the folder within SharePoint there is a straight forward way to access the files within that folder.

using Microsoft.SharePoint.Client;
...
using (ClientContext clientContext = new ClientContext(&amp;quot;https://something.sharepoint.com/sites/mysite/&amp;quot;))
{
    Folder folder = clientContext.Web.GetFolderByServerRelativeUrl(&amp;quot;/sites/mysite/root_folder/sub_folder&amp;quot;);

    // Load the Folder and Files into the ClientContext so we can access them
    clientContext.Load(folder);
    clientContext.Load(folder.Files);
    clientContext.ExecuteQuery();

    foreach (var item in folder.Files)
    {
        // Load each file into the ClientContext to access the file information
        context.Load(item);
        context.ExecuteQuery();
    }
}

Skype for Business (Lync) Web App

When you have the Skype for Business app installed on your machine you cannot open the meeting in a browser (web app) without it trying to force you to use the full application. This can be frustrating because you may want to join a meeting for client who is not part of your business. In my scenario:

  • I was logged out of my SfB desktop app
  • Opened IE and pasted in the URL for the meeting.
  • This then tries to open the desktop app and fails.
  • Since Edge was my default browser the system then tries to open Edge and takes you to the download page for the Lync Web App. Since Edge does not work with SfB then I cannot access my meeting.

The solution comes in the form of a query string parameter appended to the URL. Open IE, enter the URL to the conference call and append ?SL=1 to the end and press ENTER.