Running SharePoint 2013 in Azure IaaS

Moving your SharePoint Infrastructure to the Cloud? Have a requirement to host SharePoint in an IaaS solution? Look no further.

Microsoft have several Virtual Machine Sizes in Windows Azure IaaS which suit the requirements for SharePoint Server 2013 and have also certified Microsoft SharePoint Server 2013 running in Windows Azure IaaS.

The link to the whitepaper below details the best practices for deploying a SharePoint Infrastructure in Windows Azure:
SharePoint 2013 on Windows Azure Infrastructure Services
I have highlighted the important aspects of running SharePoint Server 2013 in Windows Azure IaaS below:

Supporting Infrastructure

  • Deploy a Virtual Network and deploy a gateway in Windows Azure and create a site-to-site VPN if you have not done so already.
  • Ensure that you have at least two domain controllers running in Azure IaaS to support the IaaS deployed infrastructure. They should belong to their own availability group.
  • If you plan to deploy a new forest you can review the Windows Azure documentation Install a new Active Directory forest in Windows Azure.
  • Never shutdown your domain controller in Windows Azure (Shutdown and restart only), you potentially get the infinite DHCP lease removed and at start-up, your domain controller will get a new IP address when it starts from a cold boot.

SharePoint 2013

  • Ensure that each SharePoint role belongs to the appropriate availability set for high availability. This is so that there is a separation in fault domains and the roles do not go down during maintenance.
  • Be aware of the network throughput and virtual disk limits per VM size in the depot, this is important to get the correct throughput and number of disks per role.
  • Never store anything on the temporary space drive (D:).
  • Ensure that your infrastructure points to the DNS servers defined in your VNet configuration.
  • Use a Windows Azure load balancer since SharePoint 2013 now supports load balancers that do not support sticky sessions.
  • Create gold images of your SharePoint servers so that you can deploy them from the Windows Azure Virtual Machine Gallery.

SQL Server 2012

This information should provide you the basics of getting started in your journey to deploying a SharePoint farm in Windows Azure.

If you already have a private cloud built on Microsoft Windows Server Hyper-V, I would highly recommend deploying System Center Virtual Machine Manager and App Controller to manage your private and public cloud infrastructure as a minimum. Many of the System Center products should be reviewed, planned and deployed accordingly since the there are no other solutions in the market place, that provide the comprehensive functionality which System Center provides, to deploy and manage Microsoft public and private clouds.

SharePoint 2013 Claims and the Welcome Control

Recently, one of my colleagues wanted to update the SharePoint 2013 welcome control with custom claim values, rather than the default values, when utilizing ADFS SAML claims based authentication. If the signed in users display name is not updated in the all users table on the SharePoint web site, then the welcome control will display the primary encoded format of the user id. For example, if the user was authenticated by a trusted Identity Token Issuer, utilizing the User Principle Name (UPN) as the identifier claim, the format will be as follows:

i:05.t|Trusted Identity Token Issuer Name|UPN

The SharePoint claims encoding article can be found here: SharePoint 2013 and SharePoint 2010 Claims Encoding

If you are also not planning on running a SharePoint user profile import, then setting welcome control display can be a little problematic. One approach is to have a custom control in the master page. The control can update the inner HTML of the welcome control, so that it can display a value from augmented claims. In the example below, I specifically pull out the Claim Type of Email, but depending on your scenario, you could use any valid claim augmented from the SharePoint STS which was originally provided by the identity provider STS.

Please note that you may want to check the user is authenticated first and the claims exist, as per the notes in code below.

            // Cast the Thread.CurrentPrincipal
            IClaimsPrincipal icp = HttpContext.Current.User as IClaimsPrincipal;

            string claimValueforWelcomeControl = "No Claims Found";

            // Access IClaimsIdentity which contains claims
            IClaimsIdentity claimsIdentity = (IClaimsIdentity)icp.Identity;
            // Create a Claims Collection - could use IEnumberable and then LINQ
            ClaimCollection claimsCollection = claimsIdentity.Claims;
            // Grab the type we want to display from the claimsCollection
            if (claimsCollection.Count > 0)
            {
                try
                {
                    foreach (Claim c in claimsCollection)
                    {
                        // Whichever claim type you want from claims to be displayed in the welcome control
                        if (c.ClaimType == ClaimTypes.Email)
                        {
                            // consider checking the claimtype exists in the collection first
                            if (c.Value != null)
                            {
                                // Set the Welcome Control Value to the claim value
                                claimValueforWelcomeControl = c.Value;
                            }
                        }
                    }
                }
                catch (SPException ex)

                {

                    Literal1.Text = ex.ToString();
                }
            }

            try
            {
                ClientScriptManager clientScriptManager = Page.ClientScript;
                StringBuilder sb = new System.Text.StringBuilder();
                if (!clientScriptManager.IsClientScriptBlockRegistered("WelcomeControlUpdate"))
                {
                    
                    sb.Append("<script type=\"text/javascript\">");
                    // **** consider JQuery instead: $(document).ready(function (){"); ****
                    sb.Append("window.onload = function () {");
                    // sb.Append("document.getElementById('zz4_Menu').innerHTML = 'Some Claim Value';");
                    sb.Append("document.getElementById('zz4_Menu').innerHTML = '" + "From Claims: " + claimValueforWelcomeControl + "';");
                    sb.Append("}");
                    sb.Append("</script>");
                    clientScriptManager.RegisterStartupScript(this.GetType(), "WelcomeControlUpdate", sb.ToString());
                }
            }
            catch (Exception ex)
            {
                Literal1.Text = ex.ToString();
            }



Using Riverbed Steelhead WAN Optimization Appliances with Hyper-V Replica

Microsoft have recently published a whitepaper that captures the results of bandwidth optimization experiments conducted in the Microsoft® Engineering Excellence Center (EEC) lab by using the Riverbed Steelhead appliance WAN optimization devices with Windows Server 2012 Hyper-V Replica.

Windows Server 2012 Hyper-V Replica allows asynchronous replication of Virtual Machines across Wide Area Networks. By utilizing a WAN optimization appliance, like the Riverbed Steelhead, you can improve your overall replication strategy and provide bandwidth effective WAN efficiencies. The de-duplication of the devices abilities is certainly something that provided very interesting results, which I highly recommend reviewing.

You can download the whitepaper here.

Microsoft Office 365 Resources

This post is dedicated to learning Office 365 and includes various resources. I’ll keep updating this post with additional resources in the future.

Start with a free trial account
Office 365 Free Trial

White Papers
SharePoint Online Administration Guide in Office 365 for enterprises
Office 365 Service Descriptions
Office 365 White Paper: Guidance for Office Development in Office 365
Office 365 Single Sign-On with AD FS 2.0 whitepaper

Videos
Office 365 for enterprises: A tour for administrators

Office 365 Administration
Exchange Online Administration
SharePoint Online Administration
Lync Online Administration

TechNet
Office 365 TechNet Library

Security
Office 365/Office 2013 Security Features

Support
Support for Microsoft Office 365
Office 365: Outlook and mobile device connectivity troubleshooting resources

Windows 8 Server Beta

As well as the Windows 8 Consumer Preview, don’t forget to evaluate the cool new features of Windows Server 8 Beta. It’s Cloud optmized, cost effective, more scalable and has tons of news features. Here are some key resources for you to evaluate Windows 8 Server Beta:

Microsoft Server and Cloud Platform – Windows Server 8 Beta
Windows 8 Server Beta Resources
Windows 8 Server Beta Capabilities
Windows 8 Server Beta for Developers
Windows 8 Server Beta Technical Documentation

Microsoft Windows 8 Consumer Preview is here !!

Microsoft have announced the Windows 8 consumer preview !

Download it, install it, read all about it here

You will LOVE it !!! 🙂

Windows 8 Quick Resource Links:

Start Developing for Windows 8 now
Windows 8 Resources for IT Pros
Windows 8 Consumer Preview Technical Library on TechNet
Windows 8 Product Guide
Windows Engineering Team Blog
Windows 8 FAQ

SharePoint Development: Custom Web Part Settings

This post briefly covers how to create custom web part settings in your Visual Studio solution.

In the main webPart.CS file add the following settings:

 // Custom WP Setting – English RSS URL

 [Personalizable(PersonalizationScope.Shared),

 WebBrowsable(true),

 WebDisplayName(“English RSS URL”),

 WebDescription(“Enter the English RSS URL”),

 Category(“Custom Web Part Settings”)]

 publicstring ENRSSUrl { get; set; }

 // Custom WP Setting – English RSS URL

 [Personalizable(PersonalizationScope.Shared),

 WebBrowsable(true),

 WebDisplayName(“French RSS URL”),

 WebDescription(“Enter the French RSS URL”),

 Category(“Custom Web Part Settings”)]

 publicstring FRRSSUrl { get; set; }

 Update the createChildControls method:

protected override void CreateChildControls()

{

 Control control = Page.LoadControl(_ascxPath);

 // Reference public properties in visual webpart control

 VisualWebPart1UserControl vswebcontrol = control asVisualWebPart1UserControl;

 // Pass through the values to the web part control

 vswebcontrol.toolPartENRSSUrl = ENRSSUrl;

vswebcontrol.toolPartFRRSSUrl = FRRSSUrl;

Controls.Add(control);

}

Reference the settings in the main web part control class:

public partialclass VisualWebPart1UserControlUserControl

 {

 // Public Properties

 public string toolPartENRSSUrl { get; set; }

 public string toolPartFRRSSUrl { get;set; }

 // Internal strings

 string ENURL = string.Empty;

 string FRURL = string.Empty;

 protectedvoid Page_Load(object sender, EventArgs e)

{

 // Set the string values

ENURL = toolPartENRSSUrl;

FRURL = toolPartFRRSSUrl;

 // Reference the custom web part settings

lblEN.Text = ENURL;

LblFR.Text = FRURL;

}

}

It’s as simple as this !

SharePoint 2010 Document Library Replicator: Part 4

Its been a while since my last post on this solution. The code is almost complete and this is the final update to the current solution. The solution can be downloaded from CodePlex here.

In this post, the code update covers the following areas:

1 – A new method has been added to read the configuration list where we specify source and target document libraries. A new class named SPListOperations was created with a method named queryConfigList to query the replicator configuration list for source and target libraries.

2 – The itemupdated and itemdeleted methods in the solution have been updated to call a method that performs the add and delete operation.

Changes to the Event Receiver methods

///

<summary>

///

 An item was updated.

 ///

 </summary>

 public override void ItemUpdated(SPItemEventProperties properties)

{

 base.ItemUpdated(properties);

replicatorOperation(properties,“Added/Updated”);

}

<summary>

///

An item was deleted

///

</summary>

public override void ItemDeleted(SPItemEventProperties properties)

{

 base.ItemDeleted(properties);

replicatorOperation(properties,“Deleted”);

}

New method to perform the copy/update and delete operations

public void replicatorOperation(SPItemEventProperties properties, string operation)

{

 using (SPSite spsite = newSPSite(properties.WebUrl))

 try

 {

EventFiringEnabled = false;

 if (properties.ListItem.ParentList.Title != “Replicator Logger”)

{

 SPWeb siteForLogger = spsite.OpenWeb();

 // determine target filename – the same as the source

 string targetfilename = properties.ListItem.Name.ToString();

 string SourceLibPath = properties.WebUrl + “/” + properties.ListItem.ParentList.ToString();

 string sourceLibrary = properties.ListItem.ParentList.ToString();

 string targetLibraryFromConfigList = SPListOperations.queryConfigList(siteForLogger, sourceLibrary).ToString();

 // Query the Configuration List

 if (targetLibraryFromConfigList != “NotListed”)

{

 // Copy/Delete the file to the destination library (targetlibrary)

 if (operation == “Added/Updated”)

{

 properties.ListItem.File.CopyTo(targetLibraryFromConfigList + “/” + targetfilename, true

);

}

if (operation == “Deleted”)

{

 SPFile spFileTarget = siteForLogger.GetFile(targetLibraryFromConfigList + “/” + targetfilename);

spFileTarget.Delete();

 }

 // Write to the Replicator Log – unfinished…

 ReplicatorLogger replogger = newReplicatorLogger();

 // Get the current Date and Time

 DateTime dtime = DateTime.Now;

 // Create the title for the logger list item

 string title = (dtime.Date.ToString() + “_” + dtime.Hour.ToString() + “_” + dtime.Minute.ToString() + “_” + dtime.Second.ToString() + “_” + targetfilename.ToString());

// Write to the log list

EventFiringEnabled = false;

replogger.writeToLog(title, dtime.ToShortDateString(), properties.UserDisplayName.ToString(), operation, SourceLibPath, targetfilename, siteForLogger);

}

}

}

catch (SPException spEx) { }

 finally

{

 // Enable Event Firing

 EventFiringEnabled = true;

}

 }

 SPListOperations Class and a new queryConfigList method

using Microsoft.SharePoint;

 namespace DocLibraryReplicator

{

 internal class SPListOperations 

{

publicstaticstring queryConfigList(SPWeb spWeb, string query)

{

 // Build a query.

 string result = “NotListed”;

 SPQuery spQuery = newSPQuery();

spQuery.Query =  string.Concat(“<Where><Eq>”, “<FieldRef Name=’Source Library Path and Name’/>”,“<Value Type=’Text’>” + query + “</Value>”, “</Eq></Where>”);

spQuery.ViewFields = string.Concat(“<FieldRef Name=’Source Library Path and Name’ />”);

spQuery.ViewFieldsOnly = true;

 // Fetch only the data that we need.

 // Get data from a list.

 string listUrl = spWeb.ServerRelativeUrl + “lists/Replicator Configuration”;

 SPList spList = spWeb.GetList(listUrl);

 // result = list.GetItems(spQuery);

 string sourceList = spWeb.Url + “/” + query;

 foreach (SPListItem spItem in spList.Items)

{

 string a = spItem.GetFormattedValue(“Source Library Path and Name”).ToString();

 if (spItem.GetFormattedValue(“Source Library Path and Name”).ToString() == sourceList)

result = spItem[“Target Library Path and Name”].ToString();

}

 }

 return result;

}

 }

 }

 There you have the final pieces which make up the replicator. This solution does not take checking SPFolders into consideraton, but could easily be modified to accomodate this.