Friday, February 20, 2009

WebPart for adding Item To Bug List.

Хочу выложить код, в своё время с котором немного намучился из за каламбура со связанными списками.
Задача стояла такая: Есть список для логирования багов, самой форме слишком много полей которые не всегда есть время заполнять, а хочется в момент ввести данные и отправить их. Потому предстояло сделать вэб часть, в которую можно было бы ввести данные и добавить новый элемент.
Код:



using System;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;

namespace ELEKS.SharePoint.WebParts
{
[Guid("28ce955d-63e9-4681-b02c-d0583a25e0e3")]
public class QuickBugLog : System.Web.UI.WebControls.WebParts.WebPart
{
private Microsoft.SharePoint.SPWeb web = null;
private Microsoft.SharePoint.SPList bugsList = null;
private Microsoft.SharePoint.SPList projectsList = null;

protected TextBox txtBugTitle;
protected TextBox txtReproSteps;
protected DropDownList ddlProject;
protected Label lblValidationError;
protected Button btnBugLog;



public QuickBugLog()
{
}

protected override void CreateChildControls()
{
try
{

//initialize label
lblValidationError = new Label();
lblValidationError.CssClass = "ms-formvalidation";
Controls.Add(lblValidationError);

//initialize textboxes
txtBugTitle = new TextBox();
txtReproSteps = new TextBox();
txtReproSteps.TextMode = TextBoxMode.MultiLine;
txtReproSteps.Columns = 40;
txtReproSteps.Rows = 8;
Controls.Add(txtReproSteps);
Controls.Add(txtBugTitle);

//initialize button
btnBugLog = new Button();
btnBugLog.Text = "Log Bug";
btnBugLog.Click += new EventHandler(btnBugLog_Click);
Controls.Add(btnBugLog);

//initialize comboboxes
ddlProject = new DropDownList();
Controls.Add(ddlProject);

}
catch
{
this.lblValidationError.Text += "Error 1 : Can't Initialize controls.";
}



try
{
//get the web
this.web = Microsoft.SharePoint.SPContext.Current.Web;
web.AllowUnsafeUpdates = true;
//get the bugsheet list
this.bugsList = Microsoft.SharePoint.SPContext.Current.Web.Lists["Bugs"];
//get the projects list
this.projectsList = Microsoft.SharePoint.SPContext.Current.Web.GetList(web.ServerRelativeUrl + "/Lists/Projects/");

}
catch
{
this.lblValidationError.Text += "Error 0 : Can't connect to the curent context.";

}
try
{
//write CALM query for filtering data in list, to display active projects
string strCalmQuery =
"<Query>" +
"<OrderBy>" +
"<FieldRef Name='Title' />" +
"</OrderBy>" +
"<Where>" +
"<Geq>" +
"<FieldRef Name='EndDate' />" +
"<Value Type='DateTime'>" + System.DateTime.Today.ToString("yyyy/MM/dd HH:mm:ss") + "</Value>" +
"</Geq>" +
"</Where>" +
"</Query>";
SPQuery query = new SPQuery();
query.Query = strCalmQuery;
//Filter Project list Using CALM query
SPListItemCollection filteredItems = this.projectsList.GetItems(query);
if (filteredItems.Count != 0)
{
foreach (SPListItem item in filteredItems)
{
ListItem li = new ListItem(item.DisplayName.ToString());
ddlProject.Items.Add(li);
}
}
else
{
this.lblValidationError.Text = "Projects List is empty.";
}
}
catch
{
this.lblValidationError.Text += "Error 2 : Can't Filter Data With this CALM query.";
}


}
protected override void Render(System.Web.UI.HtmlTextWriter writer)

{


try
{
writer.Write("<table width=100%>");
writer.Write("<tr>");
writer.Write("<td colspan=2>");
lblValidationError.RenderControl(writer);
writer.Write("</td>");
writer.Write("</tr>");
writer.Write("<tr>");
writer.Write("<td>Bug Name:<span class=’ms-formvalidation’>*</span></td>");
writer.Write("<td>");
txtBugTitle.RenderControl(writer);
writer.Write("</td>");
writer.Write("</tr>");
writer.Write("<tr>");
writer.Write("<td>Project:<span class=’ms-formvalidation’>*</span></td>");
writer.Write("<td>");
ddlProject.RenderControl(writer);
writer.Write("</td>");
writer.Write("</tr>");
writer.Write("<tr>");
writer.Write("<td>Repro Steps: <span class=’ms-formvalidation’>*</span></td>");
writer.Write("<td>");
txtReproSteps.RenderControl(writer);
writer.Write("</td>");
writer.Write("</tr>");
writer.Write("<tr>");
writer.Write("<td></td>");
writer.Write("<td>");
writer.Write("</td>");
writer.Write("</tr>");
writer.Write("<tr>");
writer.Write("<td></td>");
writer.Write("<td>");
writer.Write("</td>");
writer.Write("</tr>");
writer.Write("<tr>");
writer.Write("<td>");
writer.Write("</td>");
writer.Write("<td>");
btnBugLog.RenderControl(writer);
writer.Write("</td>");
writer.Write("</tr>");
writer.Write("</table>");
}
catch
{
this.lblValidationError.Text += "Error 3 : Can't Render controls.";
}
}


public void btnBugLog_Click(object sender, EventArgs e)
{
try
{
string strCalmQuery_ProjectSelected =
"<Query>" +
"<Where>" +
"<Geq>" +
"<FieldRef Name='Title' />" +
"<Value Type='Text'>" + ddlProject.SelectedItem.Text.ToString() + "</Value>" +
"</Geq>" +
"</Where>" +
"</Query>";
SPQuery query_ProjectSelected = new SPQuery();
query_ProjectSelected.Query = strCalmQuery_ProjectSelected;
int ProjectSelected_id = 0;
//Filter Project list Using CALM query
SPListItemCollection filteredItems = this.projectsList.GetItems(query_ProjectSelected);
if (filteredItems.Count != 0)
{
ProjectSelected_id = filteredItems[0].ID;
}

if ((txtBugTitle.Text.ToString() != "") & (txtReproSteps.Text.ToString()!=""))
{

SPListItem item = this.bugsList.Items.Add();
item["Title"] = txtBugTitle.Text.ToString();
item["Repro Steps"] = txtReproSteps.Text.ToString();
item["Assigned To"] = "";
item["Resolved By"] = "";
item["Resolution"] = "";
item["Status"] = 2;
item["Priority"] = 2;
item["Fix By"] = "";
item["Project"] = new SPFieldLookupValue(ProjectSelected_id, ddlProject.SelectedItem.Text.ToString());
item["Category"] = 2;
item["Comments"] = "";
item["Created By"] = "";
item.Update();
this.lblValidationError.Text = "Bug: " + item.Title.ToString() + " loged at: " + System.DateTime.Today.ToString("yyyy/MM/dd HH:mm:ss");
txtBugTitle.Text = "";
txtReproSteps.Text = "";
}
else
{
this.lblValidationError.Text = "Fill in all fields to log a bug.";
}
}
catch
{
this.lblValidationError.Text += "Error 4 : Can't add Item to the bug list.";
}
}

}
}

Thursday, February 19, 2009

Running SharePoint on Windows 7

Устал от тормозов на виртуальной машине с Windows Server 2008+ VS2008 + MOSS 2007 + VSeWSS...
Установил себе на ноутбук Windows 7 далее используя tool созданный by Bamboo Solutions установил Windows SharePoint Services 3.0 SP1 предварительно установив SQL Server 2008 Express.
На это всё установил VS 2008 и вуаля...







И помните что для полного "администрирования сервера" в центральной панели нужно браузер запускать как администратор.
VSeWSS 1.3 установится только если инсталяцию запустить с правами администратора.

"Event Receiver" для "Project Tasks"

Нашёл отличную статью по созданию "Event Receiver"
При помощи (VS2005 или VS2008) + VSeWSS (да, да, да.. .я всётаки это сделал и настроил работу с этим расширением :) подробный отчёт в процессе написания.)

В конце статьи ссылка на просто незаменимую тулзу облегчающую жизнь при деплое:
EventReceiver-Installer for SharePoint
После написания библиотеки "Event Receiver" с нужной нам функциональность нам останется её подписать, добавить в GAC и потом используя EventReceiver-Installer for SharePoint добавить перехватчик событий в нужный нам список.


Небольшая путаница возникает при использование свойств ( properties.BeforeProperties и properties.AfterProperties ) которые как оказалось предназначены только для библиотек документов и в других случаях возвращают "null", потому к значениям нового элемента списка доступимся так:

SPListItemcurrentListItem = properties.ListItem;
string befor = currentListItem["Status"].ToString();

Ещё один важный момент, если мы перехватываем событие на изменение, нужно
отключить перехватчик событий внутри функции а затем включить, дабы избежать зацикливания.

this.DisableEventFiring();
// Тут используемый код.
this.EnableEventFiring();

Мой класс для перехватчиков событий в итоге выглядит так:

using System;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Security;
using VSeWSS;

namespace ELEKS.EventReciver.List.ItemChanged
{
[CLSCompliant(false)]
[TargetList("00bfea71-513d-4ca0-96c2-6a47775c0119")]
[Guid("941095ba-e685-4cc5-8b59-b06bb87e53cf")]
public class FreezeOnCompletItemEventReceiver : SPItemEventReceiver
{
/// <summary>
/// Initializes a new instance of the Microsoft.SharePoint.SPItemEventReceiver class.
/// </summary>
public FreezeOnCompletItemEventReceiver()
{
}
private SPUser GetUser(SPListItem item, SPField userField)
{
string currentValue = item[userField.Title].ToString();
SPFieldUser field = (SPFieldUser)userField;
SPFieldUserValue fieldValue =
(SPFieldUserValue)field.GetFieldValue(currentValue);
return fieldValue.User;

}
private SPUser GetUser(SPWeb web,string userName)
{
SPUserCollection users = web.SiteUsers;
SPUser user = users[userName];
return user;
}


public override void ItemDeleted(SPItemEventProperties properties)
{
string currentDate = DateTime.Today.ToShortDateString();
using (SPWeb web = properties.OpenWeb())
{
try
{
string authormail = GetUser(properties.ListItem, properties.ListItem.Fields.GetField("Author")).Email;
string masage = "Your task: " + properties.ListItem.Title.ToString() + " Deleted by " +properties.UserLoginName + "on Date:" + currentDate;
string title = "Task: " +properties.ListItem.Title.ToString() + " Deleted." ;
SPUtility.SendEmail(web, false, false, authormail, title, masage);
}
catch (Exception)
{
properties.ErrorMessage ="Error on Sending Email Aftre Deleted an Item";
}
}

}

public override void ItemDeleting(SPItemEventProperties properties)
{
SPWeb currentWeb = properties.OpenWeb();
SPUser currentUser = GetUser(currentWeb, properties.UserLoginName);
SPUser createdByUser = GetUser(properties.ListItem, properties.ListItem.Fields.GetField("Author"));
if ((properties.UserLoginName != createdByUser.LoginName) | (!(currentUser.IsSiteAdmin)))
{
properties.Cancel = true;
properties.ErrorMessage = "Deleting of Items not allowed!";
}
}


public override void ItemUpdating(SPItemEventProperties properties)
{
SPWeb currentWeb = properties.OpenWeb();
SPUser currentUser = GetUser(currentWeb, properties.UserLoginName);
SPUser createdByUser = GetUser(properties.ListItem, properties.ListItem.Fields.GetField("Author"));
bool curentUserIsSiteAdmin = currentUser.IsSiteAdmin;
SPListItem currentListItem = properties.ListItem;
string befor = currentListItem["Status"].ToString();
bool answer = (properties.UserLoginName != createdByUser.LoginName) | ((!(curentUserIsSiteAdmin)) & (befor == "Completed") & (properties.UserLoginName != createdByUser.LoginName)) | (!(curentUserIsSiteAdmin));


if (answer)
{
this.DisableEventFiring();
properties.Cancel = true;
properties.ErrorMessage = "Editing of 'Completed' Item is not allowed for you!";
this.EnableEventFiring();
}


}
}
}

Thursday, February 5, 2009

Microsoft SharePoint Online Standard Developer Guide

Пока все наблюдают как за осторожным перешёптыванием в округ выхода SharePoint Online, так и развёрнутые аналитические посты "чего и по чём" а так же "за чем"
Можно притвориться американской компанией и попробовать триальную версию ....

А в это время почитать документацию по разработке под этот сервис...
для разработчиков.....