On this page

Obtaining the connection string for a site in sps - Complete Guide
i'm an HTML
Memory leaks using SPS object model.
post disappeared suddenly
writing secure .Net code for web applications - Prologue
Coding with Threads in .Net - Lesson 1
Blog version updated to 1.9
back to action
IIS 6 - run with an application user
Gallery section opened

Ads

Navigation

Search

Categories

Clouds

Sql Server (5) .Net (16) .Net 2.0 (2) C# (3) @ff Topic (5) Architectural solutions (9) ASP (1) BDD (5) Blog related (8) database (2) Development process (8) Facebook (1) job interviews (1) Lessons (5) Life (12) Microsoft (5) IIS 6 (2) SPS (sharepoint server) (3) Drivers (1) Internet Explorer (2) Windows 2003 server (1) NightDuck (2) Performance (5) Security (9) Sql Server 2000 (4) Study (2) TDD (1) Threading (3) Under the hood (1) Web (1) Web services (1) XSS (6)

Archive

Blogroll

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

RSS 2.0 | Atom 1.0 | CDF

Send mail to the author(s) E-mail

Total Posts: 63
This Year: 0
This Month: 0
This Week: 0
Comments: 33

Sign In
Pick a theme:

 Wednesday, October 11, 2006
Wednesday, October 11, 2006 5:45:58 PM (GMT Standard Time, UTC+00:00) ( Sql Server  | .Net | Lessons | SPS (sharepoint server) | Performance )

As you know, Microsoft didn't intended that you access the SPS database, but via object model only.
the problem that it has many bugs, performance issues, security issues and lots lots problems that will make the programmer's life a living hell.

So, lets see how can we break the 1st guideline of SPS programming - "do not use the SPS database directly".
man , I'm feeling like a criminal now, presenting a guide how to do something that Microsoft invested a lot of effort to prevent us from doing.

Lets get down to business,
don't count that the connection string is laying in some property, this one we need to do some dirty work.

A little background how we are going to do it:

The connection string looks like this :

"Integrated Security=SSPI;Server=someServer;database=SomeDatabase"

as you can see, the only thing that can change here is the server name and the database name.

lets create a core function that will receive DB collection and the desired site guid and construct the connection string.

private string GetConnectionStringForSite(SPContentDatabaseCollection DBs, Guid siteGuid)
{
    string rc = "";
    SPContentDatabase oDB = null;

    for(int i=0; i<DBs.Count;i++)
    {
        // Get the database
        oDB = DBs[i];

        SqlCommand c = new SqlCommand();
        string strConn = "Integrated Security=SSPI;Server=" + oDB.Server + ";database=" + oDB.Name;

        using(SqlConnection conn = new SqlConnection(strConn))
        {
            // Set the Connection
            c.Connection = conn;
            try
            {
                // Open the connection
                conn.Open();

                c.CommandText = "SELECT FullUrl FROM Sites where Id=@Id";

                // Set the parameter
                c.Parameters.Add(new SqlParameter("@Id",System.Data.SqlDbType.UniqueIdentifier));
                c.Parameters["@Id"].Value = siteGuid;

                // Execute reader
                SqlDataReader reader = c.ExecuteReader(System.Data.CommandBehavior.SingleRow);

                // check if we have rows
                bool hasRows = reader.HasRows;

                // Close the connection and the reader
                reader.Close();
                conn.Close();

                // Check if it got rows
                if(hasRows)
                {
                    // Set the return value
                    rs = strConn;

                    // Stop iterating through the DB's
                    break;
                }

                // Close the reader
                reader.Close();
            }
            finally
            {
                // Close the connection
                if(conn.State != System.Data.ConnectionState.Closed) conn.Close();
                oDB = null;
            }
        }
    }
    return rc;
}

 

this function will be placed in a dedicated class, i call is "SPSDB"

lets create the class itself and its private members

    public class SPSDB
    {
        private string _conString = "";
        private string _vsUrl = "";

        public String URL
        {
            get{return _vsURL;}
        }
    }

now we need to write the constructor and the connection "factory"

the constructor will look like this :

public SPSDB(string siteUrl)
{
    using(Microsoft.SharePoint.Administration.SPGlobalAdmin ga = new Microsoft.SharePoint.Administration.SPGlobalAdmin())
    {
        Microsoft.SharePoint.Administration.SPVirtualServerCollection VSc = ga.VirtualServers;

        SPVirtualServer vs = null;
        Guid g;
        bool isFound = false;
        
        // Run through all the VS collection
        for(int i=0; i<VSc.Count;i++)
        {
            // Get the virtual server reference
            vs = VSc[i];

            // if the current vs is not from the needed state than continue to the next VS
            if(vs.state != SPVirtualServerState.Ready)
                continue;

            // Run through all the sites in the vs
            for(int j=0; j< vs.Sites.Count;j++)
            {
                using(SPSite s = vs.Sites[j])
                {
                    // Check if we found the needed vs
                    if(s.Url.ToLower() == siteUrl.ToLower())
                    {
                        // Save the needed data
                        isFound = true;
                        g = s.ID;
                        _vsURL = vs.Url.ToString();
                        _conString = GetConnectionStringForSite(vs.ContentDatabases,g);
                        break;
                    }
                }
            }

            // Check if the vs has been found
            if(curVs != null)
                break;

            // Clear the virtual server object
            vs = null;

            // Clear memory
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }

        // Throw an exception if the site guid is not there
        if(!isFound)
            throw new Exception("the given site url cannot be found");
        
    }
}

and the factory method will look like this :

public SqlConnection GetCon()
{
    return new SqlConnection(_conString);
}

thats it!
now to use it you can do it like this :

SPSDB dbstuff = new SPSDB("http://www.krokhmal.com");

using(SqlConnection con = dbstuff.GetCon())
{
    // Your DB code here ...
}

I've added a file attachment to this post with the mentioned class.
enjoy.

SPSDB.rar (1.34 KB)
Comments [0] | | # 
 Thursday, October 05, 2006
Thursday, October 05, 2006 10:45:22 PM (GMT Standard Time, UTC+00:00) ( @ff Topic )

found some quiz, giving you your extention :)

You are .html You are versatile and improving, but you do have your limits.  When you work with amateurs it can get quite ugly.

give it a try yourself here

Comments [0] | | # 
Thursday, October 05, 2006 5:53:17 PM (GMT Standard Time, UTC+00:00) ( .Net | SPS (sharepoint server) | Performance )

Recently i have given a task to build a tool for managing file versions in share point.
for some architectural decisions and performance issues, I've decided to do the aggregations directly through the share-point database (yes, even if is against Microsoft's guidelines).

Considering the fact that Microsoft invested a lot of afford so you wont find where each SPsite is located (on which DB) , one of the things i had to do is to iterate through all the sites in SPsitecollections in every SPVirtualServer in the SPVirtualServerCollection.
Sounds like a lot of "fun".

Well, actually there was problem.
I'll show some bad practices to iterate through that and explain each one

Option 1 :

SPGlobalAdmin globalAdmin = new SPGlobalAdmin();
SPVirtualServerCollection vServers = globalAdmin.VirtualServers;


// Run through the virtual servers
foreach (SPVirtualServer vs in vServers)

   // Run through the sites
   foreach (SPSite site in vs.Sites) 
   { 
      if(site.Url == predefinedUrl)
      {
         // Do some logic ...
      }
   }
}


Option 2 :

SPGlobalAdmin globalAdmin = new SPGlobalAdmin();
SPVirtualServerCollection vServers = globalAdmin.VirtualServers;


// Run through the virtual servers
for(int i=0; i<vServers.Count; i++)

   // Run through the sites
   for(int j=0; j<vServers[i].Sites.Count; j++) 
   { 
      if(vServers[i].Sites[j].Url == predefinedUrl)
      {
         // Do some logic ...
      }
   }
}

Option 3 :

SPGlobalAdmin globalAdmin = new SPGlobalAdmin();
SPVirtualServerCollection vServers = globalAdmin.VirtualServers;


// Run through the virtual servers
for(int i=0; i<vServers.Count; i++)

   SPVirtualServer vs = vServers[i];
   
   // Run through the sites
   for(int j=0; vs.Sites.Count; j++) 
   { 
      SPSite s = vs.Sites[j];
      if(s.Url == predefinedUrl)
      {
         // Do some logic ...
      }
   }
}


So, what's wrong with this practices ?
the problem lays in the way the object model is implemented : Unmanaged code - which means that you must to release memory explicitly.
garbage collector will not handle these object, and you must handle it in your code.

problems in option 1 :

  • implementing this practice (please don't), will cause memory leaks, due to a fact that dispose() method is not being used, and memory is not being released.
  • Exception management - suppose you will call the dispose method of the SPSite object and the end of the foreach loop,
    what will happen if an exception occur ?
    the memory allocated to the object will not be released, and the garbage collector won't release it either, causing memory leaks each time exception takes place.
  • Even if you decide to include some exception management code (try-catch for example), the given object won't be reachable because it lives in it's own scope (the foreach scope).

Problems in option 2 :

  • implementing this practice (just like the 1st option), will cause memory leaks, due to a fact that dispose() method is not being used, and memory is not being released.
  • reading the previews statement probably raise some reasonable question :
    "hey, I'm not creating any new objects, and does not allocating any memory, just accessing some property in a given collection, what is the problem here ?"
    this is a question i asked myself too, so i dug deep through it, and found that the sites in the Sites collection that lays in a virtual server object is not being created until you reference them explicitly - which means : accessing their properties or getting an outer reference to some site through a variable.
    so when accessing a property will cause memory allocation behind the scenes.
  • calling the dispose method like so :

    Sites[i].Dispose();

         will not release the memory.
         maybe its related to the fact that the Sites[i] object is defined as "read-only" .
         if you find the reason for that please let me know.

Problems in option 3 :

  • OK, i must admit, this looks much better than the ones mentioned above, but still lack of some memory releasing.

How can we write it right ?
here is an example of what i consider as a good practice :

Option 4:

// Wrap the globalAdmin object in a using scope - this object is unmanaged
using(SPGlobalAdmin globalAdmin = new SPGlobalAdmin())
{
    // Get the virtual servers collection reference
    SPVirtualServerCollection vServers = globalAdmin.VirtualServers; 

    // Run through the virtual servers
    for(int i=0; i<vServers.Count; i++)
    {
        SPVirtualServer vs = vServers[i];
    
        // Run through the sites
        for(int j=0; vs.Sites.Count; j++)
        {
            // Wrap the SPSite object in a using scope - this object is unmanaged
            using(SPSite s = vs.Sites[j])
            {
                if(s.Url == predefinedUrl)
                {
                    // Do some logic ...
                }
            }
        }

        // Make sure that this objects memory will be cleared by the GC
        vs = null;

        // Call the garbage collector and make sure that the memory is released
        GC.Collect();
        GC.WaitForPendingFinalizers();
    
    }
}


as you can see, unmanaged object is wrapped in a using scope,
and the GC(garbage collector) is being activated manually.

changing from one of the bad practices to this one improved dramatically performance.
for example :
iterating with option number 2 caused the w3wp.exe process (that is the IIS process) to reach 1200 MB and crash (reaching the given limit) after iterating through 2700 sites,
while implementing option 4, i didn't saw any dramatic changes in the process info, and it stayed at 87 MB only and iterated through all the sites, a total of 8876 sites.

Comments [0] | | # 
 Wednesday, September 27, 2006
Wednesday, September 27, 2006 7:15:20 PM (GMT Standard Time, UTC+00:00) ( Blog related )
a very strange thing happened just now.
as soon as i posted my last post(minutes ago) all post disappeared.
a very strange phenomena.

update :
after restarting the application, all posts came back to "life".
probably some bug at dasBlog system

Comments [0] | | # 
Wednesday, September 27, 2006 5:41:45 PM (GMT Standard Time, UTC+00:00) ( .Net | Security | XSS )

Today I stepped into my parallel team office just when shani raba (AKA - "human debugger") explained to a new programmer the usage of validators in ASP.NET form.
We started an argument about the affectivity of the .Net built-in validators, and what should you do besides that on the server side, to guarantee no security breaches through that tiny input that protected by the "mighty" .Net Validator.

We came to several interesting conclusions and understanding about aspect of the subject that we didn't knew.
So, I decided to write a post about that,
I came home, and started to write some example on the subject.
The problem is that as soon as I started to cover one aspect of the subject, other aspects came across that I couldn't neglect.
So I decided to create several posts during this week and the next, which will cover most of the "secure .Net code for web applications" subject.

The posts will refer to:

  • Cross-site scripting (XSS)
  • Session hijacking
  • Hidden field tampering
  • SQL injection
  • Cookies and Authentication
  • some other aspects that I'll encounter on the way
  • Your requests...
  •  

So stay tuned for the next weeks for more about the subject.

 

 

Comments [1] | | # 
 Monday, September 25, 2006
Monday, September 25, 2006 5:28:14 PM (GMT Standard Time, UTC+00:00) ( .Net | Lessons | Performance | Threading )

the main reason that I've started to play with threads is because the industry WILL (sooner or later) move to a multi-core guided programing, and it WILL become mainstream (mark my words :) ).

any way, lets start from the beginning, and why do we need threads.
according to the definition : "Threads are a way for a program to split itself into two or more simultaneously (or pseudo-simultaneously) running tasks. Threads and processes differ from one operating system to another, but in general, the way that a thread is created and shares its resources is different from the way a process does."

so, in other words, we will use threads when we need to perform simultaneous tasks.
these kind of actions made when you have unused processing time while waiting for other task to finish.

so, back to the .Net world, how would we do that ?

to use threads, we need to include the library :

using System.Threading;

the next thing we need i to know how to to lunch a thread with a task.

  • we need to create a task to be done.
  • a ThredStart delegate which will point to our task.
  • a new thread ( or an old one from a thread pool ) - which is better and when will be explained in some later posts.
  • start the thread.

so :

lets create some task :

        private void BurnCPUwithOneThread()
        {
            for(int i=0; i< 5000000;i++)
            {
                lblcounter.Text = i.ToString();
            }
        }

 

and one more :

        private void BurnCPUwithTwoThreads()
        {
            for(int i=0; i< 5000000;i++)
            {
                lblCounter2.Text = i.ToString();
            }
        }

now we will create the delegate and the threads, and activate them.

        private void button4_Click(object sender, System.EventArgs e)
        {
            //We will run the action in a different thread from the gui
            //so when we do sleep the the tread the gui will not hang up.

            // Create the thread start object
            ThreadStart ts = new ThreadStart(BurnCPUwithOneThread);
            
            // The tread itself
            Thread t = new Thread(ts);
            
            // Starting the thread
            t.Start();

            // Create the thread start object
            ThreadStart ts2 = new ThreadStart(BurnCPUwithTwoThreads);
            
            // The tread itself
            Thread t2 = new Thread(ts2);
            
            // Starting the thread
            t2.Start();

        }

 

  thats it.
   now you have a working little program with 2 threads.
   if you will run this code , you will notice that it is done simultaneously.


   next lessons will handle : sending parameters to threads, synchronizing, thread pool, and more.
   please comment, if you would like me to focus on some specific subject...

Comments [0] | | # 
Monday, September 25, 2006 4:06:33 PM (GMT Standard Time, UTC+00:00) ( Blog related )

as a part of the site development,
the dasBlog system upgraded to th 1.9 version.

Comments [0] | | # 
 Saturday, September 23, 2006
Saturday, September 23, 2006 6:26:05 PM (GMT Standard Time, UTC+00:00) ( Life )
after almost a month with no posting, due some heavy work at home (house remodeling)
I'm back to action.

so stay tuned for some new exiting posts on various subjects.

Comments [0] | | # 
 Tuesday, August 29, 2006
Tuesday, August 29, 2006 10:55:46 PM (GMT Standard Time, UTC+00:00) ( Microsoft | IIS 6 | Security )

One of the most important rules about running an application (specially web application) is giving to the application only the needed permissions to run, and no more ! (running a web application with an administrator user is bad....).
Sure, it's very comfortable to give the application all the permissions that the system has, and not trying to solve permission related problems directly,
But this kind of an approach is a security-breach prone approach.
suppose, you wrote an application that has a minor security hole in it, and it allows the user to execute some unwanted script.
If it will run in a full permissions context, than it would be very easy to hijack the entire system, or even just do a system-wide damage.
But, if it will run only with the needed permission, then the attacker would have a hard time doing it.

So, what is the solution ?

Comments [2] | | # 
 Monday, August 28, 2006
Monday, August 28, 2006 10:05:57 PM (GMT Standard Time, UTC+00:00) ( Blog related )

i've added some gallery to my site ring.
check it out : http://gallery.krokhmal.com


changed on 23.09.06

Comments [0] | | #