Wednesday, May 25, 2016

Installing SharePoint 2013: Fails in step 4 while creating content database.

In recent project I was installing SharePoint 2013 on one of my machines. Every time I run the SharePoint products configuration wizard it would fail with error on step 4.


I was facing the issue because my service account that was running the wizard was not part of "Manage audit log and security policies" on the windows server.

Solution: Using windows prompt type gpedit.msc that should take you to Local Group Policy Editor. Then navigate to Computer Configuration > Windows Settings > Security Settings > Local Policies > User Rights Assignment. Here you should look for "Manage audit log and security policies" and add your account here.


In my case windows administrator has disabled the add button. I had to approach them and they added me.


SharePoint Timer Job: Sending notifications with dynamic email templates stored in SharePoint list

I was recently working on a project requirement that involved setting up the alert system on a SharePoint list and system had to send notifications based on the due date. The email content is dynamic in nature and it is based on due date of the item. For instance  we need to send an particular kind of notification if the filing is due in 7 days and other set of notification if the filing is due in 15 days.

My intention was to create self service email template that would reside in SharePoint list as shown below such that user can change the wording if needed without developer intervention or deployment of code.

The fields with in the square brackets are read by SharePoint custom code and it will be auto populated by system based on list item when the timer job runs.




I had created hash table with all the required fields and will parsing the above template.
[code]String emailBody = string.Empty;
String emailsubject = string.Empty;
SPList spList = web.Lists.TryGetList("MessageTemplates");
SPQuery messageTemplateQuery = new SPQuery();
messageTemplateQuery.Query = "<Where><Eq><FieldRef Name='Title' /><Value Type='Text'>StandardRemainder</Value></Eq></Where>";
messageTemplateQuery.RowLimit = 1;
messageTemplateQuery.ViewFields = "";
SPListItemCollection listitem = spList.GetItems(messageTemplateQuery);
SPListItem item0 = listitem[0];
emailBody = item0["BodyHTML"].ToString();
emailsubject = item0["Subject"].ToString();
Hashtable hashTableForMessageBody = null;
hashTableForMessageBody = CreateHashTableForMessageBody(title, description, regulatoryFilingEntity, regulatoryFiling, FilingDueDate, Duein);
emailBody = GetEmailBody(web, hashTableForMessageBody, emailBody);
[/code]
When the above "CreateHashTableForMessageBody" is called following method will be executed. It basically stores all the information in hashtable.

[code]private Hashtable CreateHashTableForMessageBody(string title, string description, string regulatoryFilingEntity, string regulatoryFiling, DateTime FilingDueDate, int Duein)
        {
            Hashtable hashTableForMessageBody = new Hashtable();
            try
            {
                hashTableForMessageBody.Add("Title", title);
                hashTableForMessageBody.Add("Description", description);
                hashTableForMessageBody.Add("Regulatory Entity", regulatoryFilingEntity);
                hashTableForMessageBody.Add("Regulatory Filing", regulatoryFiling);
                hashTableForMessageBody.Add("Filing Due Date", FilingDueDate);
                hashTableForMessageBody.Add("Due In", Duein);              
            }

            catch (Exception ex)
            {
                EventLog.WriteEntry("Regulatory Calendar Error", "CreateHashTableForMessageBody\r\n" + ex.Message, EventLogEntryType.Error);
            }
            return hashTableForMessageBody;
        }


        //Parses the message template from list and sets the relevant subject
        private string GetEmailBody(SPWeb web, Hashtable hashTableForMessageBody, string body)
        {
            try
            {
                foreach (object obj in hashTableForMessageBody.Keys)
                {
                    body = body.Replace("[" + obj.ToString() + "]", hashTableForMessageBody[obj].ToString());
                }
            }

            catch (Exception ex)
            {
                EventLog.WriteEntry("Regulatory Calendar Error", "GetEmailBody\r\n" + ex.Message, EventLogEntryType.Error);
            }
            return body;
        }
[/code]

Reverting SharePoint 2010 UI to MOSS 2007 UI

There might be occasions we as developer or admin migrated SharePoint 2007 site collection to SharePoint 2010 and we leverage SharePoint visual upgrade feature to update the UI to 2010. There are two options,  We have preview mode to update and other one regular update. The later one update the UI permanently and you cant revert it back when your users doesn't like the new 2010 UI.

Solution: Fortunately there is power shell script that would let you to revert you to previous UI.

For site collection use the below PS

[code]$site = Get-SPSite("http://mysite/sites/siteCollName")
$web = $site.OpenWeb()
$web.Update()
$web.Dispose()[/code]

For sub site use the below PS
[code]$web = Get-SPWeb("http://mysite/sites/siteCollName/Subsite")
$web = $web.OpenWeb();
$web.Update()
$web.Dispose()[/code]

Saturday, May 21, 2016

SharePoint 2013 REST API CRUD Operations

SharePoint 2013 new OData Rest web service API  that would let us to communicate with SharePoint list items. In the below code, I had written REST web api that would perform CRUD operations on list items. The example uses JavaScript on button click action.


[code]<%@ Page Inherits="System.Web.UI.Page" MasterPageFile="~masterurl/default.master" Title="REST Demo" meta:progid="SharePoint.WebPartPage.Document" %>
<asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server">
 <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
    <script type='text/javascript'>
  //Retrieve list items 
$(document).ready(function () {
     $("#getItem").click(function (event) { 
     retrieve();
     });  

     //Insert new item
     $("#addNewItem").click(function (event) {
     var name = document.getElementById('txtItem').value;
     var addNewItemUrl = "/_api/Web/Lists/GetByTitle('Northwind')/Items";
     var data = {__metadata: { 'type': 'SP.Data.NorthwindListItem' }, Title: name};
     addNewItem(addNewItemUrl,data);        
     });        

 

     //Update new item
     $("#updateItem").click(function(event){  
     var updateItemUrl = "/_api/Web/Lists/getbytitle('Northwind')/getItemById(4)";
     var data = {__metadata: { 'type': 'SP.Data.NorthwindListItem' }, Title: 'Joe'}; 
     updateNewItem(updateItemUrl,data)
     });  

     //Delete item
     $("#deleteItem").click(function(event){  
     var url = "/_api/Web/Lists/getbytitle('Northwind')/getItemById(4)";
     deleteitem(url);
     });
});

function retrieve() {
 $.ajax({
            url: "http://sharepoint2013.gcm.com/sites/RBSSharePoint/_api/Web/Lists/GetByTitle('Northwind')/Items",
            type: "GET",
            headers: {
                "accept": "application/json;odata=verbose",
                "content-type": "application/json;odata=verbose",
                "X-RequestDigest": $("#__REQUESTDIGEST").val()
            },

            success: function (data) {      
            var results = data.d.results;
             for (i = 0; i < data.d.results.length; i++) {
             var item = data.d.results[i];
             $("#ResultDiv").append(item.Title + "\t" + item.Continent+"<br>" );
             }
            },

            error: function (error) {
                       $("#ResultDiv").append(JSON.stringify(error));
            }
            });
}

function addNewItem(url,data) {
$.ajax({
        url: _spPageContextInfo.webAbsoluteUrl + url,
        type: "POST",
        headers: {
            "accept": "application/json;odata=verbose",
            "X-RequestDigest": $("#__REQUESTDIGEST").val(),
            "content-Type": "application/json;odata=verbose"
        },

        data: JSON.stringify(data),
        success: function (data) {
            console.log(data);
        },

        error: function (error) {
            alert(JSON.stringify(error));
        }
    });
}

function deleteitem(url) {
    $.ajax({
        url: _spPageContextInfo.webAbsoluteUrl + url,
        type: "DELETE",
        headers: {
            "accept": "application/json;odata=verbose",
            "X-RequestDigest": $("#__REQUESTDIGEST").val(),
            "content-Type": "application/json;odata=verbose",
            "IF-MATCH": "*"
        },

        sucess: onSucess,
        error: onError
    });
}

function updateNewItem(updateItemUrl,payload) {
$.ajax({
   url: _spPageContextInfo.webAbsoluteUrl + updateItemUrl,
   type: "POST",
   headers: { "Accept": "application/json;odata=verbose",
      "X-RequestDigest" : $("#__REQUESTDIGEST").val(),
      "X-HTTP-Method": "MERGE",
      "If-Match": "*"},
   data: JSON.stringify(payload),
   contentType: "application/json;odata=verbose",
   success: function (data) {
  console.log(data);
},

error: function (error) {
alert(JSON.stringify(error));
}
});
}

function onSucess(data) {
    alert(data + 'Item Deleted');
}

function onError(error) {
    alert(JSON.stringify(error));
}

 

</script>
    <div id="MainContent">
    <P>
      <button id="createList">Create list</button>
      <button id="addNewItem">Insert Item</button>
     </p>
     <p>

   <button id="updateItem">Update Item</button>
   <button id="deleteItem">Delete Item</button>
   <button id="getItem" type="button">Retrieve Item</button>
     </p> 
     <p style="text-align:justify"> 
      <input type="text" id="txtItem"/>
     </p>
     <p>
     <div id="ResultDiv">
     </div>
     </p></div>
</asp:Content>[/code]