cloud.net

Friday, August 31, 2007

Recursive batch delete command

We all know the scenario: we have a list with a large number of junk testing records we need to get rid of.
We could write a console app with the following:
SPListItemCollection listItems = list.Items;
for (int id = 8; id <= listItems.Count; id++)
{
 try {
  listItems[id].Delete();
  Console.WriteLine("Deleting " + id.ToString());
 }
 catch(Exception ex){ }
} 
list.Update();

Now sit back and watch the numbers tick by... or you could what is widely considered the fastest way in SharePoint (WSS) to perform the operation, to use 'ProcessBatchData' as it avoids the Object Model and is considerably faster.
Here is some example code which will remove items from a SharePoint list.
StringBuilder oSBDelBat = new StringBuilder();
oSBDelBat.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><batch>");
foreach (SPListItem item in CurrentList.Items)
{
 oSBDelBat.Append("<method>");
 oSBDelBat.Append("<setlist scope="\">" + CurrentList.ID + "</setlist>");
 oSBDelBat.Append("<setvar name="\">" + Convert.ToString(item.ID) + "</setvar>");
 oSBDelBat.Append("<setvar name="\">Delete</setvar>");
 oSBDelBat.Append("</method>");
}
oSBDelBat.Append("</batch>");
try
{
 SPContext.Current.Site.RootWeb.ProcessBatchData(oSBDelBat.ToString());
}
catch (Exception ex)
{
 Console.WriteLine("Delete failed: " + ex.Message);
 throw;
}

Tuesday, August 28, 2007

Deploying a dll to the GAC and recycling the application pool

When developing a sharepoint dll in Visual Studio 2005 the quickest way to deploy and test your dll is to automate it with a post build event.

How do we do this?
1.- Open the properties window for your project... solution explorer> right click project name > select properties.
2.- Click "Build Events".
3.- Paste
"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil" -i "$(TargetPath)" } C:\Recycle.vbs
in to the "Post-build event command line" field.
4.- Create a new text file with the following script:
strAppPoolName = "Sharepoint - 80"
strComputer = "."
Set objWMIService = GetObject("winmgmts:{authenticationLevel=pktPrivacy}\\"& strComputer & "\root\microsoftiisv2")
Set colItems = objWMIService.ExecQuery("Select * From IIsApplicationPool Where Name = 'W3SVC/AppPools/" & strAppPoolName & "'")
For Each objItem in colItems
    objItem.Recycle
Next
Wscript.echo "Recycle Completed"
5.- Save as C:\Recycle.vbs

Tuesday, July 31, 2007

Request for the permission of type 'System.Data.SqlClient.SqlClientPermission, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561

A Web part/InfoPath form with managed code causes the above error.

Cause: DLL's that access databases require at least the WSS_Medium security policy in the web.config file. If you receive a security message from the web part, it's usually the trust element in the web.config file.
You could also have a dll outside the GAC that's trying to access some part of the SharePoint Object Model.
Fix: There's a couple of ways to resolve this issue.
  1. Put you dll in the GAC. I don't like putting limited use web parts in there and managed code for InfoPath doesn't like it.
  2. Open wss_mediumtrust.config & wss_minimaltrust.config usually (C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\config\) look in your web.config file for the exact path.
    Find in wss_mediumtrust.config:
    <SecurityClass Name="SqlClientPermission" Description="System.Data.SqlClient.SqlClientPermission, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
    Copy and paste it in to the <SecurityClasses> node of wss_minimaltrust.config.
    In the PermissionSet section of this configuration file, add the following: Find in wss_mediumtrust.config: <IPermission class="SqlClientPermission" version="1" Unrestricted="true"/>
    Copy and paste it in to the a <PermissionSet> node of wss_minimaltrust.config. That about covers it.
  3. You could also set the trust level to "wss_mediumtrust" or create a custom trust level. Google it...

The file or folder name contains characters that are not permitted. Please use a different name.

Creating a new site based on a custom site definition, you get the above error.
 
Cause: This error is caused by one of the aspx files in your site definition referencing and invalid master page. ei not default.master
 
Work Around: The only work around I've found is to put your custom master page in the masterpage library of the top site.
 
Even if the master page exists in both \Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\GLOBAL & LAYOUTS it will not work.


Update: OK had this issue again and its caused by the SP dll not finding the master page defined in the aspx page.
The fix is to make sure it can.
Options:
  • Put the masterpage at the site collection level, use it's absolute path (/_catalogs/masterpage/new.master or ~sitecollection/_catalogs/masterpage/new.master)
  • Use a site local masterpage library and use (~site/_catalogs/masterpage/new.master)
  • Thursday, June 21, 2007

    Using ASP.Net user controls ASCX in MOSS/WSSv3

    Chris Johnson has posted a great article on using ASP.Net ASCX user controls in MOSS/WSSv3. I have been recently creating custom controls in Visual Studio (i.e. Control Classes not ASCX). To use these I add the controls to the GAC and then add an entry to the web.config to make it a safe control. The benefit of the ASCX model is that you can develop the user control in a more visual manner.

    The ASCX controls can be used in MOSS/WSSv3 via the following method:

    1. Create a Directory called “usercontrols” in the root of your sharepoint web site on the file system E.g. C:\Inetpub\wwwroot\wss\VirtualDirectories\moss.litwareinc.com80\UserControls

    2. Open IIS manager and in the root of your SharePoint site create a VirtualDirectory called “_controls” and point it to that newly created directory.

    3. Put your user control in that newly created directory on the filesystem

    4. Open the web.config file and add the following:

    <SafeControl src="~/_controls/*" mce_src="~/_controls/*" IncludeSubFolders="True" Safe="True" AllowRemoteDesigner="True" /">

    5. In your ASPX page add the following:

    <%@ Register src="~/_controls/SomeControl.ascx" mce_src="~/_controls/SomeControl.ascx" TagName="somecontrol" TagPrefix="uc2" %">

    And…

    <uc2:somecontrol id="mycontrol1" runat="server"></uc2:somecontrol>

    6. Run your ASPX page and your control should render correctly.