Tuesday, April 28, 2009

MOSS 2007 - Create List Item using aspx query string

Can’t get email enabled document libraries working?

I was unable to get email enabled libraries to work in my SharePoint environment due to security issues relating to Active Directory account creation. The following code takes the query string parameters and creates a list item with the metadata in the specified list. I have this script being called by event handlers in Outlook, which call the page / script, passing the required details in the query string.

By default, SharePoint (MOSS 2007) has code block enabled. This means that a page or script won’t load / run if there it contains code. To disable code blocks in MOSS, please see my post
Code Blocks in MOSS 2007 for instructions on how to disable code blocks.

The following code must be placed inside the aspx page the you would like to create the list items via the query string:

<script type="text/c#" runat="server">

/*---------------------------------------------------------------------
This page/script is used to create a list item using a GET query
string.
---------------------------------------------------------------------*/

//Declare Variables
public String siteURL;
public String list;
public String itemSubject;
public String itemSentBy;
public String itemSentTo;
public String itemSentOn;
public String linkToItem;
public String received;
public String strCc;
public String strBcc;
public String itemSent;

protected void Page_Load(object sender, EventArgs e)
{

/*---------------------------------------------------------------------
This function runs when the page loads, which calls all required
functions to create the list item. This page does not Display
any content.
---------------------------------------------------------------------*/


//form1.InnerHtml = "<h1>Hello</h1>";
//AddNewListItem();
getQueryStringValues();

InsertEnquiryToSharepoint();
}


/*---------------------------------------------------------------------
This function stores the query string values into public variables
---------------------------------------------------------------------*/
public void getQueryStringValues()
{

siteURL = Request.QueryString["URL"];
list = Request.QueryString["List"];
itemSubject = Request.QueryString["Subject"];
itemSentBy =
Request.QueryString["SentBy"];
itemSentTo = Request.QueryString["SentTo"];
itemSentOn = Request.QueryString["DateSent"];
received = Request.QueryString["Received"];
strCc = Request.QueryString["Cc"];
strBcc = Request.QueryString["Bcc"];
itemSent = Request.QueryString["ItemSent"];
}


/*---------------------------------------------------------------------
This function opens the required SharePoint Site and list and
creates a list item with the values supplied via the query string
---------------------------------------------------------------------*/
protected void InsertEnquiryToSharepoint()
{

string strDashListRoot = "http://sitecollectionroot/Lists/EmailRegister/";
using(SPSite site = new SPSite(strDashListRoot))
{

using (SPWeb web = site.OpenWeb())
{
web.AllowUnsafeUpdates = true;

SPList list = web.Lists["List Name"];
SPListItem item = list.Items.Add();

item["Subject"] = itemSubject;
item["To"] = itemSentTo;
item["From"] = itemSentBy;

item["Sent"] = itemSentOn;
item["Received"] = received;
item["Cc"] = strCc;
item["Bcc"] = strBcc;

item.Update();
form1.InnerHtml = "<p>Item Created
Successfully:<br/>Site Name: " + web.Title +
"</p><br/>List Name: " + list.Title;
}
}
}

</script>

Monday, April 27, 2009

InfoPath data connection not returning all results from a SharePoint list

Problem

I have a data connection retrieving ID values from a library’s items to determine the maximum ID of items currently in the list. Certain metadata results in items not appearing in the default view. When InfoPath queries the data connection, only IDs of items which display in the default view are retrieved.

This became a problem as the maximum ID found by InfoPath was 240, when documents existed in the library with an ID of 246. To complicate the matter even further, a number of documents had been added and removed from the library making the next available ID 268. I needed InfoPath data connection to give me the maximum ID of current documents (246).

Cause

Data connections in InfoPath return the same results as the default view for the specified SharePoint list.

Solution 1:

  • Create a view which returns all items in a list / library (no filter criteria) – Set this view as default
  • Will work well for lists libraries with less than 2000 items, and when a custom view is not required as the default

Solution 2:

If a large number of items exist in a library, performance can be maintained by creating a view which filters out items which are not required. If a list contains over 2000 items, create a view which returns the most recent 200 items which satisfy reasons for using the InfoPath data connection. In terms of the example above, as I need to find the maximum ID of current documents, the result won’t be affected if documents older than two months (IDs 1 to about 150) filtered out.

This would also apply when you require a view with custom filtering as the default view for a list. If this is the case, care must be taken when setting filter criteria to ensure that items to be retrieved by the InfoPath data connection are returned by the view.

If you required a custom view as the default, but are not getting the expected results: Try both:

  • Keep the custom view
  • Create a view to return all items in a list, set as default (this is for the InfoPath data connection)
  • Modify all hyperlinks pointing to the list (site navigation, web part titles, etc.) to point to the custom view if a user navigates to the list. (this is for the SharePoint User Interface)

Note: You may have to set the item limit to number greater than the total number of items in the list / library

  • There is no set maximum number of documents or items allowed in a SharePoint list or library, but performance is affected when a large number of items exist.

SharePoint (MOSS 2007) Document library and List item limits

The following is a summary of Microsoft’s recommended item limits required to maintain server performance. (Reference: http://technet.microsoft.com/en-us/library/cc262787.aspx )

  • Document Library: Max 5 million, recommended 2000 to maintain list view performance (time to load a page containing the list items)
  • Max file size: 50MB (default) – can be set up to 2GB.

Code Blocks in MOSS 2007

By default, code blocks are set in the web.config file for the SharePoint server. For the code in this page to run, you will need to add an exception to the file to allow code to be run in the aspx.

Security Warning: The web.config file accepts a wildcard character: * when specifying the path, which could allow any page in the specified site collection to run code. With code blocks disabled, it is possible to bypass or work around permissions used on sites, lists and libraries.

The web.config file is generally located in the C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\CONFIG directory


1. Find the following tag in the web.config file:

<pageparserpaths>
........
</pageparserpaths>


2. Add a <pageparserpath> tag with path required attributes (see below)

<pageparserpath virtualpath="/_catalogs/masterpage/*"
compilationmode="Always" allowserversidescript="true"
includesubfolders="true">


The above line will allow any page in the masterpage library and sub-folders to run script or code. The web.config file should look like this:

<pageparserpaths>

<pageparserpath
virtualpath="/_catalogs/masterpage/*"
compilationmode="Always"
allowserversidescript="true"
includesubfolders="true">

</pageparserpaths>

Sunday, April 19, 2009

Split List View web part labels (javascript)

The following is a javascript function created to split long questions / column titles on a SharePoint survey or list when editing (EditForm.aspx / DispForm.aspx).

I had a survey with questions containing hundreds of characters. When the EditForm.aspx / DispForm.aspx pages render the survey for completion, the questions are wrapped in <nobr> tags, which results in the page's width being much larger than the browser, regardless of resolution.

The function takes all <nobr> elements and replaces those which match required criteria. Each question / column in the survey starts with a number, which is followed by the question ( "1. ..." "2. ..." etc.). The function runs through a series of tests to determine the currrent question. If the beginning of the line matches the required question number, contents of the element is replaced to include a break (<br>) tag to split the line.

Possible improvements:

  • Split the question string after a specific number of characters: Replacing the space between the words closest to the the specified number of characters with a <br&gt tag. This would make the function generic, meaning that each question would be split by the same block of code if a line is greater than the maximum number of characters. If placed into another EditForm.aspx or DispForm.aspx page, the function will continue to split long column names with having to modify the code (the code below is not generic).
  • Link the function to the site collection masterpage, which can then be triggered if a variable (the string length) is found in the query string. If found, the function can be called, passing the specified maximum length for question lines. (May split undesired lines of text if also wrapped in <nobr> tags)

<script type="text/javascript" language="javascript" >
<!--
// this is default SharePoint function
//it will call after page is loaded.
_spBodyOnLoadFunctionNames.push("split");

//this function finds all <nobr> tag
//then check our original text and
//replace new text which contains <br>
function split()
{

var subInner = "";
var oP = document.getElementsByTagName('nobr');//the collection of <p> tags
for(var i=0;i<oP.length;i++) //loop through array
{
subInner = oP[i].innerHTML.substring(0,3); //Get the first 3 chars of current string

if(subInner == '13.') //text to identify a specific question
{
oP[i].innerHTML = '13. first line text...<br> second line text...<span class="ms-formvalidation"> *</span>'
}
}
}
//-->
</script>