Pages

Search This Blog

Friday, February 18, 2011

Restart Remote Machine IIS from Code

If anybody have requirement to restart Remote Machine IIS through code, then this is quite simple.

Scenario: If you are developing some assembly/dll, and need to deploy that dll in GAC. Each time you deploy that assembly in GAC, you must re-start IIS to see the changes.

Following code will make your life easy, because without going to server you can re-start IIS of that server.

Note:-To re-start remote machine IIS you must be an administrator of the remote computer. Either have your account added to the administrator local group of the remote computer or to the domain administrator global group.

using System.Diagnostics;
using System;

namespace ResetIISConsole
{
class Program
{
static void Main(string[] args)
{
string serverName = string.Empty;
try
{
//Read input from Console
//First argument as ServerName
serverName = args[0];
//IISReset Process resides in WINDOWS\SYSTEM32 Folder
Process iisreset = Process.Start("iisreset.exe", @"C:\windows\system32");
//Pass Name of the server
iisreset.StartInfo.Arguments = serverName;
iisreset.Start();
Console.WriteLine("SUCCESS: Done!!!");
}
catch (Exception ex)
{
Console.WriteLine("ERROR:" + ex.Message);
}
}
}
}


Another way to do this is simple command:

c:\Windows\System32>IISRESET [COMPUTERNAME]


Thursday, February 17, 2011

Custom Permission Level in Sharepoint 2010


SharePoint gives us the following Permissions Level by default.

Full Control
Has Full Control

Design
Can view, add, update, delete, approve, and customize

Contribute
Can view, add, update, and delete list items and documents

Read
Can view pages and list items and download documents

Limited Access
Can view specific lists, document libraries, list items, folders, or documents when given permissions

View Only
Can view pages, list items, and documents. Document types with server-side file handlers can be viewed in the browser but not downloaded
Suppose we have a requirement like we need to give the Permissions in such a way that a user can add and edit the item but will not be able to delete the Item in a list/Document Library or any other requirement which can not be fulfilled by using the default Permission Level.
In such scenario we can create a Custom Permission Level in which we can specify which permission set it should contain.
In this article we will see how to create a Custom Permission Level.
Step 1: Click on Site Permissions under Site Actions Menu.

Step 2: Click on Permission Level as shown in the below figure.

Step 3: Click on Add a Permission Level

Step 4: Select the appropriate ‘Permission Set’ by checking the checkboxes and click on Create Button.

Custom Permission Level has been created. 

Now use this Custom Permission Level as per your requirement.

Sunday, February 13, 2011

Advantage of Storing custom information in Content Type XmlDocument Element

Content types enable us to manage the settings for a category of information in a centralized, reusable way. It allows us to store information in a number of ways. One of them which I found very important is XmlDocument. Many times we have project requirements where we are supporting inheritance in custom content types and there comes XmlDocument very handy. XmlDocument elements included in a site content type are automatically copied into any children based on that content type and we are not required to do any custom code for that. A content type can include any number of XMLDocument elements and we can manipulate them programattically through the object model. The contents of each XmlDocument element can conform to any given schema; however, they must be valid XML.

Add XmlDocument to Custom Content type:

public SPContentTypeId CreateContentType(out Boolean IsExists, XmlNode objNode)
{
SPContentTypeId ContentTypeID = default(SPContentTypeId);
SPContentType CustomContentType = null;
SPWeb objSPRootWeb = SPContext.Current.Web;
XmlDocument doc = new XmlDocument();

try
{
CustomContentType = new SPContentType(objSPRootWeb.AvailableContentTypes[“Document”], objSPRootWeb.ContentTypes, “TestContentType”);
CustomContentType.Description = “TestContentType Description”;
CustomContentType.Group = “TestContentType Group”;
doc.LoadXml(objNode.OuterXml);
CustomContentType.XmlDocuments.Add(doc);
objSPRootWeb.ContentTypes.Add(CustomContentType);
CustomContentType.Update();
ContentTypeID = CustomContentType.Id;
}
catch (Exception Ex)
{
}
return ContentTypeID;
}

Retreive a XmlDocument:
CustomContentType.XmlDocuments[index];

Delete a XmlDocument:

CustomContentType.XmlDocuments.Delete(“Xml schema namespace that you provided in xml document”);

Thanks

Friday, February 11, 2011

Publishing Sharepoint 2007 Publishing Pages,Master pages using Object Model

Requirement : We are having 150+ pages. So every time we have to demo when we have to go to pages library and master page library to check the publishing status. It was tedious task to make sure that all the pages, master pages and css file in style library are check in and published.
Solution : We have create a console application so every time when we needs all the pages to be check in and approve all we have to do is to run the console applicaton .
Code:


using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;
namespace Publishing_Sharepoint_Pages
{
class Program
{
static void Main(string[] args)
{
//Get the reference of site object
using (SPSite site = new SPSite("http://test"))
{
//Get the spweb object
using (SPWeb webs = site.OpenWeb())
{
// To publish all the page in pages library
//Get the publishing instance of the web
PublishingWeb pubWeb = PublishingWeb.GetPublishingWeb(webs);
//Get the pages library
PublishingPageCollection pages = pubWeb.GetPublishingPages();
foreach (PublishingPage page in pages)
{
SPModerationInformation moderationStatus = page.ListItem.ModerationInformation;
//Check if the page is not approved
if (moderationStatus.Status != SPModerationStatusType.Approved)
{
// the page page status approved and update the page status
page.ListItem.ModerationInformation.Status = SPModerationStatusType.Approved;
page.Update();
}
}
// Code to publish the master page
//Get the master page libaray reference
SPList masterPageGallery = site.GetCatalog(SPListTemplateType.MasterPageCatalog);
//Navigate the all item in master page
// This will also include all the page layouts
foreach (SPListItem galleryPage in masterPageGallery.Items)
{
//if the page is status in not published
if (!galleryPage.HasPublishedVersion)
{
//Check in the page with automated comments and set the status to checkin
galleryPage.File.CheckIn("Automatically approved", SPCheckinType.MajorCheckIn);
galleryPage.File.Update();
// approve the page with comments
galleryPage.File.Approve("Automatically approved");
galleryPage.File.Update();
}
}
// Update the style library items
SPList styleLibrary = webs.Lists["Style Library"];
//Get all the css from the style library
SPFolder editingMenuFolder = styleLibrary.RootFolder;
foreach (SPFile cssFile in editingMenuFolder.Files)
{
// if the file is not checkin then check in the file with comments.
if (cssFile.CheckOutStatus != SPFile.SPCheckOutStatus.None)
{
cssFile.CheckIn("Automatically approved");
cssFile.Update();
}
}
}
}
}
}
}

Prevent a Field Value From Being Edited without Event Handler

In some scenarios, user may ask for a field which should not be editable after information has been added to it. Or many times we may want to disallow user to delete that field. This can be easily achieved through code by changing the properties of SPField object.

//Get the field that you want to update
SPField objSPField = objSPWeb.Fields.GetField("Your Field Title");

if (objSPField != null)

{
//change the properties
objSPField.AllowDeletion = true;
objSPField.ShowInDisplayForm = true;

objSPField.ShowInListSettings = false;
objSPField.ShowInEditForm = false;
objSPField.ShowInNewForm = true;
objSPField.Update();
}

Reading XML Through Feature

In a scenario we have to create the whole site on the activation of feature, so for that we used a xml, which contains all the information regarding it.
This posts shows how we can read the xml (custom.xml) through feature, the custom.xml should be placed along with the feature.xml

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
XmlNodList objRootNode;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(properties.Definition.RootDirectory + "XML_FILE_NAME");
objRootNode = xmlDoc.SelectNodes("ChannelStaffing");
foreach (XmlNode objNode in objRootNode[0].ChildNodes)
{
foreach(XmlNode objChildNode in objNode.ChildNodes)
{
//Your code here
}
}
}

Enabling Intellisense in Sharepoint javascript client OM :Sharepoint 2010

We recently came across a requirement in one of our projects to write code in javascript client OM like checking which features are enabled on the web.While we are writing code in javascript client OM, one of the things you would love to have is intellisense which can help you find the right methods to use in the client OM.

Well, I decided to explore more on this and found that you can enable sharepoint intellisense in a javascript file (in Visual Studio 2010) by adding following 2 lines of code on the top of your javascript file:

/// <reference path="C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\MicrosoftAjax.js" />
/// <reference path="C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\SP.debug.js" />

Adding these lines enables the intellisense as you can see in the screenshot:

Here, I have added reference to 2 of the files in the '14 hive' layouts directory.Depending on your need , you might need to add reference to other javascript files in this directory to enable intellisense.

We can also add this intellisense to application pages and visual webparts.More details on this can be found in this article in MSDN:
 http://msdn.microsoft.com/en-us/library/ff798328.aspx

Create Browsable Webpart Property

Sometimes there are requirements like we need to create a webpart which can be configured from the UI itself.
The solution is to create a webpart property which can be browse through UI so that user of the webpart can change the value accordingly and configure the webpart.
To add the Browsable Properties in the Toolpane of the webpart add the below code snippet  into your webpart code and deploy it.

public class TestWebPartProperty : WebPart
    {
        //WebBrowsable true - It will make the property to be browse in tool pane
        //Category - It will create the property section in the property tool pane
        //personilation - will share the personalized data to all users.
        //WebDisplay Name - It is the caption or lable of the property to be shown in property tool pane

        [WebBrowsable(true), Category("Custom Properties"), Personalizable(PersonalizationScope.Shared), WebDisplayName("CheckBox")]
        public bool Prop_CheckBox { get; set; }

        [WebBrowsable(true), Category("Custom Properties"), Personalizable(PersonalizationScope.Shared), WebDisplayName("TextBox")]
        public string Prop_TextBox { get; set; }


        protected override void CreateChildControls()
        {
            Label lblTextBoxValue = new Label ();
            Label lblCheckBoxValue = new Label ();

            lblCheckBoxValue.Text = Prop_CheckBox.ToString();
            lblTextBoxValue.Text = Prop_TextBox.ToString();

            this.Controls.Add(lblCheckBoxValue);
            this.Controls.Add(lblTextBoxValue);           
        }

After installing the webpart click on webpart click on Edit web part.

You will see your Custom Properties section in the Tool Pnae of the webpart. Now change the property to configure your webpart.


Now click on Ok button and it will show the custom properties value in the lables created.

Thursday, February 10, 2011

Hide the Site Settings Link in SharePoint Portal

In SharePoint Portal, if you want to hide the Site Settings link under Site Actions, add this to your custom style sheet (CSS):
#SettingsOrReturnURL {display: none}
All this does is change the display of the link itself to none.
So you aren't actually removing it from the code.


Saturday, February 5, 2011

Dump SharePoint Lists Data into SQL Server Tables using SqlBulkCopy

In one of our projects it is required to clean and normalize SharePoint Data and dump that data into SQL server so that any third party can consume that data for reporting purposes. For that we created a timer job that runs every night and does the job....  Here is the approach that we took for implementation


Create a SharePoint Timer job  and add these two references

using System.Data;
using System.Data.SqlClient;



class DatabaseDump : SPJobDefinition
    {
        // No Argument Constructor (required for the system internal operation)
        public DatabaseDump()
        {
        }

        public DatabaseDump(string JobName, SPWebApplication objWebApplication)
            : base(JobName, objWebApplication, null, SPJobLockType.Job)
        {

        }


        public override void Execute(Guid targetInstanceId)
        {

            SPWebApplication currentWebApplication = this.WebApplication;
            try
            {
                using (SPSite currentSite = currentWebApplication.Sites[0])
                {
                    //todo:call export program
                    ExportData(currentSite.Url);
                 }
            }
            catch (Exception ex)
            {
                //exception handling here
            }
        }
    }


Step 2 : Create a function for ExportData

public void ExportData(string SpSiteURL)
        {
            DataTable SourceTable;
            DataTable UserMappingTable;
            DataRow dr;
            DataRow drMapping;
            string tableName;
            string connectionString;
            SPQuery query;
            try
            {
                connectionString = "SQL SERV ER CONNECTION STRING";
                if (!string.IsNullOrEmpty(connectionString))
                {
                    using (SqlConnection connection = new SqlConnection(connectionString))
                    {
                        connection.Open();
                        if (connection != null)
                        {
                            using (SPSite objSite = new SPSite(SpSiteURL))
                            {
                                using (SPWeb currentWeb = objSite.OpenWeb())
                               {
                                    //first of all get the data of all lists in the system
                                    foreach (SPList DFList in currentWeb.Lists)
                                    {
                                        try
                                        {
                                            if (!DFList.Hidden)
                                            {
                                                foreach (SPView view in DFList.Views)
                                                {
//we created a view for the data to be exported but default view can also be used here

                                                    if (view.Title =="Reports View")
                                                    {
                                                        SourceTable = DFList.GetItems(view).GetDataTable();
                                                        if (SourceTable != null)
                                                        {
                                                            //clean table name if required
                                                            tableName = CleanupSQLOBjectName(DFList.Title);
                                                        //drop and create new table first or if you don't want to do this then truncate it first                  
                                       CreateTable(connection, tableName, SourceTable);
                                                            BulkCopy(connection, tableName, SourceTable);
                                                        }
                                                        else
                                                        {
                                                            //no data in this list
                                                            //we need to truncate the existing data for this list now
                                                            tableName = CleanupSQLOBjectName(DFList.Title);
                                                            TruncateTable(connection, tableName);

                                                        }
                                                        break;
                                                    }
                                                }
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                          //handle exception here
                                        }
                                    }
        }




   private string CleanupSQLOBjectName(String SQLObjectName)
        {
            StringBuilder tempSb = new StringBuilder(SQLObjectName);
            tempSb = tempSb.Replace("/", "_");
            //these are two types of dashes
            tempSb = tempSb.Replace("–", "_");
            tempSb = tempSb.Replace("-", "_");
            tempSb = tempSb.Replace("(", "_");
            tempSb = tempSb.Replace(")", "_");
            tempSb = tempSb.Replace(" ", "_");
            tempSb = tempSb.Replace("_x0020_", "_");
            tempSb = tempSb.Replace("_x002f_", "_");
            tempSb = tempSb.Replace("__", "_");
            if (tempSb.Equals("group"))
            {
                tempSb.Replace("group", "group_1");//"Group" is a reserved word
            }
            return tempSb.ToString();
        }




private void CreateTable(SqlConnection connection, string tableName, string[] columns, string[] dataTypes)
        {
            StringBuilder strBuilder;
        
            SqlCommand cmd;

            //first drop this table
            DropTable(connection, tableName);


            //now we need to create table
            strBuilder = new StringBuilder();
            strBuilder.Append("CREATE TABLE " + tableName + " (");

            for (int i = 0; i < columns.Length; i++)
            {
                strBuilder.Append("[" + columns[i] + "] " + dataTypes[i] + ", ");
            }

            strBuilder.Append(")");


            cmd = new SqlCommand();

            cmd.Connection = connection;
            cmd.CommandType = CommandType.Text;
            cmd.CommandText = strBuilder.ToString();
            cmd.ExecuteNonQuery();
        }





   private void BulkCopy(SqlConnection connection, string tableName, DataTable SourceTable)
        {
            //now copy the data
            using (SqlBulkCopy bulkcopy = new SqlBulkCopy(connection))
            {
                //Set destination table name
                //to table previously created.
                bulkcopy.DestinationTableName = tableName;
                bulkcopy.WriteToServer(SourceTable);
            }
        }


This will update all the data of sharepoint lists in a SQL server database. You can add code to normalize lookup columns, multivalue columns etc and can also extend it to create child tables for lookup data..

Let us know if somebody require any assistance in extending this code.

Friday, February 4, 2011

Simple and Fastest way to Delete All Items from a SharePoint List

Deleting a large number of items from SharePoint list, the best way I found was to use "SPContext.Current.Site.RootWeb.ProcessBatchData" as it avoided the API and was considerably faster.

I have created a Console utility to achieve this. This utility accepts two arguments:
1. Server URL
2. List Name

Below is the full code of the utility:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;

namespace DeleteAllItemsFromList
{
class Program
{
static void Main(string[] args)
{
string serverUrl = string.Empty;
string listName = string.Empty;
if (args.Count() > 1)
{
try
{
//Read input from Console
//First argument as ServerURL
serverUrl = args[0];
//Second argument as ListName
listName = args[1];
using (SPSite site = new SPSite(serverUrl))
{
using (SPWeb web = site.RootWeb)
{
SPList list = web.Lists[listName];
SPListItemCollection splic = list.Items;
StringBuilder batchString = new StringBuilder();
batchString.Append("");

foreach (SPListItem item in splic)
{
batchString.Append("");
batchString.Append("" + Convert.ToString(item.ParentList.ID) + "");
batchString.Append("" + Convert.ToString(item.ID) + "");
batchString.Append("Delete");
batchString.Append("
");
}

batchString.Append("
");

web.ProcessBatchData(batchString.ToString());

}
}

Console.WriteLine("Done.");
}
catch (Exception exc)
{
Console.WriteLine("ERROR:" + exc.Message);
}
}
else
{
Console.WriteLine("ERROR: Please provide serverUrl[0] and listName[1] as arguments.");
}
}
}
}


Happy Coding!!!

Redirect user on preferred language

If you are working on SharePoint multi lingual portal and want to redirect the user on his preferred language, you need to customize the variationRoot.aspx page. This page is created by SharePoint when the variation labels created in the site. it's available on the pages library of the root site.
variationRoot.aspx internally refers the "VariationsRootLanding.ascx" control which contains the logic of redirecting user on source variation language site. To customize this, you need to
  • Create a copy of VariationsRootLanding.ascx control available in the 14 hive folder. (14\TEMPLATE\CONTROLTEMPLATES).
  • Assign a code behind file to the control.

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="XYZVariationRootLanding.ascx.cs"
Inherits="XYZ.XYZ.Web.XYZVariationRootLanding" %>
<%@Assembly Name="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%>
<%@Assembly Name="Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%>
<%@Register TagPrefix="CMS" Assembly="Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" namespace="Microsoft.SharePoint.Publishing.WebControls"%>
<%@ Import Namespace="System.Collections" %>
<%@ Import Namespace="System.Collections.Specialized" %>
<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.Collections.ObjectModel" %>
<%@ Import Namespace="System.Globalization" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Import Namespace="Microsoft.SharePoint.Utilities" %>
<%@ Import Namespace="Microsoft.SharePoint.WebControls" %>
<%@ Import Namespace="Microsoft.SharePoint.Publishing" %>

  • Add the following code in the code behind
public partial class XYZVariationRootLanding : System.Web.UI.UserControl
{
private const string QualityValuePrefix = ";q=";
private enum PropertiesOnLabelToUse
{
Language,
Locale
}
private enum MatchingPreference
{
ImpreciseOrderFirst,
PreciseMatch
}
private PropertiesOnLabelToUse PropertyOnLabelToUse
{
get { return this.propertyOnLabelToUse; }
set { this.propertyOnLabelToUse = value; }
}
private PropertiesOnLabelToUse propertyOnLabelToUse = PropertiesOnLabelToUse.Locale;
private MatchingPreference PreferenceOrder
{
get { return this.preferenceOrder; }
set { this.preferenceOrder = value; }
}
private MatchingPreference preferenceOrder = MatchingPreference.ImpreciseOrderFirst;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
string targetUrl = this.GetRedirectTargetUrl();
if (!string.IsNullOrEmpty(targetUrl))
{
SPUtility.Redirect(targetUrl, SPRedirectFlags.Default, Context);
}
}
private string GetRedirectTargetUrl()
{
try
{
ReadOnlyCollection spawnedLabels = Variations.Current.UserAccessibleLabels;
LoggedInUser loggedInUser = new LoggedInUser();
string ReturnURL = string.Empty;
string XYZURL = string.Empty;
loggedInUser.LoginName = SPContext.Current.Web.CurrentUser.LoginName;
if (spawnedLabels.Count > 0)
{
string sourceLabelUrl = string.Empty;
Dictionary cultureCodeToUrlMapping = new Dictionary();
Dictionary cultureCodeStrippedToUrlMapping = new Dictionary();
foreach (VariationLabel label in spawnedLabels)
{
if (label.IsSource)
{
sourceLabelUrl = label.TopWebUrl;
}
CultureInfo labelCultureInfo = this.GetLabelCultureInfo(label);
string labelCultureInfoName = labelCultureInfo.Name.ToUpperInvariant();
if (!cultureCodeToUrlMapping.ContainsKey(labelCultureInfoName) || label.IsSource)
{
cultureCodeToUrlMapping.Remove(labelCultureInfoName);
cultureCodeToUrlMapping.Add(labelCultureInfoName, label.TopWebUrl);
string strippedCode = labelCultureInfoName.Split('-')[0];
if (!cultureCodeStrippedToUrlMapping.ContainsKey(strippedCode) || label.IsSource)
{
cultureCodeStrippedToUrlMapping.Remove(strippedCode);
cultureCodeStrippedToUrlMapping.Add(strippedCode, label.TopWebUrl);
}
}
}
string matchedUrl;
if (MatchingPreference.ImpreciseOrderFirst == this.preferenceOrder)
{
matchedUrl = this.GetRedirectTargetUrlImpreciseOrderFirst(
cultureCodeToUrlMapping, cultureCodeStrippedToUrlMapping);
}
else
{
matchedUrl = this.GetRedirectTargetUrlPreciseMatch(
cultureCodeToUrlMapping, cultureCodeStrippedToUrlMapping);
}
ReturnURL = (string.IsNullOrEmpty(matchedUrl) ? sourceLabelUrl : matchedUrl);
XYZURL = GetXYZLanguageURL();
if (string.IsNullOrEmpty(XYZURL))
{
return ReturnURL;
}
else
{
return XYZURL;
}
}
}
catch (Exception ex)
{
LogUtility logUtility = new LogUtility();
logUtility.ManageException(ex.Message, ex);
Response.Redirect(SPContext.Current.Site.RootWeb.Url + "/Pages/Exception.aspx");
}
return null;
}
private string GetXYZLanguageURL()
{
// Logic for creating the redirection URL
}
private CultureInfo GetLabelCultureInfo(VariationLabel label)
{
if (PropertiesOnLabelToUse.Locale == this.propertyOnLabelToUse)
{
return new CultureInfo(Convert.ToInt32(label.Locale, CultureInfo.InvariantCulture));
}
else
{
return new CultureInfo(label.Language);
}
}
private string GetRedirectTargetUrlImpreciseOrderFirst(Dictionary cultureCodeToUrlMapping, Dictionary cultureCodeStrippedToUrlMapping)
{
string[] browserPrefLanguages = this.GetUserLanguages();
if (null == browserPrefLanguages)
return null;
string browserPrefLang;
string browserPrefLangStripped;
for (int i = 0; i <>
{
browserPrefLang = browserPrefLanguages[i].ToUpperInvariant();
if (cultureCodeToUrlMapping.ContainsKey(browserPrefLang))
{
return cultureCodeToUrlMapping[browserPrefLang];
}
browserPrefLangStripped = browserPrefLang.Split('-')[0];
if ((browserPrefLang != browserPrefLangStripped) &&
(cultureCodeToUrlMapping.ContainsKey(browserPrefLangStripped)))
{
return cultureCodeToUrlMapping[browserPrefLangStripped];
}
if (cultureCodeStrippedToUrlMapping.ContainsKey(browserPrefLangStripped))
{
return cultureCodeStrippedToUrlMapping[browserPrefLangStripped];
}
}
return null;
}
private string GetRedirectTargetUrlPreciseMatch(Dictionary cultureCodeToUrlMapping, Dictionary cultureCodeStrippedToUrlMapping)
{
string[] browserPrefLanguages = this.GetUserLanguages();
if (null == browserPrefLanguages)
return null;
for (int i = 0; i <>
{
string browserPrefLanguageName = browserPrefLanguages[i].ToUpperInvariant();
if (cultureCodeToUrlMapping.ContainsKey(browserPrefLanguageName))
{
return cultureCodeToUrlMapping[browserPrefLanguageName];
}
}
for (int i = 0; i <>
{
string browserPrefLanguageName = browserPrefLanguages[i].ToUpperInvariant();
if (cultureCodeStrippedToUrlMapping.ContainsKey(browserPrefLanguageName))
{
return cultureCodeStrippedToUrlMapping[browserPrefLanguageName];
}
}
string browserPrefLangStripped;
for (int i = 0; i <>
{
browserPrefLangStripped = browserPrefLanguages[i].Split('-')[0].ToUpperInvariant();
if (cultureCodeToUrlMapping.ContainsKey(browserPrefLangStripped))
{
return cultureCodeToUrlMapping[browserPrefLangStripped];
}
}
for (int i = 0; i <>
{
browserPrefLangStripped = browserPrefLanguages[i].Split('-')[0].ToUpperInvariant();
if (cultureCodeStrippedToUrlMapping.ContainsKey(browserPrefLangStripped))
{
return cultureCodeStrippedToUrlMapping[browserPrefLangStripped];
}
}
return null;
}
private string[] GetUserLanguages()
{
string[] browserPrefLanguages = Page.Request.UserLanguages;
if (null != browserPrefLanguages)
{
int qualityIndexPos = -1;
for (int i = 0; i <>
{
qualityIndexPos = browserPrefLanguages[i].IndexOf(QualityValuePrefix, StringComparison.Ordinal);
if (qualityIndexPos > 0)
{
browserPrefLanguages[i] = browserPrefLanguages[i].Substring(0, qualityIndexPos);
}
}
}
return browserPrefLanguages;
}
private string ConcatUrls(string firstPart, string secondPart)
{
if (firstPart.EndsWith("/"))
{
if (secondPart.StartsWith("/"))
{
firstPart = firstPart.TrimEnd('/');
}
return firstPart + secondPart;
}
else
{
if (secondPart.StartsWith("/"))
return firstPart + secondPart;
else
return firstPart + "/" + secondPart;
}
}
}
  • Compile the control and deploy DLL in the bin/GAC fodler.
at this point, we are done with the control customization and remaining part is to integrate the custom control with variationRoot.aspx page so user will redirect on preferred language.
for the integration of the control, download the variationrootlayout.aspx file available in the master pages folder "_catalogs/masterpage/Forms/AllItems.aspx" of the site and add the following code at the start of the page.
<%@ Register TagPrefix="Publishing" TagName="VariationsRootLanding" src="~/_controltemplates/XYZVariationRootLanding.ascx"%>
this registration will integrate the custom control with the default page. Now when you access the site, SharePoint will call control you have created and redirect based on the logic implemented in custom control.

Adding the WebPart in a Publishing Site Dynamically

When adding WebPart dynamically on a Publishing Site Page we need to define three things
1. WebPart to be Added
2. Zone
3. ZoneIndex
The Code Snippet is shown below:
SPLimitedWebPartManager manager = objFile.GetLimitedWebPartManager(System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);
manager.AddWebPart(objWebPart, Zone, ZoneIndex);
objweb.Update();
  • Here objWebPart is the object of the WebPart to be added.
  • Zone is the zone where the WebPart is to added.
o Zones for default.aspx can be:
1. TopColumnZone
2. LeftColumnZone
3. RightColumnZone
o Zones for BlankWebPart.aspx Layout can be:
1. Header
2. TopLeftRow
3. TopRightRow
4. CenterLeftColumn
5. CenterColumn
6. CenterRightColumn
7. Footer
8. RightColumn
  • ZoneIndex is the index of the WebPart in that Particular Zone, by default its zero.