05/01/2008
The Microsoft SharePoint Administration Toolkit has been released. It adds some new features for administrators. The first feature is "Batch Site Manager" and it allows you to Move, Lock, and Delete site collections from central admin on the Application Management page. The second feature called "Update Alert" lets you change the URL for an alert. This is useful if the site changes URLs after an alert was created. You can read more about this toolkit at Zach Rosenfield's blog. You can download the toolkit here:
x64: http://www.microsoft.com/downloads/details.aspx?FamilyId=F8EEA8F0-FA30-4C10-ABC9-217EEACEC9CE&displaylang=en
x86: http://www.microsoft.com/downloads/details.aspx?FamilyId=263CD480-F6EB-4FA3-9F2E-2D47618505F2&displaylang=en 04/16/2008
I've had to create a publishing page from code several times and it's a handy thing to know how to do. The following is an example of how to create a Publishing Page on the root web in SharePoint 2007: private void CreatePublishingPage()
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(SPContext.Current.Site.Url))
{
PageLayout layout = null;
// Get the root web as a publishing web
PublishingWeb pRootWeb = PublishingWeb.GetPublishingWeb(site.RootWeb);
// Find the desired page layout
string layoutName = "ArticleLeft.aspx";
foreach (PageLayout pl in pRootWeb.GetAvailablePageLayouts())
{
if (pl.Name.Equals(layoutName, StringComparison.OrdinalIgnoreCase))
{
layout = pl;
break;
}
}
if (layout != null) // Found the page layout
{
string fileName = "NewPage.aspx";
PublishingPage page = null;
try
{
// Create a new page in the root publishing web with the desired
// file name and page layout
page = pRootWeb.GetPublishingPages().Add(fileName, layout);
}
catch
{
// Page was not created
}
if (page != null)
{
// Set the page properties
string pageTitle = "Page Title";
string pageBody = "Page Body";
SPFile pageFile = page.ListItem.File;
// Get the title field by its internal name instead of the title
// and set it
SPField titleField = pageFile.Item.Fields.GetFieldByInternalName(
"Title");
pageFile.Item[titleField.Id] = pageTitle;
// Get the page content field by its internal name instead of the
// title and set it
SPField pageContent = pageFile.Item.Fields.GetFieldByInternalName(
"PublishingPageContent");
pageFile.Item[pageContent.Id] = pageBody;
// Update the list item
pageFile.Item.Update();
// Update the file
pageFile.Update();
// Check in the page
pageFile.CheckIn(string.Empty, SPCheckinType.MajorCheckIn);
// Publish the page
pageFile.Publish(string.Empty);
// If required, approve the page
try
{
pageFile.Approve(string.Empty);
}
catch
{
// Page doesn't need to be approved
}
}
else
{
// Handle page not created error
}
}
// close the publishing root web (it has no dispose method)
pRootWeb.Close();
// Dispose of the root web to free up resources
site.RootWeb.Dispose();
}
});
} 04/03/2008
Microsoft released a really neat feature in C# 3.0. This allows you to add methods to existing classes, even classes that you didn't write. I've been creating and using these all over the place to add functionality that probably should have been there from the start. They basically work like static methods, but you can call them just like you were calling a method on the current object. You can still call them as static methods if you need to. They have basically replaced functionality of some Utility classes that you always have sitting around to do various things. One useful thing you can do is Dispose of the site and the root web at the same time: using Microsoft.SharePoint;
namespace MDP.SharePoint.Extensions
{
public static class SPSiteExtensions
{
/// <summary>
/// Dispose of the site and root web with one method call!
/// </summary>
/// <param name="site"></param>
public static void DisposeSiteAndRootWeb(this SPSite site)
{
site.RootWeb.Dispose();
site.Dispose();
}
}
}To use this extension, all you have to do is reference the namespace of your Extension in a using statement on the class that you want to call the extension from. I recommend grouping your extensions in namespaces to make it easy to find them. using Microsoft.SharePoint;
using MDP.SharePoint.Extensions;
namespace MDPTest
{
public class MDPTestClass
{
public void Execute(string siteUrl)
{
SPSite site = new SPSite(siteUrl);
// Before Extension Methods we would have to call each one:
site.RootWeb.Dispose();
site.Dispose();
// Or make a Utility class to do it:
Utility.DisposeSiteAndRootWeb(site);
// Using Extension Methods, you will see that the method shows up in intellisense
site.DisposeSiteAndRootWeb();
// Or you can still call it like a static method:
SPSiteExtensions.DisposeSiteAndRootWeb(site);
}
}
}This is just one simple example of how to use the extensions, I have found them useful for many things and highly recommend using them over Utility classes since it adds options to intellisense. For more information about Extension Methods, check here: http://en.wikipedia.org/wiki/Extension_method 03/27/2008
I was trying to import a large SDO file (550MB) with Site Manager and I was getting the following error:
Error: 0 Description: The underlying connection was closed: An unexpected error occurred on a receive. Severity: 5 Source: System Debug info: N/A Extra info: N/A Client Source: CImProgress::ProcessPackage Recommended Action: N/A
After doing all of the steps in KB826210 and even in the MCMS SP Documentation, I was still having the same problem. Finally I found Mohamad Shehadeh's blog post on "Importing a SDO file manually using VB script in MCMS 2002" and that script ran just fine. You have to run the script as an MCMS Administrator or else you will get an access denied error. The only problem I had with it is afterwards, I had to login to MCMS to get rid of any errors. There is no permalink for the blog post so I will copy the script below in case it ever gets removed: ' VBScript for performing an import operation.
'usage: import.vbs filename.sdo
Dim strROPPath
Dim shell
Dim fso
strROPPath = WScript.Arguments(0)
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
If ( fso.FileExists(strROPPath) ) Then
Call Import(strROPPath)
Else
Call MsgBox(strROPPath, vbCritical, "File Does Not Exist")
End If
'**************************************
'* Routine that does the import.
'**************************************
Sub Import(strROPPath)
Dim pCmsDeployImport
On Error Resume Next
Set pCmsDeployImport = WScript.CreateObject("CmsDeployServer.CmsDeployImport.1")
If ( Err.Number <> 0 ) Then
Call MsgBox(Err.Description, vbCritical, "Import Problem")
Set pCmsDeployImport = Nothing
Exit Sub
End If
pCmsDeployImport.AuthenticateAsCurrentUser()
If ( Err.Number <> 0 ) Then
Call MsgBox(Err.Description, vbCritical, "Import Problem")
Set pCmsDeployImport = Nothing
Exit Sub
End If
Dim pImportOptions
Set pImportOptions = pCmsDeployImport.Options
If ( Err.Number <> 0 ) Then
Call MsgBox(Err.Description, vbCritical, "Import Problem")
Set pCmsDeployImport = Nothing
Set pImportOptions = Nothing
Exit Sub
End If
' Importing the grant rights
pImportOptions.IncludeRightsGroups = 3
pImportOptions.RightsOnAdd = 3
pImportOptions.RightsOnReplace = 2
pImportOptions.IncludeCreatedBy = 2
Dim strReportUrl
strReportUrl = pCmsDeployImport.Import(strROPPath)
If ( Err.Number <> 0 ) Then
Call MsgBox(Err.Description, vbCritical, "Import Problem")
Set pCmsDeployImport = Nothing
Set pImportOptions = Nothing
Exit Sub
End If
' Display the report in the Web browser.
Set shell = WScript.CreateObject("WScript.Shell")
shell.Run "http://localhost" & strReportUrl, 7
Call MsgBox( strReportUrl,vbInformation,"" )
Set shell = Nothing
Set pCmsDeployImport = Nothing
Set pImportOptions = Nothing
End Sub
03/25/2008
If you have a custom section in your site and you want to lock it down, SharePoint has provided built in functionality to do so. You can either wrap your control in the security trimmed control, or you can add one line of code to your page load function if you prefer to do it in code: SPContext.Current.Web.CheckPermissions(SPBasePermissions.ManageLists); This line makes sure that the current user has enough permissions to manage lists on the current web. If the user does not have enough permissions, they will be redirected to the access denied page. You could also use:
bool bVal = SPContext.Current.Web.DoesUserHavePermissions(SPBasePermissions.ManageLists); Instead of automatically redirecting the user, this will give you a boolean value telling you whether or not the current user has the requested permissions.
03/25/2008
If you are writing code for a custom component in SharePoint and you need to make sure that the user is logged in,
SharePoint has provided an easy way for that.
All you have to do is make a method call to:
Microsoft.SharePoint.Utilities.SPUtility.EnsureAuthentication();
This will automatically redirect the user to the login page if they are not already logged in. Otherwise it will continue executing code.
03/18/2008
Mark Arend has created a permissions matrix using the out of the box permissions in SharePoint 2007 to show you what is available to users of different permission levels. It shows you what options are available in the Site Actions and Site Settings menu as well as shows the individual permissions that each group has. Check it out here. 02/01/2008
While trying to upgrade a solution, I was getting the following error:
"A deployment or retraction is already under way for the solution "<solution_name>.wsp", and only one deployment or retraction at a time is supported."
In order to get around this, I found the following command that runs all pending admin tasks:
stsadm.exe -o execadmsvcjobs
Which resulted in the following:
Executing . Executing solution-deployment-<solution_name>.wsp-0. The solution-deployment-<solution_name>.wsp-0 job completed successfully, but could not be properly cleaned up. This job may execute again on this server. Operation completed successfully.
12/19/2007
One of the biggest problems I've had with timer jobs is that you cannot access the membership provider or role providers with them because they do not have a configuration value. Then if you want to read from a configuration file, you have to point it to one of the web.configs of the site.
All you need to do is create a config file for OWSTimer. You can do this one of two ways, you can deploy this using a solution or you can do it manually.
To do it manually, navigate to the hive (Program Files\Common Files\Microsoft Shared\web server extensions\12) and then open up the BIN folder. Now create a new file named OwsTimer.exe.config. In this file, you can place your config settings, this works just like an app.config or a web.config file that you would add in visual studio.
I've placed an example config file, but the Membership Provider and Role Provider nodes are not filled all of the way out, you can replace this with your own information or just remove the membership and role manager nodes completely.
<?xml version="1.0" encoding="utf-8" ?> <configuration> <connectionStrings> <add name="ConnString" connectionString="ConnectionStringGoesHere" /> </connectionStrings> <system.web> <membership defaultProvider="MembershipProvider"> <providers> <add name="MembershipProvider" /> </providers> </membership> <roleManager enabled="true" defaultProvider="RoleProvider"> <providers> <add name="RoleProvider" /> </providers> </roleManager> </system.web> <appSettings> <add key="SiteUrl" value="http://sharepointsite"/> <add key="ProviderPrefix" value="RoleProvider"/> </appSettings> </configuration>
Using this, you will be able to finally use a configuration file with your timer services without having to hard code the site that you are going to read the config settings from.
12/06/2007
Chris O'Brien has released a new tool for your SharePoint site to migrate content. He lists that the tool is good if you want to do any of the following:
I just need to move this document library from A to B
I just need to move these selected files (e.g. master page, page layouts, CSS etc.) from A to B
I just need to move this web from A to B
I just need to move this site collection from A to B
I just need to move these 20 list items from A to B
You can download the tool from his blog post here: http://sharepointnutsandbolts.blogspot.com/2007/12/introducing-sharepoint-content.html
I'm sure I'll be using this tool often in the future.
|
|
|
|
|
|
| Edit in Browser | /_layouts/images/icxddoc.gif | /blogs/MOSSMania/_layouts/formserver.aspx?XsnLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | FileType | xsn | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blogs/MOSSMania/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blogs/MOSSMania/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.2 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blogs/MOSSMania/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.3 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blogs/MOSSMania/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.4 | 255 | | Alert Role Members | /_layouts/images/MenuAlert.gif | /blogs/MOSSMania/_layouts/SusQtech/AlertRoles.aspx?ID={ItemId}&List={ListId} | 0x0 | 0x2000000 | ContentType | 0x01 | 1000 | | Manage Alerts | /_layouts/images/MenuAlert.gif | /blogs/MOSSMania/_layouts/SusQtech/RoleSubs.aspx?ID={ItemId}&List={ListId} | 0x0 | 0x2000000 | ContentType | 0x01 | 1100 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /blogs/MOSSMania/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsx | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /blogs/MOSSMania/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsb | 255 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /blogs/MOSSMania/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsx | 256 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /blogs/MOSSMania/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsb | 256 |
|
|
|
|