One of the most important things you can do to ensure a stable and responsive SharePoint environment is to dispose of SPWeb objects. SPWeb object are fat. The "automatic" garbage collection in .net 2.0 just doesn't do the job. So, use a using statement or explicitly call dispose. If you are passing SPWeb objects around you need to dispose of them in the method were they are used. The only time you'll run into issues disposing of an SPWeb object is when it's the current web like SPWeb myWeb = SPContext.Current.Web. Go ahead and try disposing of it anyway, it's better to fix the error and make sure you're disposing properly. A tool is available to help you check your code, SPDisposeCheck.
SPWeb myWeb = site.OpenWeb();
try{}
catch{}
finally
{
if(myWeb != null)
myWeb.Dispose();
}
using(SPWeb myWeb = site.OpenWeb())
{}
Wednesday, October 28, 2009
Saturday, October 24, 2009
Allow Anonymous Users to run SharePoint Workflows
The code that follows will allow you to start a workflow from an event receiver. There are a couple of reasons that you may want to do this. First, you have more control over your workflow. You can check and make sure that it's started successfully. Second, you can allow users or processes to execute workflows that couldn't otherwise. Next is how you can find your workflow's guid.
OOB Workflow - get the TemplateID from the url
the guid here is 19149E7D-1970-4432-B174-D88C7BF2B4008
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using System.Net;
using System.Diagnostics;
using Microsoft.SharePoint.Workflow;
namespace StartWorkflow
{
class StartWorkflowOnItemAdded : SPItemEventReceiver
{
// use the itemadded event to start a workflow
public override void ItemAdded(SPItemEventProperties properties)
{
try
{
// make sure no other events can be fired
DisableEventFiring();
// execute StartWorkflow as application pool
SPSecurity.RunWithElevatedPrivileges(delegate(){
StartWorkflow(properties);
});
}
catch (Exception ex)
{}
finally
{
// allow other events to fire
EnableEventFiring();
}
}
private void StartWorkflow(SPItemEventProperties properties)
{
using (SPSite site = new SPSite(properties.WebUrl))
{
using (SPWeb web = site.OpenWeb())
{
try
{
SPList list = web.Lists[properties.ListId];
//enter your workflow Guid
Guid wGuid = new Guid("{}");
//get the association data
SPWorkflowAssociation wTemplate =
list.WorkflowAssociations.GetAssociationByBaseID(wGuid);
//start your workflow
site.WorkflowManager.StartWorkflow(properties.ListItem,
wTemplate, wTemplate.AssociationData);
}
catch (Exception ex)
{}
}
}
}
}
}
SharePoint Designer Workflow - 650F1ED3-2FEE-499D-A9A2-40BE326951C1
OOB Workflow - get the TemplateID from the url
the guid here is 19149E7D-1970-4432-B174-D88C7BF2B4008
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using System.Net;
using System.Diagnostics;
using Microsoft.SharePoint.Workflow;
namespace StartWorkflow
{
class StartWorkflowOnItemAdded : SPItemEventReceiver
{
// use the itemadded event to start a workflow
public override void ItemAdded(SPItemEventProperties properties)
{
try
{
// make sure no other events can be fired
DisableEventFiring();
// execute StartWorkflow as application pool
SPSecurity.RunWithElevatedPrivileges(delegate(){
StartWorkflow(properties);
});
}
catch (Exception ex)
{}
finally
{
// allow other events to fire
EnableEventFiring();
}
}
private void StartWorkflow(SPItemEventProperties properties)
{
using (SPSite site = new SPSite(properties.WebUrl))
{
using (SPWeb web = site.OpenWeb())
{
try
{
SPList list = web.Lists[properties.ListId];
//enter your workflow Guid
Guid wGuid = new Guid("{}");
//get the association data
SPWorkflowAssociation wTemplate =
list.WorkflowAssociations.GetAssociationByBaseID(wGuid);
//start your workflow
site.WorkflowManager.StartWorkflow(properties.ListItem,
wTemplate, wTemplate.AssociationData);
}
catch (Exception ex)
{}
}
}
}
}
}
Labels:
Anonymous,
SharePoint,
Workflow
Thursday, October 22, 2009
SharePoint Progamming 101 - Impersonation
Many times you want to make sure that your code runs no mater what permissions the current user has. There are two easy ways that you can accomplish this in SharePoint. Both of the techniques do the same thing, execute code with the permissions of the application pool the site is running under. You must create a new spweb object from a url after impersonating the application pool.
WindowsImpersonationContext ctx = null;
ctx = WindowsIdentity.Impersonate(System.IntPtr.Zero);
SPSite site = new SPSite("http://mysteurl");
SPWeb web = site.OpenWeb();
try
{
//All of this code will run with elevated privileges
}
catch (Exception ex)
{}
finally
{
web.Dispose();
//make sure you revert to normal
ctx.Undo();
}
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite("http://mysteurl"))
{
using (SPWeb web = site.OpenWeb())
{
//All of this code will run with elevated privileges
}
}
});
Method 1
//Impersonate the poolWindowsImpersonationContext ctx = null;
ctx = WindowsIdentity.Impersonate(System.IntPtr.Zero);
SPSite site = new SPSite("http://mysteurl");
SPWeb web = site.OpenWeb();
try
{
//All of this code will run with elevated privileges
}
catch (Exception ex)
{}
finally
{
web.Dispose();
//make sure you revert to normal
ctx.Undo();
}
Method 2
//Impersonate the poolSPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite("http://mysteurl"))
{
using (SPWeb web = site.OpenWeb())
{
//All of this code will run with elevated privileges
}
}
});
Labels:
SharePoint Impersonation
Sunday, October 18, 2009
SharePoint Cross Site List Views with jQuery
Displaying or sharing lists across webs or site collections is not supported out of the box by SharePoint. The best way to overcome this limitation is by loading the list dynamically. Ok, sounds great but how am I supposed to do that? No worries, it's really pretty easy. I will use jQuery's load function to do the bulk of the work. The code here has been adapted from Christophe's solution . There are a number of changes, the most important being enabling sorting by column.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
Add the Script to the page
Add a new CEWP, yes you have to, to your page and add the following script.
<DIV id="ListPlaceholder"><span><b>...Loading...</b></span></DIV>
<script type="text/javascript">
// Make sure the page has been loaded
$(document).ready(function() {
// Paste the URL of the source list below:
var SelectedView = "http://test/sites/test/Lists/Tasks/AllItems.aspx";
// Paste the URL of Add new items page
var AddNewItems = "http://test/sites/test/Lists/Tasks/NewForm.aspx" + "?Source="+location.href;
// Title
var mTitle = "My List Name";
// Title tool tip
var MouseOverHeader = "My List Name Description";
var innerHTML = "<a href=" + AddNewItems + " tabindex='0' accesskey='W'><nobr><span>" + mTitle + "</span><span id='WebPartCaptionWPQ6'/></nobr></a>";
// Load the list
$("#ListPlaceholder").load(SelectedView+" [id^='WebPartWPQ'] .ms-listviewtable", function(){processView();setColumnClicks();});
// Format the returned list view
function processView(){
//set the header of the content place holder
var hdrNode = $("#ListPlaceholder").closest('tr').prev().find('h3');
hdrNode.html(innerHTML);
hdrNode.parent(0).attr('title', MouseOverHeader);
//Remove the dropdown menus for items
$("#ListPlaceholder *").removeAttr("id").removeAttr("onclick").removeAttr("onfocus").removeAttr("onmouseover");
//Format the Items
$("#ListPlaceholder a").each(function() {
if ($(this).attr("href").indexOf("javascript") == -1){
if ($(this).attr("href").indexOf("mailto") == -1){
if ($(this).attr("href").indexOf("?") > 0){
$(this).attr("href",$(this).attr("href")+"\&Source="+location.href);}
else {$(this).attr("href", $(this).attr("href")+"?Source="+location.href);}
}
}
});// close each
}// close processView
//Make the titles sortable
function setColumnClicks(){
$("#ListPlaceholder a[sortingfields]").click(function(){
var srtFields = $(this).attr('sortingfields');
$("#ListPlaceholder").load(SelectedView +"?" + srtFields + " [id^='WebPartWPQ'] .ms-listviewtable", function(){processView();setColumnClicks();});
});
}
});//Close document.ready
</script>
$("#ListPlaceholder").load(SelectedView+" [id^='WebPartWPQ'] .ms-listviewtable", function(){processView();setColumnClicks();});
This line means the following. Find the element on this page with an id of ListPlaceholder and load the content from SelectedView. Only load the content where the element id starts with WebPartWPQ and has the class ms-listviewtable. After loading the content run functions processView() and setColumnClicks().
Another question you may have is what is this Source used all over the place for ? SharePoint uses Source= in the url to return to the previous page.
Load the jQuery library
I'm adding a content editor web part to include the jQuery library. You should probably add the library to your master page. Once you start using it you'll want to add it all over the place. Add a CEWP to your page and add the following script tag. This will load jQuery from Google.<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
Add the Script to the page
Add a new CEWP, yes you have to, to your page and add the following script.
<DIV id="ListPlaceholder"><span><b>...Loading...</b></span></DIV>
<script type="text/javascript">
// Make sure the page has been loaded
$(document).ready(function() {
// Paste the URL of the source list below:
var SelectedView = "http://test/sites/test/Lists/Tasks/AllItems.aspx";
// Paste the URL of Add new items page
var AddNewItems = "http://test/sites/test/Lists/Tasks/NewForm.aspx" + "?Source="+location.href;
// Title
var mTitle = "My List Name";
// Title tool tip
var MouseOverHeader = "My List Name Description";
var innerHTML = "<a href=" + AddNewItems + " tabindex='0' accesskey='W'><nobr><span>" + mTitle + "</span><span id='WebPartCaptionWPQ6'/></nobr></a>";
// Load the list
$("#ListPlaceholder").load(SelectedView+" [id^='WebPartWPQ'] .ms-listviewtable", function(){processView();setColumnClicks();});
// Format the returned list view
function processView(){
//set the header of the content place holder
var hdrNode = $("#ListPlaceholder").closest('tr').prev().find('h3');
hdrNode.html(innerHTML);
hdrNode.parent(0).attr('title', MouseOverHeader);
//Remove the dropdown menus for items
$("#ListPlaceholder *").removeAttr("id").removeAttr("onclick").removeAttr("onfocus").removeAttr("onmouseover");
//Format the Items
$("#ListPlaceholder a").each(function() {
if ($(this).attr("href").indexOf("javascript") == -1){
if ($(this).attr("href").indexOf("mailto") == -1){
if ($(this).attr("href").indexOf("?") > 0){
$(this).attr("href",$(this).attr("href")+"\&Source="+location.href);}
else {$(this).attr("href", $(this).attr("href")+"?Source="+location.href);}
}
}
});// close each
}// close processView
//Make the titles sortable
function setColumnClicks(){
$("#ListPlaceholder a[sortingfields]").click(function(){
var srtFields = $(this).attr('sortingfields');
$("#ListPlaceholder").load(SelectedView +"?" + srtFields + " [id^='WebPartWPQ'] .ms-listviewtable", function(){processView();setColumnClicks();});
});
}
});//Close document.ready
</script>
Explaining the script
This line in the script really does all of the work$("#ListPlaceholder").load(SelectedView+" [id^='WebPartWPQ'] .ms-listviewtable", function(){processView();setColumnClicks();});
This line means the following. Find the element on this page with an id of ListPlaceholder and load the content from SelectedView. Only load the content where the element id starts with WebPartWPQ and has the class ms-listviewtable. After loading the content run functions processView() and setColumnClicks().
Another question you may have is what is this Source used all over the place for ? SharePoint uses Source= in the url to return to the previous page.
Labels:
Ajax,
jQuery,
List View,
SharePoint
Sunday, October 11, 2009
Customizing a SharePoint Banner
Modifying the header or banner portion of a SharePoint page is not as easy as you would hope. In this post I’ll walk you through one possible approach to adding a custom look while maintaining the functionality and positioning of out of the box components. I’m going to be using SharePoint designer to modify the master page to customize the banner. This is what I’m starting with.
Open the site you’re working on with SharePoint designer File > Edit with Microsoft Office SharePoint Designer. COPY the default.master page found in this directory _catalogs/masterpage/. Open the copied master page, find the tag below, it’s the starting point for the header portion of the page.
<TABLE class="ms-main" CELLPADDING=0 CELLSPACING=0 BORDER=0 WIDTH="100%" HEIGHT="100%">
Add this line directly underneath the table tag. You can also add an image as the background here as long as it grows and shrinks gracefully.
<tr><td><div style="background-color:fuchsia"><table width="100%">
Find <asp:ContentPlaceHolder ID="WSSDesignConsole" runat="server"> close the tags you’ve just added by adding this line above the content placeholder </table></div></td></tr>.
Find and remove class="ms-globalTitleArea".
Find and remove class="ms-bannerContainer".
Ok, we’ve changed the background color. Let’s change the title of the site. Find the content place holder tag below and remove it.
<td class="ms-sitetitle" width=100%>
<asp:ContentPlaceHolder id="PlaceHolderSiteName" runat="server">
<SharePoint:SPLinkButton runat="server" NavigateUrl="~site/" id="onetidProjectPropertyTitle">
<SharePoint:ProjectProperty Property="Title" runat="server" /> </SharePoint:SPLinkButton>
</asp:ContentPlaceHolder>
</td>
Once you have removed the content place holder tag and its contents you, will not be able to change the title via the admin settings in the browser. Add whatever markup here you would like.
<h2 style="color:white">This has been way harder than it should be</h2>
You can use this area to include an image as well, replace the <h2> tag with something like this:
<div style="background-image:url('images/header.gif');background-repeat:no-repeat; height:150px"></div>
To Get rid of the icon to the left find the SharePoint:SiteLogoImage tag and replace LogoImageUrl="/_layouts/images/titlegraphic.gif" with LogoImageUrl="/_layouts/images/blank.gif"
If you would like to change the color of the links in the header area you will need to override the following CSS classes, ms-SPLink, ms-globallinks and ms-sitemapdirectional.
Labels:
SharePoint Banner
Subscribe to:
Posts (Atom)