Monday, February 14, 2011

Custom Variation Landing page


If you have gone through part 1 of this series then you will understand how Microsoft has implemented their variation landing page and logic
We had a requirement to implement custom variation landing page, I used word custom because we didn’t want user to get redirected using browser’s culture, instead we were using one language property in user’s profile (SharePoint User Profiles) and using that user should get redirected to actual variation site
Example: suppose a user has his language set as German, and then user should get redirected to German Variation site
Approach:
Obviously we needed to do some customization but how? we went through msdn link and got three choices as mentioned in link to create custom landing page , but out of those all we didn’t follow approach to edit OOB VariationRootLanding user control , because If you do so then you need to do those customizations on each web front end and If any service pack may override your changes
So, we decided to follow how Microsoft done , like creating custom user control , creating a custom page layout on which our user control will be and a custom publishing page using our page layout , and after all of this , set this page as welcome page of root site
see how:

Creating Custom User Control – CustomVariationLandingRoot user control


Microsoft has followed inline coding approach while they implemented their control I don’t know why
We created   a user control and added this code to code behind
What this code basically does is, maintains a Dictionary object consisting of VaraitionLabel’s language as key and VariationLabels’s web url as value, and then tries to get user’s language and uses as key to do search in dictionary object, If found then we get variation web url as value and If not then we are assigning redirection web url as source label
I will try to demonstrate this code in sample webpart you can add this code to your user control’s code behind with some changes
in code I have used hardcoding for user’s language as German , you can write your own code to get user’s language from user profile’s or according to changes you want

private ReadOnlyCollection<VariationLabel> _allLabels = null;
private Dictionary<string, string> _languageToUrl = null;
private string _language = string.Empty;
string _sourceUrl = string.Empty;
string _redirectUrl = string.Empty;

protected override void OnLoad(EventArgs e)
{
  base.OnLoad(e);
  try
  {
   using (SPSite site = new SPSite(SPContext.Current.Site.ID))
   {
     using (SPWeb web = site.RootWeb)
     {
      // This Tries to Get all User Accessible Labels
      //and for which Variation Hierarchies have been created succesfully

      _allLabels = Variations.Current.UserAccessibleLabels;

      if (_allLabels != null && _allLabels.Count > 0)
      {

       _languageToUrl = new Dictionary<string, string>();

       //Dictionary Initialization

       foreach (VariationLabel _label in _allLabels)
       {
         //Check If Source Label , If yes then set source
         //web url to variable
         if (_label.IsSource)
         {
           _sourceUrl = _label.TopWebUrl;
         }

         //Check whether key exists or not If no then add
         if (!_languageToUrl.ContainsKey(_label.Language))
         {
           //Create CultureInfo From Label

           CultureInfo _cultureInfo = CreateCulture(_label);

           if (_cultureInfo != null)
           {
             string[] _displayLanguage = _cultureInfo.EnglishName.Split('(');
                                           _languageToUrl.Add(_displayLanguage[0].Trim(), _label.TopWebUrl);

           }
          }
         }

         //Searching for Key

         _language = "German";

          _redirectUrl = _sourceUrl;

          if (!string.IsNullOrEmpty(_language))
          {
           if (_languageToUrl.ContainsKey(_language))
           {
             _redirectUrl = _languageToUrl[_language];
           }
          }

           //Standard SP Redirection
           SPUtility.Redirect(_redirectUrl, SPRedirectFlags.Trusted, HttpContext.Current);
          }

          }
         }
        }

        catch (Exception ex)
        {
          this.Controls.Add(new LiteralControl(ex.Message));
        }
        }

//Private Function to get Culture Info from Label
        private CultureInfo CreateCulture(VariationLabel label)
        {
            CultureInfo _ci = null;

            if (label != null)
            {
                string _localeId = label.Locale;

                if (!string.IsNullOrEmpty(_localeId))
                {
                     _ci = new CultureInfo(Convert.ToInt32(_localeId), false);
                }
            }

            return _ci;
        }

after all code is done , we created a custom page layout and placed this user control directly , then final step was to create a custom publishing page using page layout we made , after that we just need to set this newly created page as welcome page of root site
How to set welcome page of site, I already posted on this so you can refer this link
and that’s all .. I hope this helps someone

4 comments:

  1. I am getting error while Creating Culture Info from a Label. I am using VS2008

    //Your code
    if (!languageToUrl.ContainsKey(label.Language))
    {
    CultureInfo cultureInfo =CreateCulture(label);
    //I am getting Error as The name 'CreateCulture' does not exists in current context. Please Help

    ReplyDelete
  2. Have you added the the additional method mentioned above in your code?

    ReplyDelete
  3. I followed your code to implement Custom Variation Landing Logic. I created a dll and deployed in C:\interpub\wwwroot\wss\VirtuatDirectory\port\-app_bin folder. Register the dll in VariationRootPageLayout.aspx . I also remove reference to the VariationRootLanding.ascx control(in ~/14/Templete/ControlTemplate folder). When I hit the URL of my site, I am getiing an error in VariationRoot.aspx-An item with the same key has already been added. Kindly help me.

    ReplyDelete
  4. Getting "Same key has already been added" error.
    This is related to my previous question.-
    I have the follwing Language Variations.
    en-US (source)
    en(Global),
    fr-CA(French-Canada),
    en-CA(English-Canada),
    de-De(German(Germany)),
    fr(Global).
    When I executed the below code, Please let me know what are the values will be added to the "languageToUrl".

    if (_cultureInfo != null)
    {
    string[] _displayLanguage = _cultureInfo.EnglishName.Split('(');
    _languageToUrl.Add(_displayLanguage[0].Trim(), _label.TopWebUrl);
    }

    ReplyDelete