Microsoft SharePoint and .NET Technology Insight

SharePoint, .NET, Office365, Windows Azure, TFS, Project Server and SQL Server Technology Insights


Leave a comment

SharePoint 2010 and Host Named Site Collections

A host header is a third piece of information that you can use in addition to the IP address and port number to uniquely identify a Web domain or, as Microsoft calls it, an application server. In SharePoint 2010, host headers can be applied at two different levels :

The Web application (IIS Web site) level
The site collection level

A host-named site collection allows you to address a site collection with a unique DNS name. A SharePoint Web Application when created contains many path-based site collections that share the same host name (DNS name). For example, Team A has a site collection at http://abc.com/sites/teamA, and Team B has a site collection at http://abc.com/sites/teamB. These are referred to as path-based site collections, and is the recommendation for most corporate scenarios. Host named site collections enable you to assign a unique DNS name to site collections. For example, you can address them as http://TeamA.abc.com and http://TeamB.abc.com allowing for scalability. This is a feature of SharePoint that allows individual site collections to have their own top-level URL.

The following code snippet programmatically creates the host-named site collection with the URL https://sharepointzen.wordpress.com in the SharePoint Server 2010 Web application with the URL https://sharepoint

SPWebApplication webApp = SPWebApplication.Lookup(new Uri("http://sharepoint"));
SPSiteCollection sites = webApp.Sites;
SPSite Site = sites.Add(“https://sharepointzen.wordpress.com”, "Test",
"Test Site", 1025, "STS#0", "domain\abc","Arshad Riz", “ariz@test.com”, "domain\abc1”,"Ak Riz", akriz@test.net, true);

PowerShell can also be used in place of server object model code. Please refer to : http://technet.microsoft.com/en-us/library/cc424952.aspx


Leave a comment

Invoking SharePoint Workflows manually from a Custom Timer job

I recently had a requirement to create a custom Timer job in SharePoint 2010 to manually invoke a SharePoint Custom Visual Studio developed Workflow associated with a SharePoint list. See the following code snippet for additional details.

public class ListItemWorkflowProcessingJob : SPJobDefinition
{
     enum ProcessingStatus
     {
          NotCompleted,
          Completed
     };

     public ListItemWorkflowProcessingJob()
     {
     }

     public ListItemWorkflowProcessingJob(string jobName, SPWebApplication webApplication, SPServer server, 
     SPJobLockType targetType) : base(jobName, webApplication, server, targetType)
     {
         Title = "List Item Workflow Processing timer job";
     }

     public ListItemWorkflowProcessingJob(string jobName, SPWebApplication webApplication)
     : base(jobName, webApplication, null, SPJobLockType.Job)
     {
         Title = "List Item Workflow Processing timer job";
     }

     public override void Execute(Guid contentDbId)
     {
        SPWebApplication webApplication = this.Parent as SPWebApplication;
        processListItemWorkflows(webApplication);
     }

     public void processListItemWorkflows(SPWebApplication webApplication)
     {
         using (SPSite site = webApplication.Sites["/"])
         {
          #region Action Delegates
          Action<SPListItem> CancelWorkflows = (ListItem) =>
          {
               SPWorkflowCollection workflows = ListItem.Workflows;
               foreach (SPWorkflow workflow in workflows)
               {
                   SPSecurity.RunWithElevatedPrivileges(() 
                           => SPWorkflowManager.CancelWorkflow(workflow));
               }

          };

          Action<SPListItem> StartWorkflow = (ListItem) =>
          {
               // ID value from Workflow elements.xml file
               Guid wfBaseId = new Guid("54a15d07-f2d7-4626-b82d-5a853802ad0e");
               var wfa = (from SPWorkflowAssociation spwfa in 
                          ListItem.ParentList.WorkflowAssociations
                          where spwfa.BaseId == wfBaseId && spwfa.Enabled == true
                          select spwfa).FirstOrDefault();
               site.WorkflowManager.StartWorkflow(ListItem, wfa, wfa.AssociationData, true);
          };


              #endregion Action Delegates

              site.AllowUnsafeUpdates = true;
              SPList MyList = site.RootWeb.Lists["Custom List"];

              var listItems = from SPListItem item in MyList.Items
                              orderby item.Title
                              ascending
                              where (string)item["ProcessingStatus"].ToString()
                               == ProcessingStatus.NotCompleted.ToString()
                              && item["ProcessingStatus"] != null
                              select item;

              foreach (SPListItem ListItem in listItems)  //each item in the list
              {
                 try
                 {
                     CancelWorkflows(ListItem);
                     ListItem.Update();
                     try
                     {
                        StartWorkflow(ListItem);
                     }
                     catch (Exception ex)
                     {
                         throw ex;
                     }

                     ListItem["ProcessingStatus"] = FIAProcessingStatus.Completed;
                     ListItem.Update();

                    //wait for 10 seconds
                     Thread.Sleep(10000);

                  }
                  catch (Exception ex)
                  {
                    throw ex;
                  }
                }

                MyList.Update();
                site.AllowUnsafeUpdates = false;
           }

        }
}

The  above custom timer job cancels any existing workflow instances running on SharePoint ListItems before manually invoking a new workflow instance. The Startworkflow Action<> Delegate invokes a new workflow instance on a SharePoint list item by using the workflow ID GUID value specified inthe workflow solution elements.xml file.


Leave a comment

Dynamically updating URL links within a SharePoint 2010 Content Editor Web-Part (CEWP) and reading the values from a SharePoint list using JQuery

Here is an example of dynamically updating URL links within a SharePoint 2010 Content Editor Web-Part (CEWP) and reading the values from a SharePoint list using JQuery:


<script type="text/javascript">

function processResult(xData, status) {
$(xData.responseXML).find("z\\:row").each(function() {

var keyResources1 = $("#KeyResourcesMain");
var url = $(this).attr("ows_LinkUrl");
var htmlTimeSheet = "<li><a href = " + url + ">My TimeSheet</a></li>";

keyResources1.append(html);
keyResources1.append(htmlTimeSheet);

});
}

$(document).ready(function() {
var soapEnv = "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'><soapenv:Body><GetListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'><listName>Popular Links</listName><query><Query><Where><Eq><FieldRef Name='Title'/><Value Type='Text'>My Timesheet</Value></Eq></Where></Query></query><viewFields><ViewFields><FieldRef Name='LinkUrl' /><FieldRef Name='Title' /></ViewFields></viewFields></GetListItems></soapenv:Body></soapenv:Envelope>";
$.ajax({
url: "/_vti_bin/lists.asmx",
type: "POST",
dataType: "xml",
data: soapEnv,
complete: processResult,
contentType: "text/xml; charset=\"utf-8\""
});
});

</script>

<div><h3>Key Resources</h3>
<ul id="KeyResourcesMain"></ul>
</div>

The above approach of using the JQuery Document.Ready Function is better when compared to using the JavaScript _spBodyOnLoadFunctionNames and loads a custom user defined Javascript during rendering of a page instead of loading the Custom JavaScript after rendering of the page is completed.

The functions in _spBodyOnLoadFunctionNames run after the page is finished rendering by definition. In SharePoint 2010, this effect may be more visible since in SharePoint 20010 there is more Out of box JavaScript that runs during page load. You could try to accomplish UI updates (for example updating URLs in a CEWP from SharePoint Lists as in the above example) using the server-side APIs (e.g. content placeholders, delegate controls) or using JQuery and running your script on document ready instead of waiting for the page to call the customr script after other SharePoint 2010 out of box Javascript code on is done loading on the page.


Leave a comment

Dynamically updating markup within a SharePoint 2010 Content Editor Web-Part (CEWP) using JavaScript

Here is an example of dynamically updating URL links within a SharePoint 2010 Content Editor Web-Part (CEWP) and reading the values from a SharePoint list using JavaScript.


<script type="text/javascript">

var clientContext = null;
var web = null;
ExecuteOrDelayUntilScriptLoaded(GetMyTimeSheetURL, "sp.js");

function GetMyTimeSheetURL()
{
 clientContext = new SP.ClientContext.get_current();
 web = clientContext.get_web();
 var list = web.get_lists().getByTitle('Popular Links');

var camlQuery = new SP.CamlQuery();
 camlQuery.set_viewXml('<View><Query><Where><Eq><FieldRef Name="Title"/><Value Type="Text">My Timesheet</Value></Eq></Where></Query><ViewFields><FieldRef Name="LinkUrl" /></ViewFields></View>');

this.listItems = list.getItems(camlQuery);
 clientContext.load(listItems);
 clientContext.executeQueryAsync(Function.createDelegate(this, this.onListItemsLoadSuccess),
 Function.createDelegate(this, this.onQueryFailed));

}

&nbsp;

function onListItemsLoadSuccess(sender, args) {
 var enumerator = this.listItems.getEnumerator();
 while (enumerator.moveNext()) {
 var item = enumerator.get_current();
 var url = item.get_item('LinkUrl')
 document.getElementById("contentDiv").innerHTML ='<li><a href= ' + url + '>My TimeSheet</a></li>';
 }
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());}

</script>

<div class="resources-box"><h3>Key Resources</h3>
<div id="contentDiv"><li><a href="#">My TimeSheet</a></li></div></ul></div>

</div>

The above markup can be added into a CEWP and utilizes the SharePoint 2010 JavaScript Client Object Model Features to dynamically update the URL links within the web-part based on values in a SharePoint list.  The JavaScript delegate onListItemsLoadSuccess does not return a value which is why the above code utilizes document.getElementById(“contentDiv”).innerHTML to update the markup for the HREF tag.


1 Comment

Using SPLongOperation for Synchronous Long running tasks in SharePoint

The Microsoft.SharePoint.SPLongOperation class is useful when providing consistent user feedback to users during long running synchronous operation. The documentation tells us that this class “Sets the Web page image to the image used by the server to indicate a lengthy operation (typically, an animated image with associated text)”.

For example, consider a scenario in which a SharePoint Web-Part page is used to add users to an External system by using a WCF service. The add user process maybe a lengthy operation based on the available business logic within the external system and can be wrapped in a SPLongOperation by calling the static SPLongOperation.Begin Method (String, String, SPLongOperation.BeginOperation) where the SPLongOperation.BeginOperation delegate specifies the delegate method that will begin the long operation. There are 2 string parameters which set the SPLongOperation.LeadingHTML and SPLongOperation.TrailingHTML properties (what is displayed as “the associated text”). When the call to the WCF service is completed successfully, the operation is ended by calling either the End or EndScript method, based on whether the window was opened as a dialog or not which can be verified if the query string parameter “IsDlg”, which will be equal to 1 if it is a dialog window. Here is an example for using SPLongOperation:

try
{
    SPLongOperation.Begin(
        "Calling WCF Service for adding user into External System",
        "Please wait for this process to complete. This may take a few seconds.",
        delegate(SPLongOperation longOp)
        {
            try
            {
                //Code for calling the WCF service for adding a user into an External System goes here

                // Now end the long operation
                if (Context.Request.QueryString["IsDlg"] != null)
                {
                    longOp.EndScript(String.Format(CultureInfo.InvariantCulture,
                        "<script type=\"text/javascript\">window.frameElement.commonModalDialogClose({0}, {1});</script>",
                        1, String.Format("\"{0}\"", returnValue)));
                }
                else
                {
                    string url = Context.Request.UrlReferrer.AbsoluteUri;
                    longOp.End(url,
                       Microsoft.SharePoint.Utilities.SPRedirectFlags.DoNotEndResponse,HttpContext.Current,"");
                }
            }
            catch (ThreadAbortException) { /* thrown when redirected */ }
            catch (Exception ex)
            {
                string exMessage = ex.InnerException != null ? ex.InnerException.Message : ex.Message;
                string message = String.Format("Error occurred whilst deleting relationship: {0}", exMessage);
                RedirectToErrorPage(message);
            }
        });
}
catch (ThreadAbortException) { /* thrown when redirected */ }
catch (Exception ex)
{
    string exMessage = ex.InnerException != null ? ex.InnerException.Message : ex.Message;
    string message = String.Format("Error occurred when calling WCF Service add a user into External System: {0}", exMessage);
    RedirectToErrorPage(message);
}

//The RedirectToErrorPage(message) method calls the SPUtility.TransferToErrorPage method
private void RedirectToErrorPage(string message)
{
    if (string.IsNullOrEmpty(this.Referrer))
    {
        SPUtility.TransferToErrorPage(message);
    }
    else
    {
        SPUtility.TransferToErrorPage(String.Concat(message, " {0}."), "Return to calling Web-Part page.", this.Referrer);
    }
}

Additional information on SPLongOperation can be found here:

http://blog.symprogress.com/2010/10/close-modal-dialog-when-splongoperation-finish/

http://dotnetfollower.com/wordpress/2011/08/sharepoint-how-to-use-splongoperation/


Leave a comment

SharePoint 2010 Diagnostic and Usage Analysis Logs best practice

SharePoint 2010 has improved the way the ULS logs information and now these diagnostic logging data can be written to trace files, Windows Event Viewer and a new SharePoint reporting database (new in SharePoint 2010). Trace log files are created in a Log folder under the root folder where SharePoint has been installed by default; that is also called the 14 Hive.

SharePoint diagnostic logging is very important, and extremely helpful when we encounter problems with our SharePoint environment. However, diagnostic logging can be ineffective at times, and can even cause SharePoint performance to slow down if it’s not managed properly. The one thing you should ABSOLUTELY do is move the ULS logs off of the system drive. ULS is designed to stop logging if it percieves a disk space issue and moving the logs off of the system drive ensures that logging isn’t going to fill up the system drive, and that ULS logging isn’t going to contend with your page file for disk IO. Note that in order to change the location fo the log file, the path must exist on ALL SharePoint servers, and the folder’s permissions must be set to allow the SharePoint service to write to it.

There are two sets of logs you want to move in the SharePoint 2010 farm environment, the diagnostic logs and the usage logs.

Diagnostic logs:

With Central Admin:

Central Admin > Monitoring > Configure Diagnostic Logging (/_admin/metrics.aspx). The setting is the “Trace Log” path at the bottom. It is recommended changing the Drive letter and leaving the rest of the path alone. It’ll make it easier for you to find things later on. 

With PowerShell:
You can also use PowerShell to change this. The cmdlet is Set-SPDiagnosticConfig and the parameter is –LogLocation.

Set-SPDiagnosticConfig -LogLocation “E:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\LOGS

Usage logs:

With Central Admin:

Central Admin > Monitoring > Configure web analytics and health data collection (/_admin/LogUsage.aspx). The setting is the “Log file location” setting. Set it to the same path you did the Trace Log above.

With PowerShell:

The PowerShell cmdlet to alter this is Set-SPUsageService and the parameter is –UsageLogLocation.

Set-SPUsageService -UsageLogLocation “E:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\LOGS\”


Leave a comment

SharePoint 2013 What’s New

SharePoint Foundation 2013 Preview

http://www.microsoft.com/en-us/download/details.aspx?id=30345

SharePoint Server 2013 Preview

http://technet.microsoft.com/en-US/evalcenter/hh973397.aspx?wt.mc_id=TEC_121_1_33

SharePoint Preview Site

http://sharepoint.microsoft.com/en-us/Preview/default.aspx

SharePoint 2013 Requirements

http://sharepoint.microsoft.com/en-us/Preview/sharepoint-requirements.aspx

SharePoint Designer 2013

http://www.microsoft.com/en-us/download/details.aspx?id=30346

SharePoint Server 2013 SDK

http://www.microsoft.com/en-us/download/details.aspx?id=30355

Office Web Apps Preview
http://www.microsoft.com/en-us/download/details.aspx?id=30358