Pages

Wednesday, March 23, 2011

Change PublishingPageLayout of Page Programmatically

After launch of SharePoint 2010 we all came to know that platform is improved heavily in all aspects and some enhancements in web content management too
We can easily change the layout of any Publishing Page using a ribbon in SharePoint 2010
But many of us are still in confusion that how we can achieve this using MOSS 2007? Rather some people think that we cannot change the page layout of page using MOSS 2007, but this is not true
Well, to know how to do this in MOSS 2007, here are some steps
1.    Browse the page for which you want to change page layouts (of course this should be a publishing page)
2.    If you are working with Publishing Site, click on Site Actions and select Show Page editing toolbar (If you are working with custom master pages , and see that this option is grayed out then make sure that you have added PublishingConsole control entry on master page)
3.    Now you will be able to see Page Editing tool bar, now select Page option , a drop down will appear , there you have to select Page Settings and Schedule option
4.    After selecting this you will see a page will be opened, scroll down and find option Page Layout
5.    Now this is where you can apply page layouts to page , select different page layout from dropdown and click ok
I hope now your previous page layout for page gets changed J
but there are some cases I faced where I wanted to change the layout of the page but after doing all these steps when I reached to the page where we can change page layouts , I didn’t find the dropdown filled with other page layouts , so I was not able to change
Now what to do in this case?
Well as developer, we always have code to help us , so decided to do these all using SP object model
And here is the code what I have done, this works for me at least J
Code just tries to open root web, gets collection of pages created with given page layout, searches the given page in this collection, and applies new given page layout the page and done
There can be multiple ways to do this, and code can be modified for more flexibility and according to need


static void Main(string[] args)
{
 #region Variables

 string _siteUrl = string.Empty;
 string _pageName = string.Empty;
 string _pageLayouts = string.Empty;
 string _newPageLayout = string.Empty;
 string _responce = string.Empty;
 PublishingPageCollection _pages = null;

 #endregion

 try
 {
   Console.WriteLine("Site Url: ");
   _siteUrl = Console.ReadLine();

   if (!string.IsNullOrEmpty(_siteUrl))
   {
    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
      using (SPSite site = new SPSite(_siteUrl))
      {
        using (SPWeb web = site.RootWeb)
        {
          if (web != null)
          {
           if (PublishingWeb.IsPublishingWeb(web))
           {
             PublishingWeb pWeb = PublishingWeb.GetPublishingWeb(web);
             Console.WriteLine("Search Pages with Layout: ");
             _pageLayouts = Console.ReadLine();

             if (!string.IsNullOrEmpty(_pageLayouts))
             {
string query = @"<Where><Contains><FieldRef   Name='PublishingPageLayout' /><Value Type='URL'>" + _pageLayouts + "</Value></Contains></Where>";
                 
_pages = pWeb.GetPublishingPages(query);
             }

             do
             {
              if (_pages != null)
              {
               Console.WriteLine();
               Console.WriteLine("Search Page With Name: ");
               _pageName = Console.ReadLine();

               //LINQ to get actual page for processing
PublishingPage _desiredPage = _pages.Where(p => p.Name.ToLower().Contains(_pageName.ToLower())).FirstOrDefault();

                                              

   if (_desiredPage != null)
               {
                if (_desiredPage.ListItem.File.Level != SPFileLevel.Checkout)
                {
                                                        Console.WriteLine("Processing.." + _desiredPage.Name);
                                                        _desiredPage.ListItem.File.CheckOut();

                  Console.WriteLine("which Page Layout to apply?");
                  _newPageLayout = Console.ReadLine();

_desiredPage.ListItem["PublishingPageLayout"] = @"/_catalogs/masterpage/" + _newPageLayout;
                                                        _desiredPage.ListItem.Update();

_desiredPage.ListItem.File.CheckIn(string.Empty);

                  if (pWeb.PagesList.EnableMinorVersions)
                  {
_desiredPage.ListItem.File.Publish("Page Layout Changed..");
                  }
                   if (pWeb.PagesList.EnableModeration)
                   {
_desiredPage.ListItem.File.Approve("Approved by Console Application");
                   }

                   Console.WriteLine("Page Layout Updated");

                   Console.WriteLine("do you want to continue?");
                    _responce = Console.ReadLine();

                  }
                else
                {
Console.WriteLine("Page is already Checked out to user " + _desiredPage.ListItem.File.CheckedOutBy.Name);
                }
               }
               else
               {
                 Console.WriteLine("Page Not Found!!");
               }
              }
             }
while (_responce.ToLower().Equals("y") || _responce.ToLower().Equals("yes"));

            if (pWeb != null)
            {
              pWeb.Close();
            }

           }
          }
        }
       }
      });
     }
     else
     {
      Console.WriteLine("Invalid Site Url");
     }

    }
    catch (Exception ex)
    {
      Console.WriteLine("{0}:{1}", "Error", ex.Message);
    }

     Console.ReadLine();
   }

Wednesday, March 16, 2011

Get PublishingPageContent using SharePoint Web Services

Well.. this was something interesting I was looking into for few hours and came up with quick solution
We can easily get the PublishingPageContent of any Publishing Page using Publishing API but what If we want to achieve this using SharePoint Web Services?
Here is sample code,
I have  created a simple console application where I am trying to access SharePoint Pages List data using Lists.asmx
we just need to pass the url of the site and title of the page , this creates a local .htm file which has PublishingPageContents and Image if has any
Splitting code is basically done to refractor the urls of images because file is getting saved locally

I know that this code is somewhat dirty and can be much improved but that was just a quick solution I figured out and so posted
I hope this helps someone (at least to try some trick) J
Reference : SharePoint Magazine

static void Main(string[] args)
{
  string siteUrl = string.Empty;
  string pageName = string.Empty;
  Console.WriteLine("Enter Site Name:");
  siteUrl = Console.ReadLine();
  Console.WriteLine("Enter Page Name:");
  pageName = Console.ReadLine();
  Uri _uri = new Uri(siteUrl);

  #region Get Publishing Page Content

  StringBuilder _contentImageBuilder = null;

  try
  {
    ListsSvc.Lists lsts = new ConsumeWebService.ListsSvc.Lists();
    lsts.UseDefaultCredentials = true;
    lsts.Url = siteUrl + @"/_vti_bin/Lists.asmx"; ;

    System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
    System.Xml.XmlElement query = xmlDoc.CreateElement("Query");
    System.Xml.XmlElement viewFields = xmlDoc.CreateElement("ViewFields");
    System.Xml.XmlElement queryOptions = xmlDoc.CreateElement("QueryOptions");

    /*Use CAML query*/

    //Querying Pages with Required Page Name
    query.InnerXml = @"<Where><Contains><FieldRef Name='Title' /><Value Type='Text'>" + pageName + "</Value></Contains></Where>";

    //ViewFields to be returned with Result
    viewFields.InnerXml = "<FieldRef Name=\"Title\" /><FieldRef Name=\"PublishingPageContent\" />";

    queryOptions.InnerXml = string.Empty;

   //Get Data 
   System.Xml.XmlNode nodes = lsts.GetListItems("Pages", string.Empty, query, viewFields, "500", null, null);

   foreach (System.Xml.XmlNode node in nodes)
   {
     if (node.Name == "rs:data")
     {
       for (int i = 0; i < node.ChildNodes.Count; i++)
       {
         if (node.ChildNodes[i].Name == "z:row")
         {
           if (node.ChildNodes[i].Attributes["ows_PublishingPageContent"] != null)
           {
             _contentImageBuilder = new StringBuilder();

             string[] tokens = node.ChildNodes[i].Attributes["ows_PublishingPageContent"].Value.Split('"');
             foreach (string token in tokens)
             {
              if (token.StartsWith("/"))
              {
_contentImageBuilder.AppendFormat("{0}://{1}{2}", _uri.Scheme, _uri.Host, token);
              }
              else
              {
                 _contentImageBuilder.Append(token);
              }
             }
            }

if (_contentImageBuilder != null && !string.IsNullOrEmpty(_contentImageBuilder.ToString()))
{
StreamWriter writer= new StreamWriter("C:\\contents.htm", true, Encoding.UTF8);                                                                        writer.Write(_contentImageBuilder.ToString());
  writer.Close();
}

}
}
}
}
}
catch (Exception ex)
{
  Console.WriteLine("Error " + ex.Message);
}
#endregion
}

Talk to SharePoint using Web Services

most of the times , being a typical SharePoint developer includes task likes customizing SharePoint and build your custom solutions on top of SP platform , mostly to achieve this people use SharePoint object model (Server object model)
But there are some cases where you will not be working on server where SharePoint is not installed and still you will need to get the data or communicate to SharePoint platform or sites
Well to achieve such functionalities, MOSS 2007 had only one way and that’s by using SharePoint WebServices
Now with the SharePoint 2010 one have lot of options available now such as SharePoint WebServices, Client object model, REST web services
We will have a quick look on how we can code using SharePoint web services,
I have create a sample console application in which I am making use of SharePoint 2007 Web Services
Typically all SharePoint web services (.asmx) are found in [12 hive]\ISAPI folder and can be accessed like http://servername/_vti_bin/webservicename.asmx
to get started I will create a sample console application and will add Web Reference of Webs.asmx (_vti_bin/Webs.asmx)
after adding this web reference we can use web service like this, I am trying to retrieve all available webs in site collection and urls

I hope this helps someone J

static void Main(string[] args)
{
   string siteUrl = string.Empty;
   Console.WriteLine("Enter Site Name:");
   siteUrl = Console.ReadLine();
   Uri _uri = new Uri(siteUrl);
   try
   {
      WebsSvc.Webs _webs = new ConsumeWebService.WebsSvc.Webs();
      _webs.Url = siteUrl + @"/_vti_bin/Webs.asmx";
      _webs.UseDefaultCredentials = true;
              
 XmlNode _allWebs = _webs.GetAllSubWebCollection();
       string _webUrl = string.Empty;
       if (_allWebs != null && _allWebs.ChildNodes.Count > 0)
       {
         foreach (XmlNode _web in _allWebs.ChildNodes)
         {
           if (_web.Attributes["Title"] != null && _web.Attributes["Url"] != null)
           {
  Console.WriteLine(_web.Attributes["Title"].Value + " - " + _web.Attributes["Url"].Value);
           }
          }
       }
   }
   catch (Exception ex)
   {
       Console.WriteLine("Error : " + ex.Message);
   }
}

Monday, March 14, 2011

Unable to Play Flash in SharePoint 2010 Error

While working with SharePoint 2010, one issue came into picture was like I was not able to play flash animation files (.swf) in SP 2010 environment directly. This was not the case when we work with SharePoint 2007.
We can use swfobject.embed script to play flash directly in SharePoint 2007, but when same is done in SharePoint 2010 then flash does not get displayed at all.. Why??
After some search on google / bing I came to know that this is something related with security and so SharePoint blocks some files
So to solve this and put more focus on the settings what you are doing I would like to put this in summary
Very first thing you should check that you have referred the main jQuery file or not? (you can check, in your custom master page or page layout or custom control)
 Because after discussing with a designer I came to know that swf object works with jQuery main file dependency
Then second thing to be verified and important
Go to central administration > click on Manage Web Applications > select your web application and select General Settings from ribbon
In browser file handling section there are two radio buttons..
  1. Strict : when this option is selected then SharePoint prevents automatic the execution of files which content creators upload
When we try to see the HttpResponce of the web page which has flash on it with this option selected then we get something like this

  1. Permissive : when this option is selected then SharePoint allows automatic download and execution of files
And If we try to see HttpResponce of page having flash with these settings then we get like this

This is it.. This worked for me at least J
I hope this helps someone and you are able to see flash animation to your SharePoint 2010 site now

Why SharePoint Logs are empty (0KB size)?

SharePoint logs are quite important in many scenarios when we don’t find what’s wrong in Event Viewer


I was working with SharePoint 2010 environment and saw this, in 14 hive Logs, all logs were of size 0KB

So to solve this,

I checked that Diagnostic Logging was enabled and correct path for logs was set

Then as next step you should check this

For logging, SharePoint uses tracing service named as SharePoint 2010 Tracing (run services.msc)

Check which account this service is using

In my case, I changed service account to local system and logging worked

I hope this helps some one J

Error: Index was out of range. Must be non-negative and less than the size of the collection

I was facing this error while editing pages in SharePoint sites, and was not able to figure out what’s going wrong ?
But finally figured out the solution after 1 day search
There are few checks you need to do to solve this
  1. Check that page using correct page layout
  2. Check that associated content type with page layout is correct
  3. And most important : If there are some wrong / corrupted page layouts in the site’s master page gallery then delete them
Sometimes we can’t delete those page layouts using UI, (at least in my case I was not able to do so ) so I written a simple console application to delete them and that’s all
I hope this helps someone J

Change Locale of SharePoint Site Programatically

While working with SharePoint sites, we can change the regional settings of the site by using user interface and that’s easy to be done
You can do it like
Click on Site Actions > Site Settings > Click on Regional Settings link under Site Administration
and this is the small code using which you as a developer can do
I have used hardcoding here to Initialize CultureInfo object but you can do customizations according to your need

I hope this helps some one J


namespace ChangeCulture
{
  class Program
  {
    static void Main(string[] args)
    {
      using (SPSite site = new SPSite("http://yoursite"))
      {
        try
        {
          using (SPWeb web = site.RootWeb)
          {
            ChangeCulture(web);
          }
         }
        catch (Exception ex)
        {
         Console.WriteLine(string.Format("{0}:{1}", "Error: ", ex.Message));
        }
       }
      }

    private static void ChangeCulture(SPWeb web)
    {

      if (web != null)
      {
        web.AllowUnsafeUpdates = true;

        //Initialize CultureInfo
        CultureInfo ci = new CultureInfo("en-US");

        if (ci != null)
        {
          string.Format("{0}{1}", "Processing ", web.Name);
          web.Locale = ci;
          web.Update();
        }

         web.AllowUnsafeUpdates = false;
       }

       if (web != null)
       {
         foreach (SPWeb _web in web.Webs)
         {
           ChangeCulture(_web);
         }
       }


     }
    }
}