Friday, October 9, 2009

Custom Paging in SharePoint List

To do custom paging in SharePoint list, just we should calculate the position of last item (ListItemCollectionPosition) and pass it to the query. The steps to do paging are as following:

1. Get the previous page last SPList Item. And then generate the paging filter string as following:

SPList assetList = web.Lists[listName];

SPQuery query = new SPQuery();

query.Query = camel;

query.RowLimit = (uint)(pageItemCount * (pageIndex - 1));

assetDetailsItems = assetList.GetItems(query);

int previousPageLastItemPosition = assetDetailsItems.Count - 1;

StringBuilder columnBuilder = new StringBuilder();

if (columnNames != null)

{

foreach (string column in columnNames)

{

string columnValue = (assetDetailsItems[previousPageLastItemPosition][column] == null) ? string.Empty : assetDetailsItems[previousPageLastItemPosition][column].ToString();

columnBuilder.Append("&p_" + column + "=" + columnValue);

}

}

2. Create SPListItemCollectionPosition object based on columns details which retieved in step 1.

SPListItemCollectionPosition objSPListColPos = new SPListItemCollectionPosition("Paged=TRUE"

+ columnBuilder.ToString());

query.ListItemCollectionPosition = objSPListColPos;

3. Pass the SPQuery to the GetItems function, which will fetch items starting from the position that we created in step 2.

assetList.GetItems(query);

The following function does the paging for you, and in each calling, it will calculate first the total items count and then generate the last position for the page index parameter and finally get the items by using GetItems Function.

public static DataTable GetItems(string webSite, string listName, string camel,string viewFields, string[] columnNames, int pageIndex, int pageItemCount,out int ItemsCount)

{

SPListItemCollection assetDetailsItems = null;

using (SPSite site = new SPSite(webSite))

{

using (SPWeb web = site.OpenWeb())

{

// Get the list

SPList assetList = web.Lists[listName];

SPQuery query = new SPQuery();

query.Query = camel;

if (!string.IsNullOrEmpty(viewFields))

{

query.ViewAttributes = "Scope='RecursiveAll'";

query.ViewFields = viewFields;

}

// first calculate the totla items count

assetDetailsItems = assetList.GetItems(query);

ItemsCount = assetDetailsItems.Count;

// Retrieve the items for the last page. E.g.: If request is for 5th page and item count/page=10 then row limit will retrieve 40 items and 40th item will be used to get the column details which will be used for pagination.

query = new SPQuery();

query.Query = camel;

if (!string.IsNullOrEmpty(viewFields))

{

query.ViewAttributes = "Scope='RecursiveAll'";

query.ViewFields = viewFields;

}

query.RowLimit = (uint)(pageItemCount * (pageIndex - 1));

assetDetailsItems = assetList.GetItems(query);

// Get the previous page last item position. Use this item to retrieve the column details which will be used for pagination.

int previousPageLastItemPosition = assetDetailsItems.Count - 1;

// generate the last position

StringBuilder columnBuilder = new StringBuilder();

if (columnNames != null)

{

foreach (string column in columnNames)

{

// Make sure that if the field value is mandatory and if you are passing it as NULL then SPList.GetItems will throw exception.

string columnValue = (assetDetailsItems[previousPageLastItemPosition][column] == null) ? string.Empty : assetDetailsItems[previousPageLastItemPosition][column].ToString();

// Check if the value is null or empty

columnBuilder.Append("&p_" + column + "=" + columnValue);

}

}

query = new SPQuery();

query.Query = camel;

if (!string.IsNullOrEmpty(viewFields))

{

query.ViewAttributes = "Scope='RecursiveAll'";

query.ViewFields = viewFields;

}

// Create Paging Information which will be used for retrieving paging based items

SPListItemCollectionPosition objSPListColPos = new SPListItemCollectionPosition("Paged=TRUE"

+ columnBuilder.ToString());

query.RowLimit = uint.Parse(pageItemCount.ToString());

// check if the page index = 1,that mean no need for list position

if (pageIndex != 1)

query.ListItemCollectionPosition = objSPListColPos;

// Execute the CAML query.

assetDetailsItems = assetList.GetItems(query);

}

}

return assetDetailsItems.GetDataTable();

}

[Note: we can increase the performance of the code by storing the last calculated position in view state and don't generate it each time, but in this case we can do paging not by numbers but with next and previous functionality]

Monday, June 22, 2009

How to create Mailbox in Exchange Server 2007 programmatically

If you have exchange server 2007 or you want to upgrade from exchange server 2003 to exchange server 2007. And you want your end user to create his email on exchange from your application or portal. Of course in exchange 2003 we can use CDOEXM to create mailboxes programmatically. But in exchange server 2007 doesn't support CDOEXM. Therefore to do this, we should depend on Power Shell in creating mailboxes.

The prerequisites are just to install power shell on your web server and of course you need to install the Exchange Server Management Tools on the server that will execute the code.
After that you can use this function:

public static IList CreateEmail(string userName, string mail, string domain, string ou, string exDatabase)
{
//create the command
string cmd = string.Format("Enable-Mailbox -Identity '{0}/{1}/{2}' -Alias '{3}' -Database '{4}'", domain, ou, userName, mail, exDatabase);
ExchangeManagementShellWrapper ems = ExchangeManagementShellWrapper.Instance;
ICollection results;
IList IErrors;

results = ems.RunspaceInvoke(cmd, out IErrors);

return IErrors;

}

Of course this function needs user name, mail (the name that you want to be user email), domain, ou (which represents the organization unit path, which this user is existed on), and exchange database. And by using ExchangeManagementShellWrapper you can run this command and get the result.

for source code of ExchangeManagmentShellWrapper, you can download it from internet or anyone who need it,I can send it to him by email.

Monday, June 15, 2009

Custom Field Type in SharePoint: Upload File, Image, Video

Custom Field Type: Upload File, Image, Video


In this post I'll explain how you can create a custom field type, which enables end user to upload files, images and videos to document library and attach these files to pages in one step in edit properties of the page.
I build this custom field type according to these requirements, which were:


- The end user wants to attach a file to page in edit properties form.
- The user doesn't want to go first to document library or image library and upload the file and then go back to edit form page and choose the file, he want to use Upload File Control to choose the file from his device in the edit properties form of the page directly.
- The Admin wants to set the maximum size of files that user will upload.
- The Admin wants to set the allowed extensions for uploaded files.
- The Admin specify where these files will be stored inside the site.


Therefore I build a custom field type with these features:
When you define a site column from Upload File Type, you
- Set the URL of the site that contains the document library that you want to store files in.
- Choose the document library that you want to store files in.
- Set the allowed extensions.
- Set the maximum file size.


The value of this field will be string, which represent the URL of the file. To build this custom field we should create the following:



1. The Editor Control, which appear when you define the site column of this custom field type. In this editor we should save the URL of the site, the document library, allowed extensions and maximum file size as the following:








This user control (Editor) should implements IFieldEditor and should inherit UserControl. So we should implement the InitializeWithField function and OnSaveChange as following:

public void InitializeWithField(SPField field)
{
try
{
fldUploadImageField = (UploadImageField)field;

if (Page.IsPostBack) return;

labelDescription.Text = ResourceManager.GetResource("labelDescription");
labelDocLib.Text = ResourceManager.GetResource("ImagelabelDocLib");
labelWebUrl.Text = ResourceManager.GetResource("labelWebUrl");
labelExtensions.Text = ResourceManager.GetResource("labelExtensions");
labelMaxFileSize.Text = ResourceManager.GetResource("labelMaxFileSize");
txtMaxFileSize.Text = ResourceManager.GetResource("txtMaxFileSize"); // as default value to max size
btnLoadDocLibs.Text = ResourceManager.GetResource("btnLoadDocLibs");

if (field != null)
{
txtExtensions.Text = fldUploadImageField.AllowedExtensions;

txtWebUrl.Text = fldUploadImageField.FieldToInsertLink;

fillDocLibraries(ddlDocLib, txtWebUrl.Text.Trim());

txtMaxFileSize.Text = fldUploadImageField.MaxFileSize;

// set values from field properties
ddlDocLib.SelectedValue = fldUploadImageField.DocumentLibraryName;

}



}
catch (Exception ex)
{
labelError.Text += string.Format("Error in InitializeWithField: {0}
", ex);
}
}

2. Creating Field Class which inherits SPFieldText : this class represents the particular field and should contains a properties which represent URL, document library, files allowed extensions and maximum file size as following:

public string DocumentLibraryName
{
get { return GetCustomProperty("DocumentLibraryName") + ""; }
set { SetCustomProperty("DocumentLibraryName", value); }
}

public string FieldToInsertLink
{
get { return GetCustomProperty("FieldToInsertLink") + ""; }
set { SetCustomProperty("FieldToInsertLink", value); }
}

public string AllowedExtensions
{
get { return GetCustomProperty("AllowedExtensions") + ""; }
set { SetCustomProperty("AllowedExtensions", value); }
}

public string MaxFileSize
{
get { return GetCustomProperty("MaxFileSize") + ""; }
set { SetCustomProperty("MaxFileSize", value); }
}


3. A field Control which should inherits from BaseFileFieldControl:
In this class we should implement the following properties and functions:
o Value Property: which is used to set and get the value of the field.
o CreateChildControls: this function is used when the control is drawn in edit mode of the page or in edit properties form.
This function will draw the control as following:











o RenderFieldForDisplay: which is used when the page is in display mode, in this function if the file type is image, then we should render it as image tag and it'll appear in the page as following:



















And if the file is video, we should render it as object tag and it'll appear as following:





And if the file is document, we should render it as link tag as following:







o Validate: which is used to validate the value of the fields like maximum file size or validate on file extension.

4.Xml file which contains the information that the WSS needs to correctly render the field as following :