Register CSS file from JavaScript in SharePoint Online

There is a way to register a CSS file in SharePoint Online without any help from server side code. Seems Microsoft created a method called “registerCssLink” and attached it directly to window object (no namespace for this).

registerCssLink('/sites/mysite/SitePages/style.css', function (htmlLink) {
    // Do something here with htmlLink object representing link to CSS file
});

It might work on SharePoint 2013 and 2010 as well, but I did not tested it yet. I will post the results of the tests once will be completed.

Advertisements

Sys.UI.DataView to show records from SharePoint lists via listdata.svc

There are hundreds of articles probably about this, but some of them did not work for me. Just simply Sys.UI.DataView client control did not bind to listdata.svc. So I used my own way to get and display the data using client side template. I know that probably most of the developers do not use anymore Microsoft Ajax library and consider it obsolete, but it my eyes is still reliable to be used in SharePoint environment, in combination with JQuery.

What will follow is a simple example of how to get the data from a custom list called “Ajax”, which contains a single column called “Title”. I used the simplest example I had in my mind for a practical demonstration.

1. Prepare Sys.UI.DataView control for undefined object properties inside data source

Sys.UI.DataView is throwing an error if in the one the properties you want to display is referencing to undefined object properties in the data source. As I am not always sure what is coming from the web service, I modified “set_data” method to replace these with an empty string. So HTML code below for a template where actually “CustomTitle” properties doesn’t exist in the data source will not fail.

  <asp:ScriptManager id="ScriptManager" runat="server" EnablePageMethods="true" EnablePartialRendering="true" EnableScriptGlobalization="false"   EnableScriptLocalization="true" LoadScriptsBeforeUI="false">
    <Scripts>
            <asp:ScriptReference Name="MicrosoftAjax.js" Path="/_layouts/PeppermintFeature/MSAjax/MicrosoftAjax.js" />
            <asp:ScriptReference Name="MicrosoftAjaxWebForms.js" Path="/_layouts/PeppermintFeature/MSAjax/MicrosoftAjaxWebForms.js" />
            <asp:ScriptReference Path="/_layouts/PeppermintFeature/MSAjax/MicrosoftAjaxDataContext.js" />
            <asp:ScriptReference Path="/_layouts/PeppermintFeature/MSAjax/MicrosoftAjaxOpenData.js" />
            <asp:ScriptReference Path="/_layouts/PeppermintFeature/MSAjax/MicrosoftAjaxCore.js" />
            <asp:ScriptReference Path="/_layouts/PeppermintFeature/MSAjax/MicrosoftAjaxComponentModel.js" />
            <asp:ScriptReference Path="/_layouts/PeppermintFeature/MSAjax/MicrosoftAjaxSerialization.js" />
            <asp:ScriptReference Path="/_layouts/PeppermintFeature/MSAjax/MicrosoftAjaxTemplates.debug.js" />
            <asp:ScriptReference Path="Ajax.js" />
      </Scripts>
  </asp:ScriptManager>
   
<ul id="MyDataView" class="sys-template">
<li>{{ Title }} {{ CustomTitle }}</li>
</ul> 

Please note the files required for this operation being loaded with asp:ScriptManager. If you prefer, you can load them on demand using start.js

2. Get the data from listdata.svc and display it on the page

For this, I used two powerful objects contained by Microsoft Ajax framework: Sys.Data.OpenDataServiceProxy, used for communication with the web service, and Sys.Serialization.JavaScriptSerializer, for converting XML response into an array of objects to server as a datasource. With these object code become very simple.

   		 var dataContext = new Sys.Data.OpenDataServiceProxy("http://servername/sites/mysite/_vti_bin/listdata.svc");
   		 dataContext.query("Ajax", function(response, context, operation, userContext) { 
   		 	 var responseAsJsonString = Sys.Serialization.JavaScriptSerializer.serialize(response);
   		 	 var dw = new Sys.UI.DataView($get('MyDataView'));
   		 	 dw.set_data(Sys.Serialization.JavaScriptSerializer.deserialize(responseAsJsonString ),['Title','CustomTitle']);
   		 	 dw.refresh();
   		 }, 
   		 function(err) {
  
   		 		alert("Error contacting service. Status code: " + err.get_statusCode() +'. Message: ' + err.get_message());
   		 
   		 });

Code was working for me in IE7, IE8, IE 9 (did not have the test to chance it IE10 and IE11) and Chrome. So it did the job, no matter if some developers consider it obsolete. For me looks simple and easy to use, but probably used JavaScript framework is in 99% of the cases a matter of personal option.

Create WCF service to get data from database table

My scope was to create a WCF service to get data from any database table, table name being pass as parameter. So, first think I did is to create a table called “TEST” with the following structure:

[First Name] nvarchar(50)
[Last Name]  nvarchar(50)
[ID Number]  numeric(18, 0)

The expected XML response was supposed to look like this (of course will look different if I choose another table with another structure, but you get the idea).

<?xml version="1.0"?>
<GetTables.TableRows xmlns="http://schemas.datacontract.org/2004/07/MVC.DataServices" xmlns:i="http://www.w3.org/2001/XMLSchemainstance">
<GetTables.TableRow>
<TableField>
<FieldName>First Name</FieldName>
<FieldType>String</FieldType>
<FieldValue>test</FieldValue>
</TableField>
<TableField>
<FieldName>Last Name]</FieldName>
<FieldType>String</FieldType>
<FieldValue>test</FieldValue>
</TableField>
<TableField>
<FieldName>ID Number</FieldName>
<FieldType>Decimal</FieldType>
<FieldValue/>
</TableField>
</GetTables.TableRow>
<GetTables.TableRow>
<TableField>
<FieldName>First Name</FieldName>
<FieldType>String</FieldType>
<FieldValue>test 1</FieldValue>
</TableField>
<TableField>
<FieldName>Last Name]</FieldName>
<FieldType>String</FieldType>
<FieldValue>test 1</FieldValue>
</TableField>
<TableField>
<FieldName>ID Number</FieldName>
<FieldType>Decimal</FieldType>
<FieldValue/>
</TableField>
</GetTables.TableRow>
<GetTables.TableRow>
<TableField>
<FieldName>First Name</FieldName>
<FieldType>String</FieldType>
<FieldValue>test 2</FieldValue>
</TableField>
<TableField>
<FieldName>Last Name]</FieldName>
<FieldType>String</FieldType>
<FieldValue>test 2</FieldValue>
</TableField>
<TableField>
<FieldName>ID Number</FieldName>
<FieldType>Decimal</FieldType>
<FieldValue/>
</TableField>
</GetTables.TableRow>
</GetTables.TableRows>

Below is the code, which did this for me:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;

using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;


namespace MVC.DataServices
{
    [ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class GetTables
    {
    
        /// <summary>
        /// Get data from database table
        [OperationContract]
        [WebGet(ResponseFormat = WebMessageFormat.Xml)]
        public TableRows GetTableData(string tableName)
        {
            TableRows results = new TableRows();
            WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
            using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
            {
                connection.Open();
                SqlCommand command = new SqlCommand("SELECT * FROM " + tableName,connection);
                SqlDataReader reader = command.ExecuteReader();
                while(reader.Read() == true)
                {
                    TableRow row = new TableRow();
                    for(int  i = 0; i < reader.FieldCount; i++)
                    {
                        TableField field = new TableField();
                        field.FieldName = Convert.ToString(reader.GetName(i));
                        field.FieldType = Convert.ToString(reader.GetFieldType(i).Name);
                        field.FieldValue = Convert.ToString(reader.GetValue(i));
                        row.Add(field);
                    }
                    results.Add(row);
                }
             }

            return results;
        }

        [DataContract(Name="TableField")]
        public class TableField
        {
            [DataMember]
            public string FieldName { get; set; }
            [DataMember]
            public string FieldType { get; set; }
            [DataMember]
            public string FieldValue { get; set; }
        }


        [CollectionDataContract]
        public class TableRow : List<TableField>
        {
            public TableRow()
            {
            }
        }

        [CollectionDataContract]
        public class TableRows : List<TableRow>
        {
            public TableRows()
            {

            }
        }
        
    }
}

I just needed to pass TableName parameter (http://localhost/DataServices/GetTables.svc/GetTableData?TableName=TEST) to the web service and it gets all the data from the specified table and display it into an XML format.