Developer Life

No less, no more. Just live between code.

How to work with Choice field in SharePoint 2013 by REST?

For last couple of days I was working with surveys where as you know we need to create choice field for each question. I like REST approach then it was my only option. The main reason is because is more clear and straightforward then JavaScript CSOM.

We will need a support functions for working with REST services, specially POST call and GET call:

GetFieldsFromCollectionREST = function (restUrl, properties) {
    var values = [];
    select = "$select="
    if (properties.length > 1) 
        select += _(properties.slice(1)).reduce(function (memo, item) { return memo + "," + item }, properties[0]);
    else 
        select += properties[0];
    if (restUrl.indexOf('?') > -1) 
        restUrl = restUrl + "&" + select;
    else 
        restUrl = restUrl + "?" + select;

    $.ajax({
        url: restUrl,
        type: "GET",
        async: false,
        headers: {
            "accept": "application/json;odata=verbose",
        },
        success: function (data) {
            if (data.d && data.d.results) {
                _(data.d.results).each(function (res) {
                    var value = {};
                    _(properties).each(function (fst) {
                        value[fst] = res[fst];
                    });
                    values.push(value);
                });
            }
        },
        error: function (err) {}
    });
    return values;
};

PostCreateByREST = function (restUrl, data) {
    var result;
    $.ajax({
        url: restUrl,
        async: false,
        type: "POST",
        data: data,
        contentType: "application/json;charset=utf-8;odata=verbose",
        headers: {
            "accept": "application/json;odata=verbose",
            "X-RequestDigest": $("#__REQUESTDIGEST").val(),
            "IF-MATCH": "*",
        },
        success: function (data) {
            result = true;
        },
        error: function (err) {
            result = false;
        }
    });
    return result;
};

Let’s go create our choice field by this code snippet:

var dataFieldCreation = "{ '__metadata': { 'type': 'SP.FieldChoice' }, 'Title': 'New choice Field', 'FieldTypeKind': 6,'Required': 'false',  'Choices': { 'results': ['Choice1', 'Choice2', 'Choice3'] } }";
var success = PostCreateByREST("<siteUrl>_api/Web/Lists/GetByTitle('<listName>')/fields", dataFieldCreation);

Beck to back let’s go to get your new created choices by following code snippet:

var choiceFieldValue = GetFieldsFromCollectionREST("<siteUrl>/_api/Web/Lists/GetByTitle('<listName>')/fields?$filter=TypeAsString eq 'Choice'", ["Title", "Choices"]);
var choices = choiceFieldValue.results;

All source code is on my github gist here.

I hope this will help you with facing a new challenges with pure JavaScript approach.

Get Calendar recurrent events by CSOM in SharePoint 2013

Let’s say you have an experience with getting this information from Server OM in SharePoint like this:

SPQuery query = new SPQuery();
query.ExpandRecurrence = true;

query.Query = String.Format(
"<Where><DateRangesOverlap><FieldRef Name='{0}' />" +
"<FieldRef Name='{1}' /><FieldRef Name='{2}' />" +
"<Value Type='DateTime'><Year/></Value></DateRangesOverlap>" +
"</Where><OrderBy><FieldRef Name='{3}' /><FieldRef Name='{0}' /></OrderBy>",
Fields.StartDate,
Fields.EndDate,
Fields.RecurrenceId,
orderBy);

Next sensible step is going internet and check CSOM if it contains all necessary field what you need is here.

Yes, the “ExpandRecurrence” is not there, that means when you call Calendar list it always give you back list of items as they are in the list. What are next steps?

  • You can think about create REST call on List.svc and do range on calendar, unfortunately the result is the same, just items.
  • Obviously when you call you list there is not recurrent events either.
  • Final way is call old-fashion List.asmx. You think is no longer there, don’t you? Don’t worry is there and here is how to use it.

My solution how to get all recurrent events by CSOM in SharePoint 2013 or Office 365 is on my github and here.

GetItemsFromCalendarAsmx = function (webUrl, calendarGuid) {

    wsURL = webUrl + "_vti_bin/Lists.asmx";

    var xmlCall =
        "<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'> <soap:Body>" +
        "<GetListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'>" +
        "<listName>" + calendarGuid + "</listName>" +
        "<query>" +
        "<Query>" +
        "<Where>" +
           "<DateRangesOverlap>" +
           "<FieldRef Name=\"EventDate\" />" +
           "<FieldRef Name=\"EndDate\" />" +
           "<FieldRef Name=\"RecurrenceID\" />" +
           "<Value Type='DateTime'><Year/></Value>" +
           "</DateRangesOverlap>" +
        "</Where>" +
        "</Query>" +
        "</query>" +
        "<queryOptions>" +
        "<QueryOptions>" +
            "<ExpandRecurrence>TRUE</ExpandRecurrence>" +
        "</QueryOptions>" +
        "</queryOptions>" +
        "</GetListItems>" +
        "</soap:Body></soap:Envelope>";
    var result = [];
    $.ajax({
        url: wsURL,
        type: "POST",
        dataType: "xml",
        async: false,
        data: xmlCall,
        complete: function (xData, status) {
            Core.LogMessage("Core.GetItemsFromCalendarAsmx-> url: " + wsURL + " status: " + status);
            if (status === "success") {
                var root = $(xData.responseText);
                root.find("listitems").children().children().each(function () {
                    $this = $(this);
                    var ids = $this.attr("ows_UniqueId").split(";");
                    var rec = $this.attr("ows_fRecurrence");
                    result.push({
                        "StartTime": $this.attr("ows_EventDate"),
                        "EndTime": $this.attr("ows_EndDate"),
                        "Title": $this.attr("ows_Title"),
                        "Recurrence": (rec === "1" ? true : false),
                        "Description": Core.HtmlDecode($this.attr("ows_Description")),
                        "Guid": ids[1],
                        "Id": ids[0],
                    });
                });
            }
        },
        contentType: "text/xml; charset=\"utf-8\""
    });
    return result;
};

I hope it saves you a few days time Smile

Interest recursive example in F#

Dear reader,

this post is one of series of F# example for learning and reference.

Do you know how to compute interest on investment? For example invest money once and then just wait for growing your venture 🙂

let interest (sum:float) (x:float) (years:int) : float =
    let rec imply (added:float) (percentil:float) (yearCount:int) : float =
        if(yearCount > 0) then
            let tmp = added * percentil 
            tmp + imply (tmp + added) percentil (yearCount - 1)
        else 0.0
    sum + imply sum x years

You would like to know when you invest 100 pounds for 10 years with 4% interest.

interest 100.0 0.04 10
val it : float = 148.0244285

F# rules!

ContentTypeRef is not for SharePoint Sandbox Solution

Today,

I’d like to show one oddity of sandbox solution when you are deploying list with more content types. What I used to do is defined my content types in separate element in separate feature for site collection scope. Then define list for web scope feature with list instances if necessary. Finally in my schema I used to love just reference my site content type like this:

<ContentTypeRef ID=0x010017AFB15E4A1249E9B69EA77F0E0A7D7B />

<ContentTypeRef ID=0x0100985EC700FD8941F6BBF8D193EEBBEED3 />

<ContentTypeRef ID=0x0100789adc2867414944a6c98a78d20fd93e />

Nice and neat way, no hassle free bug approach, but after deployment this in SharePoint, the list was there just with one content type and content type looks wrong, the name of content type was renamed by list’s name. There I have started to dig around, first stop was Google doesn’t really help me  in the first place. Then I omit SharePoint 2013 and found one misleading solution where the advice is to change your scope on feature for site collection one which doesn’t help or even worse to do update your list definition in feature receiver code (which is now deprecated), anyway I did by PowerShell it doesn’t help either.

After a few hours of searching and thinking where is that trickery with ContentTypeRef, just don’t use it and declare your content type in list schema again, also I found one nice article about this here. No one said you should not do it, but it seems to make another rule for sandbox . Don’t use ContentTypeRef!

Define full:

<List xmlns:ows=Microsoft SharePointTitle=ListNameFolderCreation=FALSEDirection=$Resources:Direction;Url=Lists/ListNameBaseType=0

<xmlns=http://schemas.microsoft.com/sharepoint/EnableContentTypes=TRUE>

<MetaData>

<ContentTypes>

<ContentTypeID=0x0100789adc2867414944a6c98a78d20fd93eName=xxx>

<FieldRefs>

<FieldRefID={fa564e0f-0c70-4ab9-b863-0177e6ddd247}Name=Title1 />

</FieldRefs>

</ContentType>

<ContentTypeID=0x0100985ec700fd8941f6bbf8d193eebbeed3Name=xx2 >

<FieldRefs>

<FieldRefID={fa564e0f-0c70-4ab9-b863-0177e6ddd247}Name=Title2 />

</FieldRefs>

</ContentType>

</ContentTypes>

</MetaData>

</List>

Easy SharePoint 🙂

CssRegistration is not allowed in SharePoint 2013 Sandbox

Dear reader,

today is full of surprises. I should say I have seriously started code for Office 365, I’m using pure declerative sandbox solution.

I have run into issue with CssRegistration web control which is not allowed in sandbox. The reason is here from MSDN forum:

Sandbox webparts do not execute in the same ASP.NET context as the page in which they reside, instead they execute in a distince ASP.NET context in a seperate worker process (UserCode Worker Process). SharePoint setups a make-believe world for the WebPart — specifically this make believe world consists of a single page with a single webpart zone and a single webpart — your sandbox webpart.

Once the webpart finishes execution the result is returned back to the main page. In fact, even if RegisterCssReference was not internal, there is no guarantee that the CSS could be applied, because we may have be too late in the ASP.NET page lifecycle to go do that.

This brings me to to answering your question, which is it is not currently possible to specify CSS into a page for a Sandbox Web Part.

This is copied from Mukul Sapharval.

Then I started to find any possible solution. Some guys advice to put C# code to web part or feature receiver, but this is not sensible for pure declarative sandbox. The reason is well explained here.

That means no code, finally we can use old fashioned link tag with SPUrl control which is still there and there are no mentions to go somewhere.

<link rel=”stylesheet” type=”text/css” href=”<% $SPUrl:~SiteCollection/Style%20Library/your_css.css %>” />

I believe this saves you some headache 🙂

Where is Web Part Page Maintenance in SharePoint 2013?

I have been asked this question for a while. Also some clients keep saying “I have run into some web part with some custom name and I cannot relate it to web part type, it really takes me back to change published pages and understand its content“.

After all this I decide to write little post as reference for me about this problem. Frankly I have failed to find a custom action or button for this solution. You need manually write additional url paramter(?contents=1) for your page. Like this:

pic2

When you want to do changes, please check our you page for you before you enter this settings.

I hope this can save you a lot of time to search for this again and again 🙂

Import-SPMetadataWebServicePartitionData issue SharePoint 2013

This reference mainly for future reference, when you are importing Managed Metadata Service Application export to new SharePoint farm. You will probably run into error message “You do not have permission to use the bulk load statement”.

Don’t worry it is not something what you are doing bad, to this is not paid much attention when you are designing permission for your service account in SharePoint farm. The solution is simple.

Go to Internet Information Service (IIS) Manager find application pool which is handle your Managed Metadata Service and read service account from it.

Then go to you SQL Management Studio, connect to your SharePoint SQL Server and set bulk permission for above metioned service account like this:

pic1

I hope this helps you 🙂

JavaScript IntelliSense for SharePoint 2013 in Visual Studio 2012

Hello reader,

today I’d like to point out nice trick how to enable JavaScript intellisense for your SharePoint 2013 solution in Visual Studio 2012.  We can enable JavaScript in other web project by file “_reference.js” in Scripts folder, but this is an issue in SharePoint 2013 project which can cause troubles when you are use jQuery or KnockOut javascript libraries. The process of adding those is nice and simple. You need it once, as preparation, locate your JavaScript libraries on one place.

Go to Tools in Visual Studio 2012

js2

Then go to Text Editor -> JavaScript -> IntelliSence -> References

js3

By triple dot button to chose your destination of prefered js libraries. Then just go back to your code and try:

JS1

For reference, for all web project (include SharePoint 2013 app model) you can use approach by “_references.js” file like this:

/// <reference path=”jquery-1.8.2.js” />
/// <reference name=”MicrosoftAjax.js” />
/// <reference path=”~/_layouts/15/init.js” />
/// <reference path=”~/_layouts/15/SP.Core.js” />
/// <reference path=”~/_layouts/15/SP.Runtime.js” />
/// <reference path=”~/_layouts/15/SP.UI.Dialog.js” />
/// <reference path=”~/_layouts/15/SP.js” />
/// <reference path=”~/_layouts/15/SP.Publishing.js” />
/// <reference path=”~/_layouts/15/knockout-2.3.0.debug.js” />
/// <reference path=”~/_layouts/15/knockout-2.3.0.js” />

Enjoy your coding 🙂

Show Favicon in Internet Explorer for SharePoint 2013

For all SharePoint developers,

I assume all of you will struggle with change favicon for SharePoint 2013 and show it in Internet Explorer. Mainly because the logic how to pick that favicon was changed between version 2010 and 2013.

The most recommended solution is located favicon icon in page layuots in your SharePoint farm and put SharePoint SPShortcutIcon control in your master page:

<SharePoint:SPShortcutIcon ID=”SPShortcutIcon1″ IconUrl=”/_layouts/15/images/your_solution/favicon.ico” runat=”server”></SharePoint:SPShortcutIcon>

If you are still failing to see your favicon in Internet explorer, try to recreate your icon by http://www.favicon.cc/.

It really helped me in my process, I was stuck with this for hours to realize that icon is wrong.

I hope it saves you time 🙂

Caesar Cipher

Hello guys,

I’m currently reading book “The Code Book” by Simon Singh. I hope all of you know it already. The post of today is only about fun coding and boredom on my way home from work. I will show you my implementation of first substitution cipher “Caesar Cipher”. The whole sense of it is encoding plaintext by replacing each letter of it by one cipher key. The cipher key is created based on chosen word or phrase, where every letter is used just once and the rest is adding from alphabet.

For example you choose phrase “I love coding for fun” and you cipher key is: “ilovecdngfruqwtypashjkzxbm”

Then from your cipher key it would be created cipher table like this one:

a b c d e f g h i j k l m n o p q r s t u v w x y z
i l o v e c d n g f r u q w t y p a s h j k z x b m

Now we can use this cipher table as our symmetric key for Caesar cipher. For example we want to encode this text:

“I finished a computer science degree last year, worked about a year in the Java EE stack. I liked requirements engineering and more ‘management stuff’ in university, but let’s face it: you tend to be driven to be a programmer.”

Result is here:

“g cgwgsnev i otqyjhea sogewoe vedaee uish beia, ztarev iltjh i beia gw hne fiki ee shior. g ugrev aepjgaeqewhs ewdgweeagwd iwv qtae ‘qiwideqewh shjcc’ gw jwgkeasghb, ljh ueh’s cioe gh: btj hewv ht le vagkew ht le i yatdaiqqea.”

Now I can show you my simple implementation.

How to create cipher text:

static List CreateCipherKey(string seed)
{
    List res = new List();
    seed.ToLower().ToCharArray().ToList()
        .ForEach(c => { if (!res.Contains(c) && !string.IsNullOrWhiteSpace(c.ToString())) res.Add(c); });
    AllChars.ForEach(c => { if (!res.Contains(c)) res.Add(c); });
    return res;
}

AllChars is collection all English letters.

Encode our plain text:

static string EncodePlainText(string text, Dictionary<char, char> cipherTable)
{
    string res = string.Empty;
    text.ToLower().ToCharArray().ToList().ForEach(c =>
        {
            if (cipherTable.ContainsKey(c)) res += cipherTable[c];
            else res += c;
        });
    return res;
}

Decode our cipher:

static string DecodeCipherText(string cipher, Dictionary<char, char> cipherTable)
{
    string res = string.Empty;
    cipher.ToCharArray().ToList().ForEach(c =>
    {
        if (cipherTable.ContainsValue(c)) res += cipherTable.Single(p => p.Value == c).Key;
        else res += c;
    });
    return res;
}

As you see I love coding for fun 🙂 source code

Happy Coding!