Selected Item getting lost on post back (Sharepoint wss3.0 webpart) - sharepoint

I am new Sharepoint developer and trying to create search webpart in window Sharepoint service 3.0 [Free edition], so far I can select multiple item from list box but when i trying to display selected item into textbox it getting lost.
Below is my code:
using System;
using System.Runtime.InteropServices;
using System.Data;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Drawing;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using System.Xml.Serialization;
using System.Collections;
namespace Filter_WebPart
{
[Guid("6641a7a3-d2c4-4fda-9ef5-89596845bd6e")]
public class Filter_WebPart : System.Web.UI.WebControls.WebParts.WebPart
{
protected DataSet _dataset;
protected ListBox lstRegion;
protected ListBox lstMaterial;
protected HtmlButton btnSubmit;
protected HtmlInputText txtDisplay;
private string myExceptions = "";
//private int[] Index1;
protected override void CreateChildControls()
{
try
{
//Region Table / DataSet
lstRegion = new ListBox();
lstRegion.ID="lstRegion";
lstRegion.SelectionMode = ListSelectionMode.Multiple;
//lstRegion.EnableViewState = true;
//lstRegion.SelectedIndex = 0;
//Material Table / DataSet
lstMaterial = new ListBox();
lstMaterial.SelectionMode = ListSelectionMode.Multiple;
lstMaterial.EnableViewState = true;
btnSubmit = new HtmlButton();
btnSubmit.InnerText = "Filter";
btnSubmit.ServerClick += new EventHandler(btnSubmit_Click);
txtDisplay = new HtmlInputText();
//CommandButton
this.Controls.Add(lstRegion);
this.Controls.Add(lstMaterial);
this.Controls.Add(btnSubmit);
this.Controls.Add(txtDisplay);
}
catch(Exception ChildControlException)
{
myExceptions += "ChildControlException:" + ChildControlException.Message;
}
finally
{
//base.CreateChildControls();
}
}
protected override void OnPreRender(EventArgs e)
{
if(!this.Page.IsPostBack)
{
lstMaterial.DataSource = GetMaterialList();
lstMaterial.DataTextField = "Material Name";
lstMaterial.DataValueField = "Material Name";
lstMaterial.DataBind();
lstRegion.DataSource = GetRegionList();
lstRegion.DataTextField = "Region Name";
lstRegion.DataValueField = "Region Name";
lstRegion.DataBind();
txtDisplay.Value="1 time";
}
base.OnPreRender(e);
}
void btnSubmit_Click(object sender, EventArgs e)
{
string tmpStr="";
int k=0;
//int i=0;
lstMaterial.DataBind();
lstRegion.DataBind();
//int[] indx = lstRegion.GetSelectedIndices();
//for(i=0;i<indx.Length;i++)
//{
// tmpStr = tmpStr+","+lstRegion.Items[indx[i]].Text;
//}
//if(lstRegion.SelectedIndex >=0 )
//{
//for(i=0;i < lstRegion.Items.Count;i++)
//{
// //if(i==5 || i==10)
// //{
// // lstRegion.Items[i].Selected = true;
// //}
// if(lstRegion.Items[i].Selected)
// {
// tmpStr = lstRegion.Items[i].Text;
// }
// k=k+1;
//}
//}
foreach(ListItem RgItem in lstRegion.Items)
{
if(RgItem.Selected == true)
{
tmpStr = tmpStr +","+RgItem.Text;
k=k+1;
}
}
//for(i=0;i<lstRegion.Items.Count;i++)
//{
// if(lstRegion.Items[i].Selected == true)
// {
// txtDisplay.Value = txtDisplay.Value +","+lstRegion.Items[i].Text;
// k=k+1;
// }
//}
if(tmpStr != "" )
{txtDisplay.Value = tmpStr;}
else{
txtDisplay.Value = k.ToString();
btnSubmit.InnerText = "Done";}
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
EnsureChildControls();
}
private DataSet GetRegionList()
{
_dataset = new DataSet();
DataTable _tbl = new DataTable();
DataColumn _tblcol = new DataColumn("Region Name");
_tbl.Columns.Add(_tblcol);
SPWeb web = SPContext.Current.Site.RootWeb;
SPList myList = web.Lists["Service Area"];
SPQuery query = new SPQuery();
query.Query = "";
SPListItemCollection items = myList.GetItems(query);
foreach (SPListItem item in items)
{
DataRow _row = _tbl.NewRow();
_row[0] = SPEncode.HtmlEncode(item["Region Name"].ToString());
_tbl.Rows.Add(_row);
}
_dataset.Tables.Add(_tbl);
return _dataset;
}
private DataSet GetMaterialList()
{
_dataset = new DataSet();
DataTable _tbl = new DataTable();
DataColumn _tblcol = new DataColumn("Material Name");
_tbl.Columns.Add(_tblcol);
SPWeb web = SPContext.Current.Site.RootWeb;
SPList myList = web.Lists["Material Master"];
SPQuery query = new SPQuery();
query.Query = "";
SPListItemCollection items = myList.GetItems(query);
foreach (SPListItem item in items)
{
DataRow _row = _tbl.NewRow();
_row[0] = SPEncode.HtmlEncode(item["Material Name"].ToString());
_tbl.Rows.Add(_row);
}
_dataset.Tables.Add(_tbl);
return _dataset;
}
protected override void RenderContents(HtmlTextWriter output)
{
try
{
this.EnsureChildControls();
lstRegion.RenderControl(output);
lstMaterial.RenderControl(output);
btnSubmit.RenderControl(output);
output.Write("<br>");
txtDisplay.RenderControl(output);
//base.RenderContents(output);
}
catch (Exception RenderContentsException)
{
myExceptions += "RenderException:" + RenderContentsException.Message;
}
finally
{
if (myExceptions.Length > 0)
{
output.WriteLine(myExceptions);
}
}
}
}
}

This should be working. I've tried your code on my 2010 farm and it works fine (should also work for WSS3).
Did you forget to do an iisreset after updating the assembly ?
Your best chance to finding a solution is to use the debugger. You can attach the debugger to the right w3wp.exe process. If you don't know which one, select them all. Then set a breakpoint on your event handler and check where you lose your selection.
You don't need to override OnInit, you can put EnsureChildControls() in btnSubmit_Click.

Related

Executing a site workflow in sharepoint from a console application

I am trying to execute a site workflow from a console application.When the code to execute the workflow runs, it thows an error
An unhandled exception of type 'Microsoft.SharePoint.Client.ServerException' occurred in Microsoft.SharePoint.Client.Runtime.dll
Additional information:
Cannot invoke method or retrieve property from null object. Object returned by the following call stack is null. "GetWorkflowInteropService new Microsoft.SharePoint.WorkflowServices.WorkflowServicesManager()"
string userName = "username";
string password = "password";
string siteUrl = "https://share.example.com/sites/workflowsite";
string workflowName = "MyWorkflow";
using (ClientContext clientContext = new ClientContext(siteUrl))
{
SecureString securePassword = new SecureString();
foreach (char c in password.ToCharArray()) securePassword.AppendChar(c);
clientContext.Credentials = new NetworkCredential(userName, securePassword);
Web web = clientContext.Web;
WorkflowAssociationCollection wfAssociations = web.WorkflowAssociations;
WorkflowAssociation wfAssociation = wfAssociations.GetByName(workflowName);
clientContext.Load(wfAssociation);
clientContext.ExecuteQuery();
WorkflowServicesManager manager = new WorkflowServicesManager(clientContext, web);
InteropService workflowInteropService = manager.GetWorkflowInteropService();
clientContext.Load(workflowInteropService);
clientContext.ExecuteQuery();
workflowInteropService.StartWorkflow(wfAssociation.Name, new Guid(), Guid.Empty, Guid.Empty, null);
clientContext.ExecuteQuery(
}
The code below for your reference:
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.WorkflowServices;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Text;
using System.Threading.Tasks;
namespace CSOMStartWorkflow {
class Program {
static void Main(string[] args) {
Console.WriteLine("Enter the Office 365 Login Name");
string loginId = Console.ReadLine();
string pwd = GetInput("Password", true);
Console.WriteLine("Web Url:");
string webUrl = Console.ReadLine();
Console.WriteLine("List Name:");
string listName = Console.ReadLine();
Console.WriteLine("Workflow Name");
string workflowName = Console.ReadLine();
var passWord = new SecureString();
foreach (char c in pwd.ToCharArray()) passWord.AppendChar(c);
using (var ctx = new ClientContext(webUrl)) {
ctx.Credentials = new SharePointOnlineCredentials(loginId, passWord);
var workflowServicesManager = new WorkflowServicesManager(ctx, ctx.Web);
var workflowInteropService = workflowServicesManager.GetWorkflowInteropService();
var workflowSubscriptionService = workflowServicesManager.GetWorkflowSubscriptionService();
var workflowDeploymentService = workflowServicesManager.GetWorkflowDeploymentService();
var workflowInstanceService = workflowServicesManager.GetWorkflowInstanceService();
var publishedWorkflowDefinitions = workflowDeploymentService.EnumerateDefinitions(true);
ctx.Load(publishedWorkflowDefinitions);
ctx.ExecuteQuery();
var def = from defs in publishedWorkflowDefinitions
where defs.DisplayName == workflowName
select defs;
WorkflowDefinition workflow = def.FirstOrDefault();
if(workflow != null) {
// get all workflow associations
var workflowAssociations = workflowSubscriptionService.EnumerateSubscriptionsByDefinition(workflow.Id);
ctx.Load(workflowAssociations);
ctx.ExecuteQuery();
// find the first association
var firstWorkflowAssociation = workflowAssociations.First();
// start the workflow
var startParameters = new Dictionary<string, object>();
if (ctx.Web.ListExists(listName)) {
List list = ctx.Web.GetListByTitle(listName);
CamlQuery query = CamlQuery.CreateAllItemsQuery();
ListItemCollection items = list.GetItems(query);
// Retrieve all items in the ListItemCollection from List.GetItems(Query).
ctx.Load(items);
ctx.ExecuteQuery();
foreach (ListItem listItem in items) {
Console.WriteLine("Starting workflow for item: " + listItem.Id);
workflowInstanceService.StartWorkflowOnListItem(firstWorkflowAssociation, listItem.Id, startParameters);
ctx.ExecuteQuery();
}
}
}
}
Console.WriteLine("Press any key to close....");
Console.ReadKey();
}
private static string GetInput(string label, bool isPassword) {
Console.ForegroundColor = ConsoleColor.White;
Console.Write("{0} : ", label);
Console.ForegroundColor = ConsoleColor.Gray;
string strPwd = "";
for (ConsoleKeyInfo keyInfo = Console.ReadKey(true); keyInfo.Key != ConsoleKey.Enter; keyInfo = Console.ReadKey(true)) {
if (keyInfo.Key == ConsoleKey.Backspace) {
if (strPwd.Length > 0) {
strPwd = strPwd.Remove(strPwd.Length - 1);
Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
Console.Write(" ");
Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
}
} else if (keyInfo.Key != ConsoleKey.Enter) {
if (isPassword) {
Console.Write("*");
} else {
Console.Write(keyInfo.KeyChar);
}
strPwd += keyInfo.KeyChar;
}
}
Console.WriteLine("");
return strPwd;
}
}
}
Reference: Starting a SharePoint Online Workflow with the Client Side Object Model (CSOM)

ListViewWebPart

I'm using listviewwebpart to display contents of SPFolder (subfolder inside a list) to display its contents.
Beolw is the code to implement the same :
protected override void CreateChildControls()
{
try
{
base.CreateChildControls();
webPart = new ListViewWebPart();
using (var site = new SPSite(SPContext.Current.Web.Url))
using (var web = site.OpenWeb())
{
clientName = DataLogic.Client.GetClientName(Constants.Session.Client_ClientID);
var library = web.Lists["Account"];
webPart.ListName = library.ID.ToString("B").ToUpper();
webPart.ListId = library.ID;
SPFolder folder = web.GetFolder("/Account/" + clientName);
if (folder.Item != null)
{
SPContentTypeId folderctid = folder.Item.ContentType.Id;
//set the folder url
SetPrivateFieldValue(webPart, "rootFolder", folder.Url);
SetPrivateFieldValue(webPart, "folderCtId", folderctid.ToString());
webPart.ListViewXml = library.DefaultView.GetViewXml();
webPart.ChromeType = PartChromeType.None;
this.mainSec.Controls.Add(webPart);
}
else
{
lblWarning.Text = "There is no document library associated with client " + clientName;
}
}
}
catch (Exception ex)
{
}
}
private static void SetPrivateFieldValue(object obj, string fieldName, string val)
{
FieldInfo fi = obj.GetType().GetField(fieldName, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
fi.SetValue(obj, val);
}
The contents display correctly but the toolbar is the parent list's toolbar and not the folder's toolbar.
How can i modify the toolbar context to load the context of the spfolder?

C# create configuration file

This code How can I create configuration file if so that i can change connection string easy
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MySql.Data.MySqlClient;
using System.Web;
using mshtml;
namespace tabcontrolweb
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string MyConString = "SERVER=192.168.0.78;" +
"DATABASE=webboard;" +
"UID=aimja;" +
"PASSWORD=aimjawork;" +
"charset=utf8;";
MySqlConnection connection = new MySqlConnection(MyConString);
MySqlCommand command = connection.CreateCommand();
MySqlDataReader Reader;
command.CommandText = "SELECT urlwebboard FROM `listweb` WHERE `urlwebboard` IS NOT NULL AND ( `webbordkind` = 'เว็บท้องถิ่น' ) and `nourl`= 'n' order by province, amphore limit 4 ";
connection.Open();
Reader = command.ExecuteReader();
string[] urls = new string[4];
string thisrow = "";
string sumthisrow = "";
while (Reader.Read())
{
thisrow = "";
for (int i = 0; i < Reader.FieldCount; i++)
{
thisrow += Reader.GetValue(i).ToString();
System.IO.File.AppendAllText(#"C:\file.txt", thisrow + " " + Environment.NewLine);
sumthisrow = Reader.GetValue(Reader.FieldCount - 1).ToString();
}
for (int m = 0; m < 4 ; m++)
{
urls[m] = sumthisrow;
MessageBox.Show(urls[m]);
}
webBrowser1.Navigate(new Uri(urls[0]));
webBrowser1.Dock = DockStyle.Fill;
webBrowser2.Navigate(new Uri(urls[1]));
webBrowser2.Dock = DockStyle.Fill;
webBrowser3.Navigate(new Uri(urls[2]));
webBrowser3.Dock = DockStyle.Fill;
webBrowser4.Navigate(new Uri(urls[3]));
webBrowser4.Dock = DockStyle.Fill;
}
connection.Close();
}
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//if (webBrowser1.Document != null)
//{
// IHTMLDocument2 document = webBrowser1.Document.DomDocument as IHTMLDocument2;
// if (document != null)
// {
// IHTMLSelectionObject currentSelection = document.selection;
// IHTMLTxtRange range = currentSelection.createRange() as IHTMLTxtRange;
// if (range != null)
// {
// const String search = "We";
// if (range.findText(search, search.Length, 2))
// {
// range.select();
// }
// }
// }
//}
}
}
}
You can create an XML configuration file looking like this :
<db-config>
<server>192.168.0.78</server>
<database>webboard</database>
<...>...</...>
</db-config>
Then, use XMLTextReader to parse it.
Here is a basic example of how you can use it to parse XML files :
using System;
using System.Xml;
namespace ReadXMLfromFile
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
static void Main(string[] args)
{
XmlTextReader reader = new XmlTextReader ("books.xml");
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element: // The node is an element.
Console.Write("<" + reader.Name);
Console.WriteLine(">");
break;
case XmlNodeType.Text: //Display the text in each element.
Console.WriteLine (reader.Value);
break;
case XmlNodeType.EndElement: //Display the end of the element.
Console.Write("</" + reader.Name);
Console.WriteLine(">");
break;
}
}
Console.ReadLine();
}
}
}
Hint : Use the ReadTofollowing() to get your values.
Once your XML DB Config Reader class is done, you use it each time you need a new connection, and you'll only need to change your DB Config XML file to change your DB Connections configuration.
Edit : there is an interesting article about Storing database connection settings in .NET here.
Use the default
System.Configuration.ConfigurationManager
that C# supports!
See: http://msdn.microsoft.com/en-us/library/bb397750.aspx

Sharepoint 2010 custom webpart paging

I am trying to implement simple paging on my sharepoint webpart. I have a single news articles list which has some simple columns. I want to be able to have then five on a page and with some numerical paging at the bottom. I have gone through the net trying to understand splistitemcollectionposition but with no luck. If anyone can help please can you give me a simple code example or some guidanc
Many thanks
Chris
I would suggest using SPDataSource and a SPGridView, together they will implement paging and many other cool features with minimal or no code.
Use this a a guide for some of the classes/methods/properties you might need to use to get paging to work. Be aware that this code does not compile, i have just pulled together various code snippets that i have in my own list results framework, which includes paging, sorting, grouping and caching. It should be enough to get you started though.
public class PagedListResults : System.Web.UI.WebControls.WebParts.WebPart {
protected SPPagedGridView oGrid;
protected override void CreateChildControls() {
this.oGrid = new SPPagedGridView();
oGrid.AllowPaging = true;
oGrid.PageIndexChanging += new GridViewPageEventHandler(oGrid_PageIndexChanging);
oGrid.PagerTemplate = null; // Must be called after Controls.Add(oGrid)
oGrid.PagerSettings.Mode = PagerButtons.NumericFirstLast;
oGrid.PagerSettings.PageButtonCount = 3;
oGrid.PagerSettings.Position = PagerPosition.TopAndBottom;
base.CreateChildControls();
}
public override void DataBind() {
base.DataBind();
SPQuery q = new SPQuery();
q.RowLimit = (uint)info.PageSize;
if (!string.IsNullOrEmpty(info.PagingInfoData)) {
SPListItemCollectionPosition pos = new SPListItemCollectionPosition(info.PagingInfoData);
q.ListItemCollectionPosition = pos;
} else {
//1st page, dont need a position, and using a position breaks things
}
q.Query = info.Caml;
SPListItemCollection items = SPContext.Current.List.GetItems(q);
FilterInfo info = null;
string tmp = "<View></View>";
tmp = tmp.Replace("<View><Query>", string.Empty);
tmp = tmp.Replace("</Query></View>", string.Empty);
info.Caml = tmp;
info.PagingInfoData = string.Empty;
info.CurrentPage = oGrid.CurrentPageIndex;
info.PageSize = oGrid.PageSize;
if (oGrid.PageIndex == 0 || oGrid.CurrentPageIndex == 0) {
//do nothing
} else {
StringBuilder value = new StringBuilder();
value.Append("Paged=TRUE");
value.AppendFormat("&p_ID={0}", ViewState[KEY_PagingPrefix + "ID:" + oGrid.PageIndex]);
info.PagingInfoData = value.ToString();
}
int pagecount = (int)Math.Ceiling(items.Count / (double)oGrid.PageSize);
for (int i = 1; i < pagecount; i++) { //not always ascending index numbers
ResultItem item = items[(i * oGrid.PageSize) - 1];
ViewState[KEY_PagingPrefix + "ID:" + i] = item.ID;
}
oGrid.VirtualCount = items.Count;
DateTime time3 = DateTime.Now;
DataTable table = new DataTable("Data");
DataBindListData(table, items);
this.oGrid.DataSource = table;
this.oGrid.DataBind();
this.oGrid.PageIndex = oGrid.CurrentPageIndex; //need to reset this after DataBind
}
void oGrid_PageIndexChanging(object sender, GridViewPageEventArgs e) {
oGrid.PageIndex = e.NewPageIndex;
oGrid.CurrentPageIndex = oGrid.PageIndex;
}
}
public class FilterInfo {
public string Caml;
public string PagingInfoData;
public int CurrentPage;
public int PageSize;
}
public class SPPagedGridView : SPGridView {
protected override void InitializePager(GridViewRow row, int columnSpan, PagedDataSource pagedDataSource) {
pagedDataSource.AllowCustomPaging = true;
pagedDataSource.VirtualCount = virtualcount;
pagedDataSource.CurrentPageIndex = currentpageindex;
base.InitializePager(row, columnSpan, pagedDataSource);
}
private int virtualcount = 0;
public int VirtualCount {
get { return virtualcount; }
set { virtualcount = value; }
}
private int currentpageindex = 0;
public int CurrentPageIndex {
get { return currentpageindex; }
set { currentpageindex = value; }
}
}
check out my post on how to page using SPListItemCollectionPosition, I did a component to page over lists, maybe it can help -> http://hveiras.wordpress.com/2011/11/07/listpagert-using-splistitemcollectionposition/

Generating unique random string in SharePoint document library

I'm working on customizing a SharePoint document library called "Quality Documents" so that when new docs are added to the library, a random and unique number is generated and applied to a field named "Document Number". I coded the feature below, but it's not working. Can anyone see what might be the problem? Nothing happens, no errors nothing, the page just works fine, but no Document Number gets generated. Any suggestions?
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.Office.Server;
using Microsoft.Office.Server.UserProfiles;
namespace QualityDocHandler
{
class DocumentHandler : SPItemEventReceiver
{
/// <summary>
/// Generates a random string with the given length
/// </summary>
/// <param name="size">Size of the string</param>
/// <returns>Random string</returns>
private string RandomString(int size)
{
StringBuilder builder = new StringBuilder();
Random random = new Random();
char ch;
for (int i = 0; i < size; i++)
{
ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
builder.Append(ch);
}
return builder.ToString();
}
private string createDocNum(SPItemEventProperties properties)
{
int newRnd = 0;
do
{
// set static department
string dept = "QUA";
// set date without separators
string dateString = DateTime.Today.ToString("ddMMyyyy");
// get 1st random string
string Rand1 = RandomString(4);
// get 1st random string
string Rand2 = RandomString(4);
// creat full document number
string docNum = dept + "-" + dateString + "-" + Rand1 + "-" + Rand2;
using (SPWeb oWeb = new SPSite(properties.SiteId).OpenWeb(properties.RelativeWebUrl))
{
SPList oList = oWeb.Lists["Quality Documents"];
//create query
SPQuery oQuery = new SPQuery();
//configure the query //
oQuery.Query = "<Where><Eq><FieldRef Name='Document_x0020_Number' /><Value Type='Text'>" + docNum + "</Value></Eq></Where>";
//get the collection of items in the list
SPListItemCollection oItems = oList.GetItems(oQuery);
if (oItems.Count > 0)
{
newRnd = 0;
}
else
{
newRnd = 1;
}
}
return docNum;
}
while (newRnd < 1);
}
public override void ItemAdded(SPItemEventProperties properties)
{
base.ItemAdded(properties);
}
public override void ItemAdding(SPItemEventProperties properties)
{
string documentNum = createDocNum(properties);
using (SPWeb oWeb = new SPSite(properties.SiteId).OpenWeb(properties.RelativeWebUrl))
{
SPListItem listItem = properties.ListItem;
properties.AfterProperties["Document_x0020_Number"] = documentNum;
listItem.Update();
oWeb.Update();
}
base.ItemAdding(properties);
}
public override void ItemUpdated(SPItemEventProperties properties)
{
base.ItemUpdated(properties);
}
public override void ItemUpdating(SPItemEventProperties properties)
{
base.ItemUpdating(properties);
}
}
}
A few things:
You don't need to get a reference to listItem and use listItem.Update(). Just setting the AfterProperties should be enough.
Prevent the same event from firing multiple times by wrapping your ItemAdding method code with:
this.DisableEventFiring();
try
{
// ...
}
finally
{
this.EnableEventFiring();
}
Run SPDisposeCheck over your code. You might have a memory leak on the SPSite object with new SPSite().OpenWeb().
Have a read of Workarounds for ItemAdding/ItemAdded Event Handlers. I've never had to do this but using the display name instead of internal name may fix the problem.
In case of desperation, use ItemAdded() instead. Get a full reference to the original item and update that.
listItem.Update(); probably throws a NullReferenceException, you can see the error message in the SharePoint log (or by attaching to w3wp), but errors from event receivers will not show up to the end user. They just cancel the event.
Besides, you don’t have to call Update on the list item or the web in ItemAdding. And when you’re creating a SPWeb for the current web in an event receiver you could use SPItemEventProperties.OpenWeb() instead. It saves you the "new SPSite()" call, which you actually forget to dispose in the above code. This could lead to problems if you’re having a medium to high load on your site. SPDisposeCheck is a good tool which could be used to find such issues.
I was able to get this working. Here's the finished code:
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.Office.Server;
using Microsoft.Office.Server.UserProfiles;
namespace QualityDocHandler
{
class DocumentHandler : SPItemEventReceiver
{
private readonly Random _rng = new Random();
private const string _chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private string RandomString(int size)
{
char[] buffer = new char[size];
for (int i = 0; i < size; i++)
{
buffer[i] = _chars[_rng.Next(_chars.Length)];
}
return new string(buffer);
}
private string createDocNum(SPItemEventProperties properties)
{
int newRnd = 0;
do
{
// set static department
string dept = "QUA";
// set date without separators
string dateString = DateTime.Today.ToString("ddMMyyyy");
// get 1st random string
string Rand1 = RandomString(4);
// get 2nd random string
string Rand2 = RandomString(4);
// creat full document number
string docNum = dept + "-" + dateString + "-" + Rand1 + "-" + Rand2;
using (SPWeb oWeb = new SPSite(properties.SiteId).OpenWeb(properties.RelativeWebUrl))
{
SPSiteDataQuery q = new SPSiteDataQuery();
q.Lists = "<Lists BaseType='1'/>";
q.Query = "<Where><Eq><FieldRef Name='Document_x0020_Number' /><Value Type='Text'>" + docNum + "</Value></Eq></Where>";
q.Webs = "<Webs Scope='SiteCollection' />";
q.RowLimit = 1;
System.Data.DataTable spSiteDataQueryResults = oWeb.GetSiteData(q);
if (spSiteDataQueryResults.Rows.Count > 0)
{
newRnd = 0;
}
else
{
newRnd = 1;
}
}
return docNum;
}
while (newRnd < 1);
}
public override void ItemAdded(SPItemEventProperties properties)
{
this.DisableEventFiring();
properties.ListItem["Document Number"] = properties.AfterProperties["Document Number"];
properties.ListItem.SystemUpdate();
this.EnableEventFiring();
}
public override void ItemAdding(SPItemEventProperties properties)
{
string documentNum = createDocNum(properties);
this.DisableEventFiring();
properties.AfterProperties["Document Number"] = documentNum;
this.EnableEventFiring();
}
public override void ItemUpdated(SPItemEventProperties properties)
{
base.ItemUpdated(properties);
}
public override void ItemUpdating(SPItemEventProperties properties)
{
base.ItemUpdating(properties);
}
}
}

Resources