Wednesday, May 5, 2010

What you need to know about AllowUnsafeUpdates (Part 1)

In short here is how to deal with AllowUnsafeUpdates:
1) Don’t update SharePoint objects from your code behind on GET requests as if you do so your code will be exploitable via a cross-site scripting. If you understand the consequences of doing this and still want to do it then read below about how to use the AllowUnsafeUpdates property.
2) If your code is processing a POST request then make sure you call SPUtility.ValidateFormDigest() before you do anything else. This will ensure that the post request is validated (that it is not a cross-site scripting attack) and after that you will not have to worry about AllowUnsafeUpdates, because its default value will be “true” after the form digest is validated. To find out more about this read the second part of this article.

The Microsoft idea behind introducing the AllowUnsafeUpdates property is to protect YOU from cross-site scripting attacks. The way this works is that if your application is running in an HTTPContext (i.e. it’s a web part for instance) and the request is a GET request then SharePoint will refuse to do any changes unless the value of AllowUnsafeUpdates is set to true and by default it will be false for GET requests. If you try to do any updates to lists, webs or any SharePoint objects that require an SPSite to be created first, and if you don’t set AllowUnsafeUpdates to true you will get this exception:
System.Exception: Microsoft.SharePoint.SPException: The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again. —> System.Runtime.InteropServices.COMException (0x8102006D): The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again.
It is important to understand that if you are writing a class library for example, your code will behave differently when called from a web application and when called from a rich client. Actually if the HTTPContext.Current is null then AllowSafeUpdates will be always true. This is the case in rich clients where no cross-scripting is possible as there are simply no web requests.
Usually when you create your own SPSite or SPWeb objects, i.e. when you are not getting them from the SPContext (such as SPContext.Web), and when you try to update anything such as web or list properties, list items metadata etc, you may get the exception listed above. This is a clear indication that AllowUnsafeUpdates of the SPWeb is false and this is preventing you from doing the update. This problem is resolved easily by setting the AllowUnsafeUpdates of the parent web object to true. Still sometimes even after you have done this you may still be getting the same error.  This is typically caused by one of the the following reasons:
A) You have set the AllowUnsafeUpdate to true for the wrong SPWeb
You have to be careful because sometimes the ParentWeb of an object is not the same instance of the web you have retrieved the object from. For example when you go initialWeb.Lists[listId] you would expect that the returned list’s ParentWeb instance is the same as you initialWeb. However this is not the case. So if somewhere later in your code you go list.ParentWeb.UpdateSomething() this will not work because you have never set the AllowUnsafeUpdates property of list.ParentWeb. You have set it for your initialWeb but even that this is the same web as the list’s parent web both are different instances. Usually you see the error and then you go and investigate in Reflector whether this is the same instance or not. Alternatively you could use another more generic and clever way to deal with almost any similar situation described in the following post:
http://community.bamboosolutions.com/blogs/bambooteamblog/archive/2008/05/15/when-allowunsafeupdates-doesn-t-work.aspx
The author suggests that you can set the HttpContent.Current to null before you do your updates and then reassign its initial preserved value when done. This will work great but remember to set the HTTPContent to null as early as possible. In the post above probably SharePoint uses the site.RootWeb to do the updates to the site scoped features and the RootWeb’s AllowUnsafeUpdates hasn’t been set to true explicitly.
B) The AllowUnsafeUpdates gets reset to false sometimes after you have set it to true
If we have a look at how the property is managed it turns out that it is stored in the request object associated with every SPWeb (which is actually a COM object)
[SharePointPermission(SecurityAction.Demand, UnsafeSaveOnGet = true)]
private void SetAllowUnsafeUpdates(bool allowUnsafeUpdates)
{
     this.Request.SetIgnoreCanary(allowUnsafeUpdates);
}
This actually means that every time the request is reset, the property will be also reset to its default value. The m_Request member is modified when a new web is created, when the web is disposed or when the SPWeb.Invalidate() method is called.
internal void Invalidate()
{
   if (this.m_Request != null)
   {
      if (this.m_RequestOwnedByThisWeb)
      {
         SPRequestManager.Release(this.m_Request);
      }

      this.m_Request = null;
   }

   this.m_bInited = false;
   this.m_bPublicPropertiesInited = false;
   this.m_Url = null;
}
So any operation that calls SPWeb.Invalidate() will reset AllowUnsafeUpdate to its default value. And for code running under HTTPContext, i.e. web applications, this default value for a GET request will be false. I’ve looked up for you all legitimate cases for which Invalidate() is being called by the SharePoint object model. These cases are:
1) When the Name or the ServerRelativeUrl properties of the SPWeb are changed and then Update() is called. In this case the AllowUnsafeUpdate is reset because with the change of these properties the URL of the web will change and logically the request object will change as it will now point to a different URL.
2) When any object that implements ISecurable (those are SPWeb, SPList and SPListItem) breaks or reverts their role definition inheritance. This means every time you call SPRoleDefinitionCollection.BreakInheritance(), BreakRoleInheritance(), ResetRoleInheritance() or set the value of HasUniquePerm the AllowUnsafeUpdates property of the parent web will reset to its default value and you may need to set it back to true in order to do further updates to the same objects.
3) In many cases when an exception is caught by the SharePoint object model when you try to retrieve any sort of data the AllowUnsafeUpdates of the parent web will be reset to false as a precaution to protect against potential exploits. In those cases however the objects will be in unknown state anyway after the request has been reset and the exception is re-thrown so they are of no practical interest.
And finally it is also good to mention that you may get another related exception when trying to update your SharePoint objects and that is:
System.Exception: Microsoft.SharePoint.SPException: Cannot complete this action.Please try again. —> System.Runtime.InteropServices.COMException (0×80004005): Cannot complete this action.
This usually happens when some updates have been made to an object (usually SPSite, SPWeb or SPList) that may be clashing with your changes and SharePoint refuses to do the update. To recover from this situation you simply need to create fresh copies of the SPSite and the SPWeb objects and do the updates on the objects retrieved from the fresh copies. And of course don’t forget to set the AllowUnsafeUpdates to true for the freshly created SPWeb if required.

Tuesday, May 4, 2010

RunWithElevatedPrivileges - exception, not the norm

Let me start by saying that while executing code via RunWithElevatedPrivileges may help you overcome certain “access denied” exceptions in your code, using it should be the exception not the norm. The very reason I wrote the article, stems from how often I’ve seen this command used, and the security risks it presents.

SharePoint provides a very extensive and well thought out API, at least from a security standpoint ;). It uses impersonation, meaning that the code you write will execute under the context of the user viewing the page where your code resides. If you write a web part or application page that reads or writes information from a SharePoint List, Library, or Site that does not grant the user such rights; your web part or application page will throw an error… as it should. Your first instinct should not be to rewrite your code so that this logic executes via the RunWithElevatedPrivileges command.

That’s not to say using RunWithElevatedPrivileges is wrong every time, there are certain unique cases where you don’t have much of a choice. But first consider checking if the user has the necessary permissions via the DoesUserHavePermission method of either the SPSite, SPWeb, SPList, or even SPListItem your accessing with your code, and avoid doing anything further on that item if the method returns false for the required permission level. Alternatively (although often cause for debate) consider handling the access denied exception.

Ultimately, don’t hurry too much writing your code, the quickest way is not always the best way.

copyright from: http://msdn.microsoft.com/en-us/library/dd878359.aspx#SecuringAppPages_ValidatingUserPermissions

Wednesday, January 27, 2010

HttpRuntime.Cache vs. HttpContext.Current.Cache

Here's a development tip I came across on one of the ASP.NET discussion lists I'm on, at AspAdvice.com.

Original question:
Is there a difference in accessing the Cache of an application when calling HttpRuntime.Cache vs. HttpContext.Current.Cache?  I "think" I remember reading about a difference in the two a few years ago, but I don't remember the specifics.  This assumes that I am within a web application.

Answer from Rob Howard:
HttpRuntime.Cache is the recommended technique.

Calling the HttpContext does some additional look-ups as it has to resolve the current context relative to the running thread.

I use HttpContext.Current in a lot of the code I write too; but touching it as little as possible. Rather than calling HttpContext.Current repeatedly it's best to hang onto a reference and pass it around (when possible).

If you're in a component HttpRuntime.Cache is still the recommendation.

That said... the differences in performance are not going to be noticeable in 99% of the applications many of us write. The cases where it is going to matter is the 1% (or less) where you're trying to squeeze every last drop of performance out of you system. But this is a *minor* performance tweak, e.g. eliminating a database call, web service call or other out-of-process call in the application is definitely a better place to spend optimizing code.

For example, if you have 5 database calls in a particular code path reducing (or even optimizing) the queries is a much better use of time.

So yes, HttpRuntime.Cache is recommended but likely won't make a difference in most applications.

Another reply from James Shaw at CoverYourASP.NET:
I discovered another *great* reason to use HttpRuntime too, when writing my unit tests - HttpRuntime.Cache is always available, even in console apps like nunit!

http://www.coveryourasp.net/UnittestingandCaching

I never use HttpContext anymore, even in class libraries.

Tuesday, January 19, 2010

JavaScript Arrays: Pushing, Popping and Shifting

1) Merge of Join Two array:

it's quite easy

var a=new Array('a','b','c');
var b=new Array('d','e','f');
var c=a.concat(b);

c will be an array: ('a','b','c','d','e','f').



 2) : Pushing, Popping and Shifting
<script  id="clientEventHandlersJS"  language="javascript">
<!--
functionShow()
{
      var myArray = new Array();
      myArray[0] = "Jag";
      myArray[1] = "Chat";
      myArray[2] = "Win";
      myArray[3] = "Dhan";
      document.write("Before adding
-------------
");
      for (var i = 0; i < myArray.length; i++)
      {
            document.write(myArray[i] + "
");
      }
      myArray.push("aaa");
      document.write("
After adding
-------------
");
      for (var i = 0; i < myArray.length; i++)
      {
            document.write(myArray[i] + "
");
      }
}

function ButtonPush_onclick() {
      Show();
}



the result:
When the above code is executed we get the following output:
Before adding
-------------
Red
Green
Blue
White

After adding
-------------
Red
Green
Blue
White
aaa
3)

3) copying, transferring and merging

functionShow()
{
      var SimpleString = "abc;def;ghi;jkl;mno;qrs";
      var myArray = SimpleString.split(";");
      var subArray = myArray.slice(0,3);
      document.write("first array
---------
");
      for (var i = 0; i < myArray.length; i++)
      {
            document.write(myArray[i] + "
");
      }
      document.write("
second array
---------
");
      for (var i = 0; i < subArray.length; i++)
      {
            document.write(subArray[i] + "
");
      }
}

JavaScript arrays: copying, transferring and merging - How to copy the elements of one array into another using JavaScript: discussion

(Page 2 of 5 )

Within the code I showed you in the previous section, I mainly created a simple button (which is identified as “Button1”).  The button is defined with an “onclick” event which calls a JavaScript function, “Button1_onclick.”  The same function simply calls another JavaScript function named “Show.”

The function “Show” is defined as follows:

functionShow()

{

      var SimpleString = "abc;def;ghi;jkl;mno;qrs";

      var myArray = SimpleString.split(";");

      var subArray = myArray.slice(0,3);

      document.write("first array
---------
");

      for (var i = 0; i < myArray.length; i++)

      {

            document.write(myArray[i] + "
");

      }

      document.write("
second array
---------
");

      for (var i = 0; i < subArray.length; i++)

      {

            document.write(subArray[i] + "
");

      }

}

In the above code fragment, I worked with a sample string as follows:

      var SimpleString = "abc;def;ghi;jkl;mno;qrs";

From the above statement, we can easily determine that the “separator” for the elements would be “;” or semi-colon (as explained in my second article in this series).  Proceeding further we have the following:

      var myArray = SimpleString.split(";");

The above statement makes the string split into several elements, based on the separator “;” (semi-colon).  Once the splitting is completed, it creates an array of those elements and assigns the same to the variable “myArray.” Continuing on, we have the following:

      var subArray = myArray.slice(0,3);

The above statement creates a new array with only three elements (copied from  the 0th location or index) from the main array “myArray” and finally assigns the same to “subArray.”

We use the following loop to display all the elements (as explained in my first article):

      for (var i = 0; i < subArray.length; i++)

      {

            document.write(subArray[i] + "
");

      }

I also displayed the elements available in the first array using the following loop:

      for (var i = 0; i < myArray.length; i++)

      {

            document.write(myArray[i] + "
");

Monday, January 11, 2010

global.asax + sharepoint

The only thing you need to do with your global.asax is add the following:
<%@ Application Language="C#" Inherits="Microsoft.SharePoint.ApplicationRuntime.SPHttpApplication" %>
Then you paste your global.asax file under C:\Inetpub\wwwroot\wss\VirtualDirectories\port_number where port_number is usually port 80 on your first site collection.
Now you have your global.asax working.
Cheers!

Tuesday, December 29, 2009

Custom upload page in Layouts for document library and it's Navigation from upload menu in the Toolbar. Bend it !! Custom upload menu for the document library.

You just dont want to use the OOB upload.aspx in the "Layouts" to upload the documents in to the document library and you have created your custom upload.aspx (with all your requirements) based on the look and feel of OOB upload.aspx. Now your custom upload.aspx page is available in the "Layouts", But................................................. You started wondering that how to integrate the Navigation to the New custom upload.aspx page from the "Upload Menu" in the document library toolbar. You might have created the customupload.aspx and placed in the "Layouts" but clicking on the upload single or multiple document in the Upload menu will navigate you to "Upload.aspx" and not to the "Customupload.aspx"...
Thinking again............ Oh got it !!! Yes, I can add a new menu item through "customaction" feature and can navigate to the "CustomUpload.aspx" page to upload the documents. Think again ...... Yes, You can do it !! But what about the existing OOB menu item which navigates you to the OOB "upload.aspx" page. Still thinking ........ Hurray !!! Through "HideCustomAction" i will hide the existing OOB menu item in the upload menu which navigates to the OOB upload.aspx page.
Let me interrupt here !! As long the "CustomAction" feature is considered, you can add a new item under the "UploadMenu". But hiding the existing OOB menu item is not possible through the "HideCustomAction" feature. The "HideCustomAction" feature can hide the item which has been rendered through the CustomAction feature framework such as Site Action, Site Setting.... etc. Even you cannot hide the item from the "ECB" menu through HideCustomAction but can add a new menu item in the ECB menu through custom action. Because the ECB menu is rendered by the JavaScript from Core.js file. Likewise the "Upload menu" is rendered through a class library as a web control from the Microsoft.SharePoint.dll
So "HideCustomAction" feature can be used only to hide the item which are rendered through the custom action feature.
Following are some truth about the document library (as well "Lists") toolbar and the way to render the custom control in the toolbar :
1.    The toolbar of the document library consists of New Menu, Upload menu, Actions Menu and Settings Menu. These menus are rendered by the sharepoint dll and not by any JavaScript.

2.    To customize the Upload Menu, Create a class which inherits from the Microsoft.Sharepoint.WebControls.UploadMenu class and Override the “SetmenuItemProperties” method to navigate to the custom upload page. In this method it has been hard coded to navigate to the OOB upload.aspx.

3. The code snippet and the sample project has been attached in this post.

4.  Compile the class library and place the DLL in the GAC.

5.    The Rending Template for the document library is in the defaulttemplates.ascx control under 12/Template/Control template. The rendering template ID is “DocumentLibraryViewToolbar”. This template renders the New menu, Upload menu, Actions menu and Settings menu in the toolbar. The template looks like follows :


 


6.    Modifying the OOB files are not supported so copy the defaulttemplates.ascx and save it with a custom name under 12/Template/Control Template.

7.    Modify the “DocumentLibraryViewToolbar” in the custom ascx such that to render your custom upload menu from the class library you created. (Note : You need to add your assembly reference and register the tag prefix in the Custom ascx control. The sample customdefaulttemplates.ascx control is attached in this post)

8. The following are the snippet from the custom ascx control :

Along with the other existing tag prefixes need to add the tag prefix for your custom upload menu control dll

<% @Register TagPrefix="MyUpload" Assembly ="customupload, Version=1.0.0.0, Culture=neutral, PublicKeyToken=be322df48bc9f56c" Namespace="customupload" %>

 
 


9.    Next step is to render the custom rendering template to the document library so that the custom upload menu will be rendered in the toolbar. For this the "ToolbarTemplate" property of the View should be changed in the schema.xml file of teh document library definition. As modifying the OOB files are not supported, Copy the “DocumentLibrary” folder from 12/Template/Features and paste in the same place as “CustomDocumentLibrary”.

10.    Change the feature ID of the “CustomDocumentLibrary”

11.    Open the schema.xml file of custom document library and add the “ToolbarTemplate=CustomDocumentLibraryViewToolbar” attribute to the “View BaseID=1”. The sample custom document library definition with schema.xml changes is attached in this post.

12.    Install the feature and activate it.

13.    Create a document library using the custom document library definition and you can test that the custom upload menu has been added to the document library toolbar.

14. Now clicking on the upload document will navigate you to the custom upload.aspx page


                                                       HAPPY CUSTOMIZING

Wednesday, December 23, 2009

Closures and executing JavaScript on page load

 coppy right from: http://www.sitepoint.com/blogs/2004/05/26/closures-and-executing-javascript-on-page-load/
Over on my other blog I’ve just published a new technique for executing a piece of JavaScript once a page has finished loading. Here’s the code:

1function addLoadEvent(func) { 
2  var oldonload = window.onload; 
3  if (typeof window.onload != 'function') { 
4    window.onload = func; 
5  } else { 
6    window.onload = function() { 
7      oldonload(); 
8      func(); 
9    } 
10  } 
11
12 
13addLoadEvent(nameOfSomeFunctionToRunOnPageLoad); 
14addLoadEvent(function() { 
15  /* more code to run on page load */  
16}); 

view plain | print

function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      oldonload();
      func();
    }
  }
}

addLoadEvent(nameOfSomeFunctionToRunOnPageLoad);
addLoadEvent(function() {
  /* more code to run on page load */ 
});


A closure consists of a function along with the lexical environment (the set of available variables) in which it was defined. This is a remarkably powerful concept, and one commonly seen in functional programming languages such as JavaScript. Here’s a simple example of closures in action:

1function createAdder(x) { 
2  return function(y) { 
3    return y + x; 
4  } 
5
6 
7addThree = createAdder(3); 
8addFour = createAdder(4); 
9 
10document.write('10 + 3 is ' + addThree(10) + ''); 
11document.write('10 + 4 is ' + addFour(10)); 

view plain | print

function createAdder(x) {
  return function(y) {
    return y + x;
  }
}

addThree = createAdder(3);
addFour = createAdder(4);

document.write('10 + 3 is ' + addThree(10) + '
');
document.write('10 + 4 is ' + addFour(10));
createAdder(x) is a function that returns a function. In JavaScript, functions are first-class objects: they can be passed to other functions as arguments and returned from functions as well. In this case, the function returned is itself a function that takes an argument and adds something to it.

Here’s the magic: the function returned by createAdder() is a closure. It “remembers” the environment in which it was created. If you pass createAdder the integer 3, you get back a function that will add 3 to its argument. If you pass 4, you get back a function that adds 4. The addThree and addFour functions in the above example are created in this way.
Let’s take another look at the addLoadEvent function. It takes as its argument a callback function which you wish to be executed once the page has loaded. There follow two cases: in the first case, window.onload does not already have a function assigned to it, so the function simply assigns the callback to window.onload. The second case is where the closure comes in: window.onload has already had something assigned to it. This previously assigned function is first saved in a variable called oldonload. Then a brand new function is created which first executes oldonload, then executes the new callback function. This new function is assigned to window.onload. Thanks to the magical property of closures, it will “remember” what the initial onload function was. Further more, you can call the addLoadEvent function multiple times with different arguments and it will build up a chain of functions, making sure that everything will be executed when the page loads no matter how many callbacks you have added.
Closures are a very powerful language feature but can take some getting used to. This article on Wikipedia provides more in-depth coverage.