Showing posts with label custom. Show all posts
Showing posts with label custom. Show all posts

Tuesday, May 11, 2010

Fixing Session error with custom SharePoint master pages

Recently one of my colleague asked me to look in to a weird problem he is facing with regards to SharePoint master page. in this SharePoint site he has a Pages library that publishes plain aspx pages that implements some of his Session related functionality in code behind. all went well until he changed the master page to a custom master page which was uploaded in to the master page gallery. suddenly we were getting the following error in the aspx page.
the funniest(or the weirdest) thing is that if the master page is changed back to any out of the box master page, the site works fine. after some investigation I realized that if the site master page is changed to a customized master page (or even to a custom master page that has been uploaded in to master page gallery through SharePoint UI) the aspx page breaks with the error. 
"Session state can only be used when enableSessionState is set to true, either in a configuration file or in the Page directive. Please also make sure that System.Web.SessionStateModule or a custom session state module is included in the <configuration>\<system.web>\<httpModules> section in the application configuration."
Straight forward, Right? so, checked the web.config over and over again, but the setting is set to enable the session state. after some Googling I realized that every body is suggesting that the web.config should be corrected. but, it is corrected. so, what's next?
So, what is the difference between OOB master pages and the custom master pages that are uploaded through SharePoint UI or customized through SharePoint Designer? the simple difference is the way how they ended up in the gallery. OOB master pages are uploaded via feature activation and sit in the WFE's file system where as other reside in the site content data base. so, I decided to create a file upload feature. please check Heather Solomon's article on how to create a master page feature.
By activating the new master page feature, I got the new master page available in the master page gallery. then I set the new master page of the site. walla, it worked!!! No more Session errors in the custom aspx page.
Even though I got the problem solved for my colleague, I still don't understand what caused the problem. so, if anybody knows the cause of the problem I would appreciate comments on this thread.

Tuesday, June 23, 2009

Custom ‘stsadm’ command to change Top Navigation Tab URL

It has been a while since my last post and today I am going to show you how to code a custom ‘stsadm’ command to change the url of a given top navigation tab. the reason I had to write this command was that, my client is using backup/restore to promote the site collection to different environments. when this happens all the non-relative urls are carried over to new environment that are not relevant to the new environment. so, one option is to change the urls in the UI. but, unfortunately the site collection has more than 500 sub-sites under it and changing them manually is nearly impossible.

Now, let’s do some coding.

There will be 3 required parameters in the command.

Url of the targeted site, title of the top navigation tab that url needs to be changed and the last one is the new Url for the tab. and also we need to have few utility methods that iterates through the site collection/site and returns the list of SPWeb objects.

Now, I will define the usage string for the command as follows.
private string usageString = "[-siteurl < site url>] - site collection url or site url\n" +
"\t[-targettitle <url>] - title of the navigation item that needs to be replaced with new url\n" +
"\t[-newurl <url>] - new url \n";
As you already know when you write a custom stsadm command you have to implement ISPStsadmCommand with GetHelpMessage and Run methods.

public string GetHelpMessage(string command)
{
return usageString;
}

public int Run(string command, StringDictionary keyValues, out string output)
{
int rtnCode = 0;
string cmd = command.ToLowerInvariant();

switch (cmd)
{
case "spupdatenavigation":
rtnCode = this.Traverse(keyValues);
break;

default:
throw new InvalidOperationException();
}
output = "";
return rtnCode;
}
now, let’s get to the code where magic happens.

my strategy here is to navigate trough all the sites that were returned by previous methods and get the Global navigation Node Collection for each site. and , then for each node, recursively navigate to the targeted node, change and update the url.

Once, you have sign the project and compile the code, one more step is required to register the command in the system. to register the command in the system I create the a xml file ‘stsadmcommands.xxx.xml’ in 12\CONFIG and the file name should be in the format of ‘stsadmcommands.<custom name>.xml’. the file contains the following;

<?xml version="1.0" encoding="utf-8" ?>
<commands>
<command name="spupdatenavigation" class="XXX.Utils.Commands.SPUpdateNavigationCommand, XXX.Utils.Commands, Version=1.0.0.0, Culture=neutral, PublicKeyToken='public key token'"/>
</commands>
After copying the dll file to GAC recycle the AppPool and you are all set to go.
This is how you will use the command at the command line;

stsadm -o spupdatenavigation -siteurl http://server01:9090 -newurl http://server05:8888/recordscenter -targettitle "Records Center"

optionally, if you want to debug the code , you can provide additional key ‘-debug’ at the command.

The whole project can be found in this link.

Tuesday, December 9, 2008

How to Create Generic Media Player Web Part

In this post I would show you how to create a web part that is intelligent enough to load and play a media file with a proper media player. when my client wanted to have a web part that plays windows media I came up with the idea of embedding the media player ActiveX object using HTML <OBJECT> tag. Then it occurred to me that if I can do it for Windows media player, why can not I do it for Flash player, Real player or any media player for that matter.

Enough on background and let's start coding.

For the sake of simplicity, I will use 3 attributes that are common to almost all the players. those are width, height and visibility of the controls of the player. one good thing about this web part is that it is capable of extracting media URL from a URL query parameter as well as from user entered web part property. for this I define another property called 'mediaURL'.

I define 4 web part properties for the above attributes as follows;

        private int height = 300;
        private int width = 400;
        private bool showControls = true;
        private String mediaURL;

then, define 4 web part properties;

        [Description("Media Player Settings"),WebPartStorageAttribute(Storage.Shared),
        Category("Media Player Settings"),Browsable(true),FriendlyName("Height")]
        public int PlayerHeight
        {
            get { return height; }
            set { height = value; }
        }
 
        [Description("Media Player Settings"),WebPartStorageAttribute(Storage.Shared),
        Category("Media Player Settings"),Browsable(true),FriendlyName("Width")]
        public int PlayerWidth
        {
            get { return width; }
            set { width = value; }
        }
 
        [Description("Media Player Settings"),WebPartStorageAttribute(Storage.Shared),
        Category("Media Player Settings"),Browsable(true),FriendlyName("URL")]
        public string MediaURL
        {
            get { return mediaURL; }
            set { mediaURL = value; }
        }
 
        [Description("Media Player Settings"),WebPartStorageAttribute(Storage.Shared),
        Category("Media Player Settings"),Browsable(true),FriendlyName("Show Controls")]
        public bool ShowControls
        {
            get { return showControls; }
            set { showControls = value; }
        }

Now that we have all the web part properties defined, we can go ahead and implement the web part.
The very first thing I am going to do is override CreateChildControls method and add a global Label that renders HTML.

    protected override void CreateChildControls()
    {
        try
        {
            base.CreateChildControls();
            displayLabel = new Label();
            if (Page.Request.QueryString["mediaurl"] == null || 
                Page.Request.QueryString["mediaurl"].ToString().Equals(""))
            {
                displayLabel.Text = "set media url...";
            }
            else
                MediaURL = Page.Request.QueryString["mediaurl"].ToString();
            Controls.Add(this.displayLabel);
        }
        catch (Exception ex)
        {
            HandleException(ex);
        }
    }

In order to render HTML we have to override void Render(HtmlTextWriter writer) in the web part. this is where all the magic happens.

protected override void Render(HtmlTextWriter writer)
    {
        this.EnsureChildControls();
        try
        {
            if (!String.IsNullOrEmpty(MediaURL))
            {
                String ext = MediaURL.Substring(MediaURL.LastIndexOf('.') + 1);
                MediaPlayerFactory factory = MediaPlayerFactory.GetInstance();
                MediaPlayer player = factory.GetMediaPlayer(ext);
                player.Height = PlayerHeight;
                player.Width = PlayerWidth;
                player.MediaURL = MediaURL;
                player.ShowControls = ShowControls;
                writer.Write(player.GetHTML()); 
                this.displayLabel.RenderControl(writer);
            }else
            {
                //Render Error message in the label
                HandleException(new Exception("set media url...."), writer);
            }
        }
        catch (Exception e)
        {
            //handle Error eroperly
            HandleException(e,writer);
        }   
    }


Now, I'll explain the above code line by line.


    String ext = MediaURL.Substring(MediaURL.LastIndexOf('.') + 1);
    MediaPlayerFactory factory = MediaPlayerFactory.GetInstance();
    MediaPlayer player = factory.GetMediaPlayer(ext);

First, the file extension is extracted. then MediaPlayerFactory Singleton Object is instantiated. this factory will expose GetMediaPlayer method that returns a MediaPlayer object based on the file extension.

    player.Height = PlayerHeight;
    player.Width = PlayerWidth;
    player.MediaURL = MediaURL;
    player.ShowControls = ShowControls;

Player properties are set based on the web part properties.

    writer.Write(player.GetHTML());
    this.displayLabel.RenderControl(writer);

Render the HTML in the Label.

Up to this point it is very straight forward and all related to web parts. All other areas of code is pure OOP. I hope you will understand the code.

Please note that I have tested the HTML
<OBJECT> tag for Windows media player and not for the others. if you find any problems with other media players I am more than happy to assist.

Find the full code for this article at http://sites.google.com/site/bhakthil/Home/MediaWebPart.zip