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, так и развёрнутые аналитические посты "чего и по чём" а так же "за чем"
Можно притвориться американской компанией и попробовать триальную версию ....

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

Monday, January 19, 2009

Exam 072-541 TS: Microsoft Windows SharePoint Services 3.0 – Application Development

Добавил к сданному на 945 балов экзамену 072-630 (бывший 070-630 TS: Microsoft Office SharePoint Server 2007, Configuring)

Ещё одну сертификацию а именно Exam 072-541 (бывший 070-541 TS: Microsoft Windows SharePoint Services 3.0 – Application Development)

Экзамен оказался сложнее чем 072-630, если на предыдущий я потратил 30 минут то это сдавал около 2х часов.
Microsoft молодцы обновили вопросы и из тех что всюду в сети лежат их дампы мне не попался ни один (хотя может я и не заметил я ен сильно вникал в них).
Итог 857 балов за 072-541

Windows Server 2008 + MOSS 2007 + VS 2008 + VSeWSS 1.3

Установил Windows Server 2008 + MOSS 2007 + VS 2008 + VSeWSS 1.3
Начал пользоваться, на первый взгляд всё очень классно и проделано кучу работы, успешно скомпилировал и создал вэб часть буквально за минут 5.
Успешно собрал её в пакет решения с фичей которая добавляет вэб часть, пернёс на сервер и запустив батник установил всё. Но не вышло запустить дэбаг, вобщем самое основное что хотелось бы иметь.
Пытаюсь автоматически задеплоить или включить дэбаг
вылазит ошибка Access Denided на дэполе
"------ Build started: Project: SimpleWepart, Configuration: Debug Any CPU ------
SimpleWepart -> C:\Projects\Sharepoint\SimpleWepart\SimpleWepart\SimpleWepart\bin\Debug\SimpleWepart.dll
------ Deploy started: Project: SimpleWepart, Configuration: Debug Any CPU ------
------ Validate solution and resolve deployment conflict(s) ------
Validating solution ...
Operation completed successfully.
------ Generate solution file and setup batch file ------
Creating solution ...
Operation completed successfully.
Creating setup batch file ...
Operation completed successfully.
------ Add and deploy the solution to SharePoint ------
Adding solution SimpleWepart ...
Operation completed successfully.
Deploying solution SimpleWepart ...
System.Exception
Server Error: Access denied.
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========
========== Deploy: 0 succeeded, 1 failed, 0 skipped ==========
"

Написал на форум подержки, решение придложенно не было.
Вообщем вывод что прелестей от пользования Windows Server 2008 я не получил а вот гемороя с секюрити, установкой шарпоинта апдейтами и тормазами сколько угодно...
Переустанавливаю всё на сервер Windows 2003. Отчёт как тольок так сразу :)

Wednesday, January 14, 2009

Visual Studio 2008 extensions for SharePoint v1.3

Пока SharePoint разработчики с нетерпением ждут VS 2010 где реализована полноценная поддержка WSS, The Community Technology Preview (CTP) выпустила расширение для VS 2008 которое должно облегчить разработку, сборку, загрузку на сервер, дэбаг стандартных компонент для SP таких как Web Parts, Data Lists, Content Types, Event Receivers, Templates, Module...
С основным постом можно ознакомиться тут: http://blogs.msdn.com/sharepoint/archive/2009/01/12/announcing-community-technology-preview-of-visual-studio-2008-extensions-for-sharepoint-v1-3.aspx
Скачать релиз можно тут: https://connect.microsoft.com/Downloads/Downloads.aspx?SiteID=428

Я сейчас как раз устанавливаю этот инструмент на 2008й сервер, обещаю отчёт в следующем посте.