Saturday, February 07, 2015

Right way to add CSS and JavaScript to SharePoint App Pages and Master-Pages

In SharePoint-Hosted App, there is a special way to embed your JavaScript and CSS.

Adding JavaScript:
To add JavaScript that resides in the "layouts\15" folder, just specify the file name:
<SharePoint:ScriptLink name="sp.core.js" runat="server" LoadAfterUI="true" Localizable="false" />

To Add JavaScript that resides in your app, for example in "Scripts" folder of your SharePoint-Hosted App:
<SharePoint:ScriptLink name="~site/Scripts/App.js" runat="server" OnDemand="false" LoadAfterUI="true" Localizable="false"></SharePoint:ScriptLink>

Adding CSS:
To add CSS to a SharePoint-Hosted App, you need to know how SharePoint works, its a bit different form that way JavaScript is embedded in the app. Initially I thought, I could use "<SharePoint:CssLink" just the way I used "<SharePoint:ScriptLink", but it wasn't true.

SharePoint uses "SharePoint:CssRegistration" and "SharePoint:CssLink" together to prevent duplication of CSS on the page. All you have to do is to register your CSS using the "SharePoint:CssRegistration" tag. Once registered, there already is a "SharePoint:CssLink" present in the master-page that collects all the registered CSS links and renders them on the page. In case you make a tiniest mistake while registering your CSS, it won't appear on the page. Here is how you can register for the SharePoint-Hosted apps:

<SharePoint:CssRegistration runat="server" Name="<% $SPUrl:~site/Content/App.css%>" After="corev15.css" />

Note that SharePoint adds all the CSS in an alphabetical order based on their file names. To control their order, you have to mention the CSS file "after" which your CSS file should be added. In above example, your CSS file will be rendered after "corev15.css" file. If you don't mention the "After" attribute, your CSS will be added before "corev15.css" since its named "App.css". If you have more than one CSS files you must mention full paths in the "After" attribute such as:

<SharePoint:CssRegistration runat="server" Name="<% $SPUrl:~site/Content/App2.css%>After="<% $SPUrl:~site/Content/App1.css%>" />

Remember, as mentioned before, "SharePoint:CssLink" is added only once and normally on the master-page. It collects all the registered CSS and adds their links. If your link doesn't appear despite the registration, make sure the "Name" is pointing to an absolute path.

Friday, January 02, 2015

Knockout binding in SharePoint 2013 SharePoint-Hosted App

Today I was trying to make Knockoutjs work with SharePoint Hosted Apps in a way that is manageable and extensible. I assume you already know Knockout JS and know how to create a basic SharePoint-Hosted App.

There can be many ways using which KO can be plugged into an application but here here is what I think would work well for SharePoint-Hosted Apps considering async JSOM calls:

Step1: Add Knockout JS
Just download the js file and paste inside the Scripts folder. Refer it in your Default.aspx page.

Step2: Add html binding
In the Default.aspx page of SharePoint 2013 Hosted put the following code in the "<p id="message">" tag:
Welcome <span data-bind="text: username"></span>
Step3: Apply KO Bindings
At the bottom of the Default.aspx page put the following code:
    <script >
        var viewModel = new window.MyApp.ViewModel();
        viewModel.load();
        ko.applyBindings(viewModel);
    </script>
Step4: Your App Module
In the App.js file (under Scripts) folder place the following script:
'use strict';
(function () {
    //create new if its not alredy initialized.
    window.MyApp = window.MyApp || {};
    window.MyApp.ViewModel = function () {
        //assign this to me so that it could be accessed with the functions/event handlers
        var me = this;
        this.context = SP.ClientContext.get_current();
        this.spUser = ko.observable();
        this.username = ko.computed(function () {
            //as soon as spUser is populated, username also gets loaded
            if (me.spUser()) {
                return me.spUser().get_title();
            }
            return '';
        });
        this.load = function () {
            //loading the user will load all its dependent bindings
            var user = me.context.get_web().get_currentUser();
            me.context.load(user);
            me.context.executeQueryAsync(function () {
                me.spUser(user);
            });
        }
    };
})();
Explanation:
Note that "spUser" as observable and "username" is a computed property that is based on spUser. As soon as spUser is loaded, username also loads itself.

Above mentioned point is the key to the above implementation. It utilizes the "Dependency Tracking". This way all the dependencies on SharePoint can be resolved asynchronously.

Wednesday, October 29, 2014

SharePoint 2013 Online and ASP.NET Web API using JSONP

Consider a scenario where you have to display data or make decisions on a SharePoint 2013 page based on the data that exists in a database. Here is what you can do:

Abstract:
1. Create an Empty ASP.NET Web API project.
2. Enable the project for JSONP format
3. Add the Controller, Model, the business and data access logic to the service
4. Deploy the Service
5. Add script to SharePoint 2013 page

Details:
1. Create an Empty ASP.NET Web API project.
This is fairly simple step, all you need is MVC4 or above and .NET Framework 4.5. Using Visual Studio 2012/2013, Add new project, select an empty project and check the Web API box and click OK.

2. Enable the project for JSONP format:
- Open package manager in visual studio (Tools&gt;NuGet Package Manager &gt; Package Manager Console and run the following command, it will add the required dlls to your project:

Install-Package WebApiContrib.Formatting.Jsonp

- In App_Start folder of the project, create a new class:

    public class FormatterConfig
    {
public static void RegisterFormatters(MediaTypeFormatterCollection formatters)
        {
            var jsonFormatter = formatters.JsonFormatter;
            jsonFormatter.SerializerSettings = new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            };

            // Insert the JSONP formatter in front of the standard JSON formatter.

            var jsonpFormatter = new JsonpMediaTypeFormatter(formatters.JsonFormatter);
            formatters.Insert(0, jsonpFormatter);
        }

    }


The Application_Start method in your Global.asax.cs should look like this:

        protected void Application_Start()
        {
            FormatterConfig.RegisterFormatters(GlobalConfiguration.Configuration.Formatters);
            GlobalConfiguration.Configure(WebApiConfig.Register);
        }

3. Add the Controller, Model, the business and data access logic to the service
I added the "Web API Controller Class (v2)" in the project.

4. Deploy the Service
- Create a new site in IIS, create bindings with a host-name and SSL.
NOTE: If you won't use SSL, you'll see the mixed content warnings or "security risk" warnings from browsers when you'll call the service from JavaScript. 
- Publish the service from visual studio and copy the published files to the site directory.

4. Test:
Create an HTML page and paste the following code in it. This code should work. (if it doesn't, open developer toolbar of the browser to make sure there are no errors).

<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
<button id="getJsonp">Get JSONP</button>
<script type="text/javascript">
$("#getJsonp").click(function () {
$.ajax({
        type: 'GET',
              url: "http://localhost/api/values/1",
              callback: callbackFunc,
              contentType: "application/json; charset=utf-8",
              dataType: 'jsonp'
              }).done(function(data){
alert(data);
});
});

function callbackFunc(resultData) {
}
</script>
</body>
</html>

5. Add script to SharePoint 2013 page
If it passes the above test, the highlighted (in blue) jQuery script can be added to the SharePoint page. Make sure you replace the localhost with an actual host-name accessible to all users, of course :)

Thursday, January 12, 2012

Future of Hard-Disk Drives?

All tape drives of the past and most recent high capacity drives used today after all are magnetic drives (which use "ferromagnets" to store bits).

Then Solid State Drives (SSDs) gave a new direction of fastest drives. I think that's the future of hard-drives for another 5 years.

However, what if we had a mixture of two? The real future of storage I think will be storage using atomic structures with an addressing scheme and algorithm of an SSD and a four-atom-wide wires. Instead of flip-flops, "antiferromagnets" will be used and result will be lightening fast drives with thousands of TB of storage... ?

Read about flip-flop replacement:
Tiny hard drive stores one byte of data with just 12 atoms
About connecting-wire replacement:
Four-atom-wide wire may herald tiny computers

I am ready to buy that drive as soon as it becomes available ;)

Saturday, January 07, 2012

Microsoft Visual Studio Useful Shortcuts

Here is a link where Visual Studio shortcuts are available which can make you efficient developer if you make good use of them…

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