Tuesday, April 7, 2009

When to use AllowUnsafeUpdates, ValidateFormDigest() or else

For scenarios in which your code is processing a POST request, ValidateFormDigest() will, behind the scenes, set AllowUnsafeUpdates to true.

But some scenarios (e.g. web services) are not a POST request, therefore ValidateFormDigest() will fail.

So, here's a simple decision tree to help:

HttpContext.Current is null => Do nothing, no need to set AllowUnsafeUpdates to true nor to call ValidateFormDigest() because update will be carried out (e.g. code being called from an .exe from a cmd prompt)

HttpContext.Current is NOT null
- SPContext.Current is null => Need to set AllowUnsafeUpdates to true (e.g. web service)
- SPContext.Current is NOT null => Call ValidateFormDigest() (e.g. POST request processing)

Monday, April 6, 2009

SPSecurity.RunWithElevatedPrivileges() throws InvalidOperationException, "Operation is not valid due to the current state of the object."

There are several reasons for this to happen.

1) HttpContext.Current.User == null
2) code running under impersonation.

If it's 2), here's one recipe, save HttpContext, set it to null, restore it back:

            HttpContext prev = HttpContext.Current;
HttpContext.Current = null;
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
...
});
}
finally
{
HttpContext.Current = prev;
}

Friday, February 20, 2009

SQL Server: how to delete non-system databases from a cursor

DECLARE @name nvarchar(200)
DECLARE @stmt nvarchar(200)
DECLARE dbCursor CURSOR FOR SELECT D.name FROM sys.databases D where owner_sid <> 0x01
OPEN dbCursor
FETCH NEXT FROM dbCursor INTO @name
WHILE @@FETCH_STATUS = 0
BEGIN
--next IF is not needed, as cursor specifies that owner_sid <> 0x01 already
--IF @name <> 'master' and @name <> 'model' and @name <> 'msdb' and @name <> 'tempdb'
--BEGIN
PRINT 'Name = ' + @name
SET @stmt = 'DROP DATABASE "' + @name + '"'
PRINT 'stmt = ' + @stmt
EXECUTE sp_executesql @stmt
--END
FETCH NEXT FROM dbCursor INTO @name
END
CLOSE dbCursor
DEALLOCATE dbCursor



Notice couple of tips (at least for someone that doesn't write T-SQL every morning ☺):

- SQL syntax doesn't allow some statements to be run from inside a cursor, so you have to call sp_executesql store proc.
- since '-' is a reserved operator, you have to enclose the DB on quotes to successfully operate on a DB whose name contains '-' or other reserved operator.
- owner_sid <> 0x01 filters out system DB's (preferred over the commented IF)

Friday, January 30, 2009

SQL Server: how to get the sizes of the columns of a table

select C.name, C.max_length from sys.columns C
inner join
sys.tables T
on C.object_id = T.object_id and T.name = '<table name>'

SQL Server: how to see Log Transaction status

select name, log_reuse_wait, log_reuse_wait_desc from sys.databases

SQL Server: how to get the sizes of all tables

EXEC sp_MSforeachtable @command1="EXEC sp_spaceused '?'"