in

Dot Net Mafia

Group site for developer blogs dealing with (usually) .NET, SharePoint 2013, SharePoint 2010, Office 365, SharePoint Online, and other Microsoft products, as well as some discussion of general programming related concepts.

This Blog

Syndication

Archives

Corey Roth [MVP]

A SharePoint MVP bringing you the latest time saving tips for SharePoint 2013, Office 365 / SharePoint Online and Visual Studio 2013.

How to: Write a value into the property bag

I have ran into a few people that didn't even know what the property bag is on the SPWeb object, so I figured that would be a good topic for a post.  The property bag exposed by the Properties and AllProperties collections on the SPWeb object gives the developer a way to cache information on a site.  It can be compared to ASP.NET's cache object but the values are shared across the farm and will persist through server reboots.  Unfortunately, using the property bag isn't as simple as you would think.  In fact to get it working in all situations, it requires a number of settings to allow it to work.  It's probably enough to scare a lot of developers away from it.

Before we start, let me talk about the differences between Properties and AllProperties.  Properties is a collection of type SPPropertyBag.  It is sort of considered deprecated.  You can use it to add new items to the property bag, but it will only return a subset of everything in the property bag when retrieving data.  Why is that?  I have no idea.  So instead, Microsoft later implemented the AllProperties Hashtable which contains everything in the property bag.

Here is what the start of our code block looks like to write to the property bag.  This assumes it is inside a using block to get access to an SPWeb.

// unsafe updates are required to be able to write to the property bag

currentWeb.AllowUnsafeUpdates = true;

 

// you must check to see if the collection has a value in the assigned key already

if (!currentWeb.AllProperties.ContainsKey(key))

    currentWeb.Properties.Add(key, myValue);

else

    currentWeb.AllProperties[key] = myValue;

 

// update the properties

currentWeb.Properties.Update();

currentWeb.AllowUnsafeUpdates = false;

There are a number of things to note here.  First, it requires AllowUnsafeUpdates to be set to true.  Secondly notice that the AllProperties object actually has a method to check to see if a key exists.  This is probably the only collection in SharePoint that lets you check to see if something exists without throwing an exception.  This is of course because, the type is Hashtable and not a custom SharePoint collection.  If the key does not already exists, you add it to the Properties object (not AllProperties).  If a value already exists, you store the value using an indexer with the AllProperties object.  You might be able to get this to work other ways, but after lots of attempts, this is what works for me.  After the value is stored, you have to call Update on the Properties object if you want it to actually store the values.  If you have multiple values to store, you only need to call this once.  Lastly, be sure to remember and turn off AllowUnsafeUpdates.

The above code works great...as long as the account running it is an administrator.  If you need this code to work when executed by a regular user, there is an additional step.  You have to use SPSecurity.RunWithElevatedPrivileges.  I am assuming you are already familiar with how this method works.

SPSecurity.RunWithElevatedPrivileges(delegate()

{

    using (SPSite currentSiteCollection = new SPSite("http://myserver/mysite"))

    {

        using (SPWeb currentWeb = currentSiteCollection.OpenWeb())

        {

            // unsafe updates are required to be able to write to the property bag

            currentWeb.AllowUnsafeUpdates = true;

 

            // you must check to see if the collection has a value in the assigned key already

            if (!currentWeb.AllProperties.ContainsKey(key))

                currentWeb.Properties.Add(key, value.Value.ToString());

            else

                currentWeb.AllProperties[key] = value;

 

            // update the properties

            currentWeb.Properties.Update();

            currentWeb.AllowUnsafeUpdates = false;

        }

    }

});

There is a complete example.  One thing to remember is that the method inside RunWithElevatedPrivileges requires that you create a new SPSite object for it to work.  Do not pass it a reference from one that already exists.  Create a new one by passing it a URL.  Since we need the SPWeb object in this case, I have things nested like I have mentioned in my post in the past.

Luckily, reading from the property bag is not as difficult.  Just check to see if the key exists and read from it using AllProperties.

if (currentSite.AllProperties.ContainsKey("MyItem"))

    myItem = currentSite.AllProperties["MyItem"].ToString();

This may seem like a lot to store and retrieve values in the property bag, but it's pretty easy to wraps this code up into a class.

Comments

 

Links (5/13/2008) « Steve Pietrek - Everything SharePoint said:

Pingback from  Links (5/13/2008) « Steve Pietrek - Everything SharePoint

May 13, 2008 8:20 PM
 

Todd Bleeker said:

Do you have any updated insight into using AllProperties within the context of a SharePoint 2010 Sandboxed Solution?

<Todd />

January 21, 2011 7:01 AM
 

Jennifer said:

@ Todd, simply use the AddProperty method.

E.g., SPContext.Current.Site.RootWeb.AddProperty("ABC_test", "ABC test");

Best, jennifer

April 5, 2011 1:30 AM
 

Steve said:

Using SP2010, I found that I had to include a call to SPWeb.Update() after setting the value with SPWeb.AllProperties[currentPropName] = currentPropValue; to commit the change to the dbase.

July 12, 2011 12:09 PM
 

Mikael said:

Thanks Steve,

SPWeb.Update() was indeed required when updating the property value. Note that calling Properties.Update() before SPWeb.UpdatE() does not work. I got it working like this:

using (var site = new SPSite(url))

               {

                   SPWeb rootWeb = site.RootWeb;

                   rootWeb.AllowUnsafeUpdates = true;

                   var keyExists = rootWeb.AllProperties.ContainsKey(key);

                   if (!keyExists)

                   {

                       WriteEventLog("WriteWebConfig key does not exist in PropertyBag. Adding it. " + key + " " + value, EventSeverity.Information);

                       rootWeb.Properties.Add(key, value);

                       rootWeb.Properties.Update();

                   }

                   else

                   {

                       WriteEventLog("WriteWebConfig keyPair already exists. Updating it.. " + Environment.NewLine +

                           "Previous keyPair: " + key + ", " + rootWeb.AllProperties[key] + Environment.NewLine +

                           "New keyPair: " + key + ", " + value, EventSeverity.Information);

                       rootWeb.AllProperties[key] = value;

                       rootWeb.Update();

                   }                  

                   rootWeb.AllowUnsafeUpdates = false;

                   result = "Success: KeyPair successfully written to PropertyBag. Key: " + key + ", Value: " + rootWeb.AllProperties[key];

               }

October 24, 2011 5:48 AM
 

Suresh Pydi said:

Nice post. Here is one more post explaining to get and set property bag values in SharePoint 2013 apps using CSOM

sureshpydi.blogspot.in/.../set-and-get-property-bag-values-in.html

May 28, 2013 11:44 PM

Leave a Comment

(required)  
(optional)
(required)  
Add

About CoreyRoth

Corey Roth is an independent SharePoint consultant specializing in ECM, Apps, and Search.
2012 dotnetmafia.
Powered by Community Server (Non-Commercial Edition), by Telligent Systems