Martin Bodocky

No less, no more. Just live between code.

Category Archives: SharePoint

70-489 Developing Microsoft SharePoint Server 2013 Advanced Solutions – Preparation links

Hello guys,

This list is not exhaustive, and i will still try to polish some links and add new ones, As you can see I haven’t covered all topics like monitoring of scalability of issues.

Please let me know if something is not correct, this is also my main source to learn, I haven’t passed the exam yet.

I hope this information helps you,  I’m quite excited about this :)

Design and Implement Search (15-20
percent)

Query Search.

  • build search queries using FQL (FAST Query Language) and
    KQL (Keyword Query Language)

Customize search
results.

Customize content
processing.

  • implement content processing extensions (entity
    extraction)

Implement BCS (Business Connectivity
Services) (10-15 percent)

General information: http://msdn.microsoft.com/en-us/library/jj163782.aspx

Create a model.

Create external
content types.

  • use WCF (Windows Communication Foundation) (like 2010,
    deprecated?)

Implement
authorization and authentication.

  • use pass-through
  • use BCS Identity and User Identity
  • use a custom model

Create custom
connectors.

  • implement methods (including Search)
  • implement security trimming
  • implement configuration properties
  • implement caching

Access BCS data.

  • use BCS Web Parts
  • use BCS data in workflows
  • use the server-side object model

Implement
client-side BCS.

  • use caching
  • use Microsoft Office apps
  • use Microsoft Visual Studio Tools for Office
  • use SQL replication
  • implement authorization and authentication

Implement User Profiles and Customize
Social Workload (15-20 percent)

Manage user profile
properties.

Manage feeds.

Access user profile
data.

  • use Web Services (deprecated)

Implement ECM (Enterprise Content
Management) and WCM (Web Content Management) (15-20 percent)

Implement a
multi-lingual site.

  • publish pages
  • create source and target labels
  • create channels
  • implement multi-language site navigation

Implement
E-discovery.

  • export discovery sets
  • manage permissions for hold

Implement SEO
(Search Engine Optimization).

  • customize a site map
  • maintain SEO configuration properties
  • maintain SEO properties on term

Implement content
management.

  • create information management policies (the same as
    2010)

Implement a
publishing page.

  • add field controls to a page layout
  • add web parts to a page layout
  • inherit content types

Design for Performance and
Troubleshooting (15-20 percent)

Design solutions to
handle a high-traffic site.

  • create a scalable aggregator(?)

Design client
applications for performance.

Monitor and mitigate
performance and scalability issues.

Implement Managed Metadata Service (MMS) (15-20 percent)

Generallinks:

http://technet.microsoft.com/en-us/library/ee424403.aspx

http://technet.microsoft.com/en-us/library/ee519603.aspx

http://msdn.microsoft.com/en-us/library/jj163949.aspx

Manage term sets.

  • re-use terms
  • manage term properties
  • perform translation
  • create groups and assign permissions

Create solutions by
using MMS.

  • use Profile Pages
  • use the Product Catalog

Use an MMS API.

  • use REST in client applications
  • use managed fields

70-488 Developing Microsoft SharePoint Server 2013 Core Solutions – Preparation links

Wrap Web Part Title in SharePoint 2013

Dear reader,

you probably know how it is spend a lot of time on one design issue and then you find solution.

Do not confuse yourself with google with SharePoint 2007/2010 stuff like:

.ms-WPTitle nobr { white-space: normal !important; }
or
.ms-WPHeaderTD nobr { word-wrap: break-word !important; white-space: wrap !important; }

The SharePoint 2013 working version:

.ms-webpart-titleText nobr span {white-space:normal !important;}

I hope it helps!

Having a great patience with SharePoint 2013 :)

SharePoint 2013 Developer Certifications are out! (Unofficial)

Hello dear reader,

I hope you are excited as I am. The new SharePoint 2013 certification for developers are out!

Today we can see, whole certification path for SharePoint developers. The new title is

Microsoft Certified Solutions Developer (MCSD): SharePoint Applications

It contains two ways, one for front-end and one for back-end:

Frond-end contain:

Back-end contain:

  • 70-488 Developing Microsoft SharePoint Server 2013 Core Solutions

    (syllabus)

  • 70-489 Developing Microsoft SharePoint Server 2013 Advanced Solutions

    (syllabus)

The last two are still in development, but I hope it will be available some beta exams.

I hope this information make you happier!

KeywordQuery doesn’t work or confusion between search namespaces

Hello all,

Today I have survived the huge confusion, I wanted create a simple server side functionality for search on SharePoint 2013. Please look on following code which was mentioned not working with exception:

Your search cannot be completed because no Search service is available. Contact your administrator for more information.

p33

I thought what is that? What can I do? I have checked central admin, all seem to be right, I have tried google, someone said in case of SharePoint 2010, it’s broken. Ok I have recreated search service application, and it was still there.

In the first time I saw that KeywordQuery is marked as obsolete with nice message “This class is obsolete now. It will be totally removed in O16 codebase and should not be used in new applications.”. I thought fine this is not version O16, they just try to scare us, but no this object doesn’t work at all!

After more digging and searching I found the solution, I have used all time this wrong assembly. The updated class for using search functionality is Microsoft.Office.Search.Query, they removed word Office from product but still is heavily using in API.(as you can see my previous post about client side query there is used KeywordQuery from Microsoft.SharePoint.Client.Search.Query which was even more questionable).

The solution is just replace these assemblies and be careful which assembly you are going to reference to your solution:

using System;
using System.Data;
using System.Linq;
using Microsoft.Office.Server.Search.Query;
using Microsoft.SharePoint;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            using (SPSite siteCollection = new SPSite("http://siteUrl/"))
            {
                KeywordQuery keywordQuery = new KeywordQuery(siteCollection);
                keywordQuery.QueryText = "PopulateNewFields";
                SearchExecutor searchExecutor = new SearchExecutor();

                ResultTableCollection resultTableCollection = 
                    searchExecutor.ExecuteQuery(keywordQuery);
                var resultTables = resultTableCollection.Filter("TableType", 
                    KnownTableTypes.RelevantResults);
                var resultTable = resultTables.FirstOrDefault();

                DataTable dataTable = resultTable.Table;

                foreach (DataRow resultRow in dataTable.Rows)
                {
                    Console.WriteLine("{0}", resultRow["Title"]);
                }
            }
            Console.ReadLine();
        }
    }
}

I hope it helps, if you have any queries just let me know.

Happy coding!

SharePoint 2013 Search by Client Object Model in C#

Today I have found nice way how to search on your SharePoint 2013 Online, and it is easy clean and nice. I won’t describe in more detail, just show you one little example which I hope it helps you to broaden your awareness about new SharePoint 2013 Search.

static void Main(string[] args) 
        { 
            string targetSite = @"https://xxx.sharepoint.com/"; 
            string loginName = "bbb@aaa.onmicrosoft.com"; 
            string passWord = "ccc"; 

            //we need use SecureString 
            SecureString securePassword = new SecureString(); 
            passWord.ToCharArray().ToList().ForEach(c => securePassword.AppendChar(c)); 

            using (ClientContext ctx = new ClientContext(targetSite)) 
            { 
                //new approach how to use your SharePoint Online Credentials 
                ctx.Credentials = new SharePointOnlineCredentials(loginName, securePassword); 

                KeywordQuery keywordQry = new KeywordQuery(ctx); 
                //query string 
                keywordQry.QueryText = "Test"; 

                SearchExecutor searchExecutor = new SearchExecutor(ctx); 
                //don't forget to wrap with ClientResult and call ExecuteQuery 
                ClientResult results = searchExecutor.ExecuteQuery(keywordQry); 
                ctx.ExecuteQuery(); 

                foreach (var resultRow in results.Value[0].ResultRows) 
                { 
                    Console.WriteLine("{0}", resultRow["Title"]); 
                    //for more colums to uncomment 
                    //Console.WriteLine("{0}: {1} ({2})", resultRow["Title"], resultRow["Path"], resultRow["Write"]); 
                } 
                Console.ReadLine(); 
            } 
        }

Next just proven that gives you the correct results:

clientSearch

Finnally if you want to use this approach for your SharePoint 2013 instance, just omit the credential line.

Let’s get searching!

App Permission request by example in SharePoint 2013

The Introduction

This article will describe how to gain information from you host/root web.  Discovering your app permission model with pointing out the right scopes to apply.

The Problem

Gathering information from your root web can be a significant action, when you used to work with old SharePoint environment through server object model, also the foundation of every app has hosted place, which means it is in isolation.

The Solution

As example of usage we develop simple app which gains list of people from root web. The solution contains a little code of JavaScript and results will be displayed on hosted home web page. See code below:
$(document).ready(function () {

    People = {
        element: '',
        url: '',
        init: function (element) {
            //set container element
            People.element = element;
            //create a REST url, we expect just Title and Name
            People.url = _spPageContextInfo.webAbsoluteUrl +
                "/_api/site/rootweb/lists/getByTitle('User%20Information%20List')/items?$select=Title,Name";
        },

        load: function () {
            $.ajax({
                url: People.url,
                method: "GET",
                headers: {
                    "accept": "application/json;odata=verbose",
                },
                success: People.onSuccess,
                error: People.onError
            });
        },
        onSuccess: function (data) {
            var html = '';
            if (data.d != undefined) {
                var results = data.d.results;
                html = "<table><tr><td><b>Title</b></td><td><b>Name</b></td></tr>";

                for (var i = 0; i < results.length; i++) {
                    html += "<tr><td>";
                    html += results[i].Title;
                    html += "</td><td>";
                    html += results[i].Name;
                    html += "</td></tr>";
                }
                html += "</table>";
                if (results.length == 0) html = "<b>No results.</b>";
            }
            else html = "<b>No data for your app, probably it doesn't have necessary permission.</b>";

            People.element.html(html);
        },

        onError: function (err) {
            alert(JSON.stringify(err));
        }
    }

    People.init($("#peopleDiv"));
    People.load();
});

You should keep in mind, when your app doesn’t have particular permission for do action the REST web service give you back this message:

p24

But this message is received as response from our calling as we can see from above source code, also we tested this situation and give the user a clue what’s happening:

p25

And now we are going to set up app permission, start in Visual Studio, click on AppManifest.xml and choose tab called, you can see below:

p26

We are select site collection scope, because in our example we are going to gain information from list of users for whole site collection, and set permission for Read, we do not need more.

p27
 Then redeploy the app and we can see the SharePoint asks us for permission:
 p28

And finally our list of user on the site collection:

p29

The source code is prepare to investigate here.

The Conclusion

The purpose of app permissions management is to manage the ability of apps to access and use internal SharePoint 2013 resources and perform tasks on behalf of users. SharePoint 2013 apps provide a wide variety tools and functionality for deployment, for our purpose I will describe two mandatory things which we should know about App permission request scopes and app permission request.

App permission request scopes

The SharePoint uses app permission request scopes and permission requests to specify the level at which the app is intended to run, and the permission level that is assigned to the app. The app permission request scope indicates the location within the SharePoint hierarchy where a permission request will apply. We identify following permission request scopes for SharePoint app:

If an app is granted permission to one scope, the permission also applies to the children of that scope. For example, if an app is granted permission to a web site by using the web site scope, the app is also granted permission to each list that is contained within the web site, and also all list items within each list.

App permission requests

App permission requests are collections of permissions that enable apps to perform specific tasks, the SharePoint include four request levels listed below:

  • Read-Only – It enables apps to view pages, list items, and download documents, the including permissions:
    • View Items
    • Open Items
    • View Versions
    • Create Alerts
    • Use Self-Service Site Creation
    • View Pages
  • Write – It enables apps to view, add, update, and delete items in existing lists and document libraries, it also includes all permissions from Read-Only level, plus these which follow:
    • Add Items
    • Edit Items
    • Delete Items
    • Delete Versions
    • Browse Directories
    • Edit Personal User Information
    • Manage Personal Views
    • Add/Remove Personal Web Parts
    • Update Personal Web Parts
  • Manage – It enables apps to view, add, update, delete, approve, and customize items or pages within a web site, it also includes all permissions from Write level, plus these which follow:
    • Manage Lists
    • Add and Customize Pages
    • Apply Themes and Borders
    • Apply Style Sheets
  • Full Control – It enables apps to have full control with in the specified scope, also includes all permission from all levels listed above.

There are important security implications when you assign a permission request level to a SharePoint app. That level must be adequate to allow the app to function correctly and complete every aspect of the task it is designed to perform. For example, the Read-Only app permission request level is adequate for reading information from SharePoint content, but for add a new one.

Finally I would like to advice you DO NOT use FULL CONTROL all the time! I know it’s a habit of us, developers, having the full permission to allow us to apply any action in SharePoint content, but consider it carefully. Please have a look at following picture:
p30

And now imagine your client with no knowledge, but with security awareness in mind, I am going to click on Cancel, because it makes me scared. Whole model makes perfectly sense to me, thus enjoy it!

Further reading:

App permissions in SharePoint 2013 – http://msdn.microsoft.com/en-us/library/fp142383.aspx

Plan app permissions management in SharePoint 2013 – http://technet.microsoft.com/en-us/library/jj219576.aspx

CRUD operations by REST services in SharePoint 2013

The Introduction

Client object model in SharePoint 2013 is going to be apart of our daily work, but most of us are a quite scare.Don’t worry, we are not going to do rocket science in this article, its purpose is describing opportunity and how to achieve the simplest way as possible. CRUD operations in the simplicity C – create, R- read, U – update, and D -delete, I’m sure all of you are aware of them, we are using them every day.

The Problem

Our problem is create the same experience as we used to have when working with lists. I mean ability to create item, edit item, delete item ,and display item. we will apply all CRUD operation. For this purpose we are going to use REST services, the whole overview you can find here.

The Solution

The solution itself is based on contact list which contains all necessary fields.  I create a simple object model based in one namespace which contains these objects:
  • Controller – object which covers linking between events and controls in your page
  • App – initialization of page
  • Operator – it contains operation communicate with SharePoint by REST services
  • FormFiller – functions work with our forms like clear, fill or lock.
  • TableRenderer – creates table for displaying our contacts
Outcome is not the main thing, but for completeness I have created 3 pages for actions and one default page where I’m displaying those contacts.
p20

There I have highlighted location when you can execute events, I hope it’s self-explanatory.

Accordingly I will show you’re my JavaScript object model, we start with Operator where I show just two functions read item and update item, rest of them will be omitted, but whole source code you can download from link at the end of this article.

readItem: function (id) { 
        $.ajax({ 
            //getting only fields which are needed 
            url: _spPageContextInfo.webServerRelativeUrl + 
                        "/_api/web/lists/getByTitle('Contacts')/getItemByStringId('" + 
                        id + "')/?$select=FirstName,Title,WorkPhone,Email", 
            type: "GET", 
            headers: { 
                "accept": "application/json;odata=verbose", 
            }, 
            success: function (data) { 
                //fill up your form  
                CRUDApp.FormFiller.fill(data.d.Title, data.d.FirstName, data.d.WorkPhone, data.d.Email); 
            }, 
            error: function (err) { 
                alert(JSON.stringify(err)); 
            } 
        }); 
    }, 

update: function (id, lname, fname, wphone, wemail) { 
        $.ajax({ 
            url: _spPageContextInfo.webServerRelativeUrl + 
                        "/_api/web/lists/getByTitle('Contacts')/getItemByStringId('" + 
                        id + "')", 
            type: "POST", 
            contentType: "application/json;odata=verbose", 
            //update only selected fields 
            data: JSON.stringify( 
            { 
                '__metadata': { 
                    'type': 'SP.Data.ContactsListItem' 
                }, 
                'Title': lname, 
                'FirstName': fname, 
                'WorkPhone': wphone, 
                'Email': wemail 
            }), 
            headers: { 
                "accept": "application/json;odata=verbose", 
                "X-RequestDigest": $("#__REQUESTDIGEST").val(), 
                "IF-MATCH": "*", 
                "X-Http-Method": "PATCH" 
            }, 
            success: function (data) { 
                SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.cancel, false); 
            }, 
            error: function (err) { 
                aler(JSON.stringify(err)); 
            } 
        }); 
    },

All the headers format is inspired from MSDN how to which you can find here. In the read item function, I have trimmed results just only for our fields and then in success branch fill form. At the second example of update item, I do create the JSON object with using helping method and put it in data branch. Next we have a look at Controller class which is responsible for consuming any events from our App.

//Namespace
window.CRUDApp = window.CRUDApp || {}

//Handle all user events
window.CRUDApp.Controller = {
    init: function () {
        //private literal properties
        var sNewContact = "#newContact", sNewButton = "#newButton",
            sSaveButton = "#saveButton", sCancelButton = "#cancelButton",
            sLastName = "#lastName", sFirstName = "#firstName",
            sWorkPhone = "#workPhone", sWorkEmail = "#workEmail"

        $(sNewContact).click(function () {
            SP.UI.ModalDialog.showModalDialog({
                url: "AddContact.aspx?IsDlg=1",
                title: "New Contact",
                allowMaximize: false,
                showClose: true,
                width: 400,
                height: 300,
                dialogReturnValueCallback: CRUDApp.Operator.readAll
            });
        });

        $(sNewButton).click(function () {
                CRUDApp.Operator.create($(sLastName).val(), $(sFirstName).val(),
                    $(sWorkPhone).val(), $(sWorkEmail).val());
        });

        $(sSaveButton).click(function () {
            var id = getQueryStringValue("Id");
            CRUDApp.Operator.update(id, $(sLastName).val(),
                $(sFirstName).val(), $(sWorkPhone).val(),
                $(sWorkEmail).val());
        });

        $(sCancelButton).click(function () {
            SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.cancel, false);
        });
    },

    editItem: function (id) {
        SP.UI.ModalDialog.showModalDialog({
            url: "EditContact.aspx?IsDlg=1&Id=" + id,
            title: "Edit Contact",
            allowMaximize: false,
            showClose: true,
            width: 400,
            height: 300,
            dialogReturnValueCallback: CRUDApp.Operator.readAll
        });
    },

    readItem: function (id) {
        SP.UI.ModalDialog.showModalDialog({
            url: "DisplayContact.aspx?IsDlg=1&Lock=1&Id=" + id,
            title: "Display Contact",
            allowMaximize: false,
            showClose: true,
            width: 400,
            height: 300,
            dialogReturnValueCallback: null
        });
    },

    deleteItem: function (id) {
        CRUDApp.Operator.remove(id);
    }
}

In the initialization function we registered events by JQuery on our button with particular functionality, you can see most of them reference functionality from Operator class which covers communication. We are using SharePoint UI Modal dialogs for wrapping our pages. As a last piece of code I show you how we build our table based on template.

//Namespace
window.CRUDApp = window.CRUDApp || {}

//Render results in a table
window.CRUDApp.TableRenderer = function () {
    //private members
    var element, data, header, rowTempale, displayDiv = 'undefined'
    var sRowTemplate = "rowTemplate"

    init = function () {
        //header template
        header = "<thead><th>&nbsp;</th><th>Last Name</th><th>First Name</th>" +
            "<th>Work Phone</th><th>Work Email</th><th>&nbsp;</th><th>&nbsp;</th></thead>";
        //template for each row
        rowTemplate = "<tr><td><a href=\"javascript:CRUDApp.Controller.readItem('{{=Id}}');\">" +
            "<img src='/_layouts/15/images/icgen.gif' border='0'/></a></td>" +
            "<td>{{=Title}}</td><td>{{=FirstName}}</td><td>{{=WorkPhone}}</td><td>{{=Email}}</td>" +
            "<td><a href=\"javascript:CRUDApp.Controller.editItem('{{=Id}}');\">" +
            "<img src='/_layouts/15/images/edit.gif' border='0'/></a></td>" +
            "<td><a href=\"javascript:CRUDApp.Controller.deleteItem('{{=Id}}');\">" +
            "<img src='/_layouts/15/images/delete.gif' border='0'/></a></td></tr>";
        //find our table
        element = $("<table>", { id: "contactsTable" });
        //apply template
        $.template(sRowTemplate, rowTemplate);
    },

    set_data = function (v) { data = v; },
    set_displayDiv = function (v) { displayDiv = v; },

    render = function () {
        element.empty();
        element.append($(header));
        element.append($.render(data, sRowTemplate));
        displayDiv.append(element);
    }

    //public interface
    return {
        init: init,
        set_data: set_data,
        set_displayDiv: set_displayDiv,
        render: render
    };
}();

The main attention is required to our template there are located JavaScript calls from where we call function in our Controller class. The whole source code is located on my Skydrive here.

The Conclusion

In this particular project I have attempted to show you, how potentially we can design solution and also discover SharePoint REST services. I hope you understand all well. Big thanks for inspiration to Scot Hillier’s codeplex project. The purpose of this article was not stole source code, but describe it and explore it.

JavaScript View Model in SharePoint 2013/Office 365

The Introduction

In this article I will introduce you my discovering new approach how to represent object model in JavaScript, I have been inspired with project which was built by Scot Hillier and located on codeplex here. My aim here is describe my way how to understand this example, and what we can gain from it.

The Problem

As long as you are aware we cannot use C# and behind code in SharePoint-hosted apps in SharePoint 2013. And here is problem how to build our business model, or logic in JavaScript. I know some developer will deal with this challenge originally, and create crazy long script full of function cover all possible issues and storing information in property bag, sessions and calling SharePoint web services every time if client change something on the client page.

I have chosen my own way, I have found (or be inspired) with view model design pattern which is described in more detail on Knockout web site. The best advantage is binding based on our object model.

The Solution

I have developed new app for SharePoint 2013 for displaying user properties of current user. This project has included one web part element with custom page and two custom JavaScript files.
Firstly I will show you outcome, please don’t laugh on me, I’m not good at HTML/CSS I’m still learning :)
p19

As you can see there are a few information gathered from user profile. My object model is store in one JavaScript file with following content:

window.ViewModel = window.ViewModel || {}

ViewModel.UserDetailViewModel = function () {
    //Define private variables
    var displayName,
        pictureUrl,
        location,
        workEmail,
        cellPhone,
        fax,
        homePhone,
    //Define public functions
    get_displayName = function () { return displayName; },
    get_workEmail = function () { return workEmail; },
    get_cellPhone = function () { return cellPhone; },
    get_fax = function () { return fax; },
    get_homePhone = function () { return homePhone; },
    get_pictureUrl = function () { return pictureUrl; },
    get_location = function () { return location; },
    //initiation
    init = function () {
        $.ajax(
            {
                url: decodeURIComponent(getQueryStringParameter("SPAppWebUrl")) +
                        "/_api/SP.UserProfiles.PeopleManager/GetMyProperties",
                method: "GET",
                headers: {
                    "accept": "application/json;odata=verbose",
                },
                success: function (data) {
                    try {
                        //Get properties from user profile Json response
                        displayName = data.d.DisplayName;
                        pictureUrl = data.d.PictureUrl;
                        var properties = data.d.UserProfileProperties.results;
                        for (var i = 0; i < properties.length; i++) {
                            var property = properties[i];
                            if (property.Key == "SPS-Location") {
                                location = property.Value;
                            }
                            if (property.Key == "WorkEmail") {
                                workEmail = property.Value;
                            }
                            if (property.Key == "CellPhone") {
                                cellPhone = property.Value;
                            }
                            if (property.Key == "Fax") {
                                fax = property.Value;
                            }
                            if (property.Key == "HomePhone") {
                                homePhone = property.Value;
                            }
                        }
                    } catch (err2) {
                        alert(JSON.stringify(err2));
                    }

                    //Bind to view model
                    ko.applyBindings(ViewModel.UserDetailViewModel);
                },
                error: function (err) {
                    alert(JSON.stringify(err));
                }
            }
            );
    },
    getQueryStringParameter = function (p) {
        var params = document.URL.split("?")[1].split("&");
        var strParams = "";
        for (var i = 0; i < params.length; i = i + 1) {
            var singleParam = params[i].split("=");
            if (singleParam[0] == p)
                return singleParam[1];
        }
    };
    return {
        init: init,
        get_displayName: get_displayName,
        get_pictureUrl: get_pictureUrl,
        get_location: get_location,
        get_workEmail: get_workEmail,
        get_cellPhone: get_cellPhone,
        get_fax: get_fax,
        get_homePhone: get_homePhone
    }
}();
As you can see that structure of file is similar as in object-oriented languages, but I warn you be careful with typos, JavaScript doesn’t care about wrong name of properties. Next you will see my page which using in client web part:
<%@ Omitted page registration %>

<html lang="en">
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE9">
    <title>User Details</title>
    <link rel="Stylesheet" href="../Content/App.css" />
    <WebPartPages:AllowFraming runat="server" ID="AllowFraming1" />
    <script type="text/javascript" src="../Scripts/jquery-1.6.2.min.js"></script>
    <script type="text/javascript" src="../Scripts/knockout-2.2.1.js"></script>
    <script type="text/javascript" src="../Scripts/UserDetailViewModel.js"></script>
    <script type="text/javascript" src="../Scripts/App.js"></script>
</head>
<body>
    <div>
        <article>
            <div id="portrait" style="text-align: left;">
                <figure>
                    <img src="#" data-bind="attr: { src: get_pictureUrl() }" alt="photo" />
                </figure>
            </div>
            <div style="text-align: left;">
                <figcaption>Hi <span data-bind="text: get_displayName()"></span>!
                </figcaption>
            </div>
            <br />
            <table>
                <tr>
                    <td>Work Email </td>
                    <td><b><span data-bind="text: get_workEmail()"></span></b></td>
                </tr>
                <tr>
                    <td>Cell Phone </td>
                    <td><b><span data-bind="text: get_cellPhone()"></span></b></td>
                </tr>
                <tr>
                    <td>Fax </td>
                    <td><b><span data-bind="text: get_fax()"></span></b></td>
                </tr>
                <tr>
                    <td>Home Phone </td>
                    <td><b><span data-bind="text: get_homePhone()"></span></b></td>
                </tr>
                <tr>
                    <td>Location </td>
                    <td>
                        <b><span data-bind="text: get_location()"></span></b>
                    </td>
                </tr>
            </table>
        </article>
    </div>
</body>
</html>

I hope your attention is focus on “data-bind” attributes which are used by Knockout project to data binding, more information here. And finally I show you custom client web part properties in web part element which impressed myself:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <ClientWebPart Name="UserDetailWebPart" Title="UserDetailWebPart Experience" 
                 Description="UserDetailWebPart by Martin Bodocky"
                 DefaultWidth="400" DefaultHeight="400">
    <Content Type="html" Src="~appWebUrl/Pages/UserDetailWebPart.aspx?{StandardTokens}&amp;ShowImage=_ShowImage_" />
    <Properties>
      <Property WebDescription="Toggle on or off displaying user image."
                Name="ShowImage" Type="boolean" WebBrowsable="true" WebDisplayName="Show Image" 
                WebCategory="Configuration" DefaultValue="true" RequiresDesignerPermission="true" 
                PersonalizableIsSensitive="false" PersonalizationScope="shared"/>
    </Properties>
  </ClientWebPart>
</Elements>
As you can see we can defined custom properties in element file and use them in url, please read more here. And usage is also straightforward, look at my App.js to show my picture:
window.ViewModel = window.ViewModel || {}

$(document).ready(function () {
    ViewModel.UserDetailViewModel.init();

    var showImage = getQueryStringValue("ShowImage");
    if (showImage == "true")
        $("#portrait").show();
    else
        $("#portrait").hide();
});

function getQueryStringValue(paramName) {
    try{
        var params = document.URLUnencoded.split("?")[1].split("&");
        var strParams = "";
        for (var i = 0; i < params.length; i = i + 1) {
            var singleParam = params[i].split("=");
            if (singleParam[0] == paramName)
                return decodeURIComponent(singleParam[1]);
        }
    }
    catch (err) {
        return null;
    }
}

My source you can find on my SkyDrive here.

The Conclusion

Probably you have seen my worries from my last post which I published yesterday. I am partly right JavaScript is everywhere, but on the other hand we have a few nice solution how to deal with challenging behavior like JQuery and Knockout in particular in creating our business model. I hope this article show you new approach how to develop apps for client side for SharePoint 2013/Office 365.

Kick off new way of programming for SharePoint 2013

Like anyone involved in SharePoint world, you know that Microsoft developed new way and new recommendation, how to deliver application to SharePoint 2013. In this article I would like to express my first experience with using, and creating SharePoint App, mainly my concerns and impressions.

My concerns:

  • Get rid of C#, essentially every .Net code what means for us huge limitation and a little without control. I still cannot imagine create object model based on Javascript or JQuery.
  • Structure of App solution in Visual Studio looks ugly with all generated files and scripts, for experienced SharePoint developer is piece of cake, but for beginners quite headache.

Look on following picture:

 p17
  • On the Office 365, respectively on SharePoint 2013(Online) doesn’t exist way to read information about Correlation ID, which is quite sad, if you are not HTML/CSS guru you will find hard a way to log exception in your code as myself.
  • If you don’t have great internet connection, you must avoid to press F5, better check you code in the first place. For my attempting it takes 6 minutes to deploy with debugging.

My impressions:

  • The smooth development process and debugging ability – I was quite surprised how easy it was deploy my first app.
  • Intellisense if you are writing JQuery code, because this was challenging with SharePoint 2010.

Early conclusion

I have been SharePoint developer for 4 years now, I became that from C# background. My specialization is more logic side than frontend, which means developing workflows, web parts, timer jobs and so on. It is understandable that I’m not quite happy about it. Anyway it’s opennng for me opportunity broaden my experience and learn new piece of technology.

Finally, I can say that environment was impress me with clear shapes and integration in one package!

p18

Happy SharePointing 2013!

Follow

Get every new post delivered to your Inbox.