Archive Page 2

28
May
09

#24 Small Employee Directory SP Web Part

Employee Directory for Sharepoint Column

Employee Directory for Sharepoint Column

This web part exposes props for an advance search URL, results table width and max record count. The results are displayed via bind to an ASP.Net Repeater.

properties exposed in Sharepoint

properties exposed in Sharepoint

Credit Due for dynamic template code

BWEmpDirSmall.cs

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
//add
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
using System.Data.Common;
using System.Web.Configuration;
using System.Data.SqlTypes;
using System.Xml.Serialization;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint;
using System.IO;

namespace BWEmpDirSmall
{
    [Guid("60c0ce25-603a-4c24-8d99-8b6046f013fe")]
    public class BWEmployeeSearch2 : Microsoft.SharePoint.WebPartPages.WebPart
    {
        private bool _error = false;

        private Label lblMessage;
        private TextBox txtSearch;
        private Button btnSearch;
        private Button btnClear;
        private Repeater rptList;
        private HyperLink hlAdvSearch;

        [Personalizable(PersonalizationScope.Shared)]
        [WebBrowsable(true)]
        [System.ComponentModel.Category("My Property Group")]
        [WebDisplayName("Advance Search Page")]
        [WebDescription("URL to Advance Search")]
        public string AdvSearchURL { get; set; }

        [Personalizable(PersonalizationScope.Shared)]
        [WebBrowsable(true)]
        [System.ComponentModel.Category("My Property Group")]
        [WebDisplayName("Table Width")]
        [WebDescription("Filter & Results Table Width")]
        public string TableWidth { get; set; }

        [Personalizable(PersonalizationScope.Shared)]
        [WebBrowsable(true)]
        [System.ComponentModel.Category("My Property Group")]
        [WebDisplayName("Max Count")]
        [WebDescription("Maximum Rows Returned")]
        public string MaxCount { get; set; }
        public BWEmployeeSearch2()
        {
            this.ExportMode = WebPartExportMode.All;
            this.AdvSearchURL = @"<a href='http://portal'>******</a>";
            this.TableWidth = "220px";
            this.MaxCount = "25";
        }

        /// <summary>
        /// Sets Display
        /// </summary>
        /// <param name="writer"></param>
        protected override void RenderContents(HtmlTextWriter writer)
        {
            writer.Write("<table width='" + TableWidth + "' border='0' >");

            spanRow(writer, "left", "2");
            //writer.Write("<b>Search: </b>");

            txtSearch.RenderControl(writer);
            writer.Write("&nbsp;");
            btnSearch.RenderControl(writer);
            writer.Write("&nbsp;");
            btnClear.RenderControl(writer);
            rowEnd(writer);

            spanRow(writer, "left", "2");
            hlAdvSearch.RenderControl(writer);
            rowEnd(writer);

            spanRow(writer, "left", "2");
            lblMessage.RenderControl(writer);
            rowEnd(writer);

            spanRow(writer, "left", "2");
            rptList.RenderControl(writer);
            rowEnd(writer);

            writer.Write("</table>");
        }

        protected void rowStart(HtmlTextWriter writer, string sAlign) { writer.Write("<tr><td align=" + sAlign + ">"); }
        protected void cellEnd(HtmlTextWriter writer) { writer.Write("</td>"); }
        protected void cellEndStart(HtmlTextWriter writer, string sAlign) { writer.Write("</td><td align=" + sAlign + ">"); }
        protected void rowEnd(HtmlTextWriter writer) { writer.Write("</td></tr>"); }
        protected void spanRow(HtmlTextWriter writer, string sAlign, string colspan)
        {
            writer.Write("<tr><td align=" + sAlign + " colspan=" + colspan + " >");
        }

        /// <summary>
        /// Create all your controls here for rendering.
        /// Try to avoid using the RenderWebPart() method.
        /// </summary>
        protected override void CreateChildControls()
        {
            if (!_error)
            {
                try
                {

                    base.CreateChildControls();

                     lblMessage = new Label();
                    btnSearch = new Button();
                    btnClear = new Button();
                    txtSearch = new TextBox();
                    hlAdvSearch = new HyperLink();

                    this.lblMessage.Width = new Unit("200px");

                    this.btnSearch.Text = "Search";
                    this.btnSearch.Click += new EventHandler(btnSubmit_Click);
                    this.btnClear.Text = "Clear";
                    this.btnClear.Click += new EventHandler(btnClear_Click);

                    this.rptList = new Repeater();
                    this.rptList.ItemTemplate = new MyTemplate(MaxCount);

                    this.hlAdvSearch.Text = "Advance Search";
                    this.hlAdvSearch.NavigateUrl = AdvSearchURL;

                    this.Controls.Add(lblMessage);
                    this.Controls.Add(txtSearch);
                    this.Controls.Add(rptList);
                    this.Controls.Add(btnSearch);
                    this.Controls.Add(btnClear);
                    this.Controls.Add(hlAdvSearch);

                    this.lblMessage.Width = new Unit("180px");
                    this.btnSearch.Width = new Unit("60px");
                    this.btnClear.Width = new Unit("60px");
                    this.txtSearch.Width = new Unit("150px");

                }
                catch (Exception ex)
                {
                    HandleException(ex);
                }
            }
        }

        /// <summary>
        /// Ensures that the CreateChildControls() is called before events.
        /// Use CreateChildControls() to create your controls.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            if (!_error)
            {
                try
                {
                    base.OnLoad(e);
                    this.EnsureChildControls();

                    // Your code here...
                }
                catch (Exception ex)
                {
                    HandleException(ex);
                }
            }
        }

        /// <summary>
        /// Clear all child controls and add an error message for display.
        /// </summary>
        /// <param name="ex"></param>
        private void HandleException(Exception ex)
        {
            this._error = true;
            this.Controls.Clear();
            this.Controls.Add(new LiteralControl(ex.Message));
        }

        protected void btnSubmit_Click(object sender, EventArgs e)
        {

            this.rptList.ItemTemplate = new MyTemplate(MaxCount);

            if (Utilities.hasData(txtSearch))
                bindRepeater();
            else
            {
                lblMessage.Text = "No Search Criteria Entered";
                //this.rptList.DataSource = new string[] { }; //clear
                //this.rptList.DataBind();
            }

        }
        protected void btnClear_Click(object sender, EventArgs e)
        {
            txtSearch.Text = string.Empty;
            this.rptList.DataSource = new string[] { }; //clear
            this.rptList.DataBind();
            lblMessage.Text = "";
        }
        private void bindRepeater()
        {
            DataSet ds = Employee.searchEmployees(txtSearch.Text.Trim());
            this.rptList.DataSource = ds;
            this.rptList.DataBind();
            int iRecCount = 0;
            Int32.TryParse(ds.Tables[0].Rows.Count.ToString(),out iRecCount);
            if (iRecCount < (Int32.Parse(MaxCount)))
                this.lblMessage.Text = iRecCount.ToString() + " record(s) found";
            else
                this.lblMessage.Text = iRecCount.ToString() + " Recs Exceeded " + MaxCount + " Max";
        }

    }
}

MyTemplate.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace BWEmpDirSmall
{
    public class MyTemplate : ITemplate
    {

            static int itemcount = 0;
            static int MAXCOUNT = 25;
            ListItemType templateType;

            public MyTemplate()
            {
                templateType = ListItemType.Item;
                itemcount = 0;
            }

            public MyTemplate(string s)
            {
                templateType = ListItemType.Item;
                MAXCOUNT = 25;
                Int32.TryParse(s, out MAXCOUNT);
                itemcount = 0;
            }

            public MyTemplate(ListItemType type)
            {
                templateType = type;
                itemcount = 0;
            }

            public void InstantiateIn(System.Web.UI.Control container)
            {
                Literal lc = new Literal();
                //switch (templateType)
                //{
                //    case ListItemType.Header:
                //        lc.Text = "<TABLE border=1><TR><TH>Items</TH></TR>";
                //        break;
                //    case ListItemType.Item:
                //        //lc.Text = "<TR><TD>Item number: " + itemcount.ToString() +
                //        //   "</TD></TR>";
                //          lc.Text = DataBinder.Eval(Container.DataItem, "FirstName");
                //        break;
                //    case ListItemType.AlternatingItem:
                //        lc.Text = "<TR><TD bgcolor=lightblue>Item number: " +
                //           itemcount.ToString() + "</TD></TR>";
                //        break;
                //    case ListItemType.Footer:
                //        lc.Text = "</TABLE>";
                //        break;
                //}
                if (itemcount <= MAXCOUNT)
                {
                    lc.DataBinding += new EventHandler(TemplateControl_DataBinding);
                    container.Controls.Add(lc);
                }
                itemcount++;

            }

            private void TemplateControl_DataBinding(object sender, System.EventArgs e)
            {
                Literal lc;
                lc = (Literal)sender;
                RepeaterItem container = (RepeaterItem)lc.NamingContainer;
                lc.Text += "&amp;raquo; <font color='#99000'><b> ";
                lc.Text += DataBinder.Eval(container.DataItem, "FirstName");
                lc.Text += " &nbsp;" + DataBinder.Eval(container.DataItem, "LastName");
                lc.Text += "</b></font> ";
                if (Utilities.hasData(DataBinder.Eval(container.DataItem, "WorkPhoneExt").ToString()))
                    lc.Text += "<b> x/" + DataBinder.Eval(container.DataItem, "WorkPhoneExt") + "</b>";
                lc.Text += "<br />";
                if (Utilities.hasData(DataBinder.Eval(container.DataItem, "WorkPhone").ToString()))
                    lc.Text += "&nbsp;<i>" + DataBinder.Eval(container.DataItem, "WorkPhone") + "</i>&nbsp;";
                if (Utilities.hasData(DataBinder.Eval(container.DataItem, "MobilePhone").ToString()))
                    lc.Text += "<i> Cell: " + DataBinder.Eval(container.DataItem, "MobilePhone") + "</i> ";
                lc.Text += "<br /> ";
            }
    }

}

Employee cs searchEmployees method:

static public DataSet searchEmployees(string sTarget)
    {

        SqlCommand cmd = null;
        SqlDataAdapter da = null;
        DataSet ds = new DataSet("Employees");
        using (SqlConnection conn = Utilities.getConnR())
        {

            try
            {
                cmd = new SqlCommand("searchEmployees", conn);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add(new SqlParameter("@Target", SqlDbType.Text));
                cmd.Parameters["@Target"].Value = sTarget.Trim();

                conn.Open();
                da = new SqlDataAdapter(cmd);
                da.Fill(ds);

            }
            catch (Exception err)
            {
                throw new ApplicationException(err.Message.ToString());

                //err.Message.ToString();
            }
            finally
            {
                if (cmd != null) { cmd.Dispose(); }
                if (da != null) { da.Dispose(); }
            }
        }
        return ds;

    }

Stored Procedure:

Procedure [dbo].[searchEmployees]
(
  @Target  nvarchar(50)
)
as
  Select
   EM.Employee as EmpNum
 , RTRIM(EM.Employee) + '-' +  SUBSTRING(EM.FirstName,1,1)
  +  RTRIM(Case When(DATALENGTH(EM.MiddleName) = 0) Then '' Else  SUBSTRING(EM.MiddleName,1,1) End )
     +  SUBSTRING(EM.LastName,1,1)  as Employee
 , isNull(EM.PreferredName,EM.FirstName)    as FirstName
 , (RTRIM(EM.LastName) + ' ' + isNull(Suffix,''))  as LastName
 , EM.MiddleName
 , EM.Org         as PrimaryDept
 , EM.Region
 , EM.WorkPhone
 , EM.WorkPhoneExt
 , EM.MobilePhone
 , ECTF.Cust5ULPhysical      as Office
 , ECTF.custSecondaryDepartment     as SecondaryDept
  From
    EM
  Join EmployeeCustomTabFields ECTF on ( ECTF.Employee = EM.Employee )
  Where
 EM.Status = 'A'
 And (  EM.FirstName  like  Case When (@Target is null) Then '%' Else RTRIM(@Target) + '%' End
     OR EM.PreferredName   like  Case When (@Target is null) Then '%' Else RTRIM(@Target) + '%' End
     OR EM.LastName   like  Case When (@Target is null) Then '%' Else RTRIM(@Target) + '%' End
   OR    SUBSTRING(EM.FirstName,1,1)  +  RTRIM(Case When(DATALENGTH(EM.MiddleName) = 0) Then '' Else  SUBSTRING(EM.MiddleName,1,1) End )  +  SUBSTRING(EM.LastName,1,1)  like Case When (@Target is null) Then '%' Else  @Target  End
     OR EM.WorkPhone like '%' + isNull(@Target,'%') + '%'
   OR EM.WorkPhoneExt like '%' + isNull(@Target,'%') + '%'
   OR EM.MobilePhone like '%' + isNull(@Target,'%') + '%'
   OR  ECTF.Cust5ULPhysical = isNull(@Target, ECTF.Cust5ULPhysical)
   OR  EM.Employee like  isNull(@Target,'%') + '%'   )
12
May
09

#23 Installing Business Data Catalog Definition Editor – error 2869

When installing the Business Data Catalog Definition Editor which allows (makes it easy for) you to connect your data sources to the Sharepoint Business Data Catalog you can get this odd error. I was loading in Windows Server 2003 & all the posts I saw were for issues with Vista.  Hope this helps those non-Vista users suffering this issue.

My Log entry:

Event Type:    Error Event Source:    MsiInstaller Event Category:    None Event ID:    10005 Date:        Time:          PM User:        CSISERVER Description: Product: Microsoft ®  Application Definition Designer — The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is 2869.

For those that install packages a lot this may be obvious – use the setup.exe directly instead of the msi package. It will install SQL 2005 Express with the app (there are some unhappy posts on that around) but the Definition Editor installs.

If looking for the SDK here are the links:

http://blogs.msdn.com/sharepoint/archive/2007/08/22/announcing-the-microsoft-business-data-catalog-definition-editor-for-microsoft-office-sharepoint-server-2007.aspx
http://www.microsoft.com/downloads/details.aspx?familyid=6d94e307-67d9-41ac-b2d6-0074d6286fa9&displaylang=en



27
Feb
09

#22 Some Sharepoint links regarding CAML, F# & LINQ

Navigating the vast object model in SP/MOSS can be daunting -  Here are some references regarding some good unifying work:

LINQ to CAML project

Linq SPListCollection

John Lao’s Exploring SP using F# Excellent blog covering F# and SP

Free F# eBook Free is free though you have to navigate & signup for access to get the pdf

Creating a test VPC for Sharepoint/MOSS

28
Jan
09

#21 Employee Directory Sharepoint Webpart Pt 2 – Class Files

There are Data Access Layer classes for each collection Employee, Office & Department which can use ADO or the Enterprise library to call stored procedures to access data.wpempdir

EmpDir.cs

Credit Due: for GridView Paging code - Powlo’s site (Paul Robinson’s SP Site)


using System;
using System.Collections.Generic;
using System.Text;
//add
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
using System.Data.Common;
using System.Web.Configuration;
using System.Data.SqlTypes;
using System.Xml.Serialization;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint;
using System.IO;
[assembly: System.Security.AllowPartiallyTrustedCallers]

namespace EmpDir

{

public class EmpDir: WebPart

{

private Label       lblMessage;
private TextBox     txtSearchFN;
private TextBox     txtSearchLN;
private TextBox     txtSearchPhone;
private TextBox     txtSearchEmployee;
private TextBox     txtSearchInitials;
private Button      btnSearch;
private Button      btnClear;
private SPGridView  oGrid;
private DataSet     oDataset;
private DataView    oView;
private DropDownList ddDepartment;
private DropDownList ddOffice;

protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
}

protected override void RenderContents(HtmlTextWriter writer)
{

writer.Write("<table border='0'  width='600px'>");
writer.Write("<tr><td align='right' nowrap='nowrap'>Intials:</td>");
writer.Write("<td align='left' >");
txtSearchInitials.RenderControl(writer);
writer.Write("</td><td align='right'  nowrap='nowrap'>Emp#:</td>");
writer.Write("<td align='left' >");
txtSearchEmployee.RenderControl(writer);
writer.Write("</td><td></td></tr>");
writer.Write("<tr><td align='right' nowrap='nowrap'>First Name:</td>");
writer.Write("<td align='left' >");
txtSearchFN.RenderControl(writer);
writer.Write("</td><td align='right'  nowrap='nowrap'>Last Name:</td>");
writer.Write("<td align='left' >");
txtSearchLN.RenderControl(writer);
writer.Write("</td><td></td></tr>");

writer.Write("<tr><td align='right' nowrap='nowrap'>Phone:</td>");
writer.Write("<td align='left' >");
txtSearchPhone.RenderControl(writer);
writer.Write("</td><td align='right'  nowrap='nowrap'>Department:</td>");
writer.Write("<td align='left' >");
ddDepartment.RenderControl(writer);
writer.Write("</td><td></td></tr>");

writer.Write("<tr><td align='right' nowrap='nowrap'>Office:</td>");
writer.Write("<td align='left' >");
ddOffice.RenderControl(writer);
writer.Write("</td><td align='right'  nowrap='nowrap'></td>");
writer.Write("<td align='left' >");
//ddDepartment.RenderControl(writer);
writer.Write("</td><td></td></tr>");

// BUTTONS
writer.Write("<tr><td colspan='3'>");
btnSearch.RenderControl(writer);
writer.Write("&amp;nbsp;&amp;nbsp;");
btnClear.RenderControl(writer);
writer.Write("</table>");

// GRID
writer.Write("<table border='0'>");
writer.Write("</td></tr>");
writer.Write("<tr><td colspan='3'>");
oGrid.RenderControl(writer);
writer.Write("</td><td></td></tr>");
writer.Write("</table>");

}

protected override void CreateChildControls()
{
base.CreateChildControls();

lblMessage          = new Label();
btnSearch           = new Button();
btnClear            = new Button();
txtSearchFN         = new TextBox();
txtSearchLN         = new TextBox();
txtSearchPhone      = new TextBox();
txtSearchEmployee   = new TextBox();
txtSearchInitials   = new TextBox();
ddDepartment        = new DropDownList();
ddOffice            = new DropDownList();

Department.loadDepartmentDropdown(this.ddDepartment, "--- All Departments --");
Office.loadOfficeDropdown(this.ddOffice, "--- All Offices ---");

this.lblMessage.Width = new Unit("800px");
this.btnSearch.Text = "Search";
this.btnSearch.Click += new EventHandler(btnSubmit_Click);
this.btnClear.Text = "Clear";
this.btnClear.Click += new EventHandler(btnClear_Click);

this.oDataset = new DataSet();
this.oView = new DataView();
this.oGrid = new SPGridView();
this.oGrid.DataSource = oView;
this.oGrid.AutoGenerateColumns = false;
this.oGrid.AllowSorting = true;

this.oGrid.Sorting += new GridViewSortEventHandler(oGrid_Sorting);

this.oGrid.AllowPaging = true;
oGrid.Columns.Add(Utilities.buildColumn("Employee", "Emp #"));

// Add Cols using a utility method
oGrid.Columns.Add(Utilities.buildColumn("FirstName", "First Name"));
oGrid.Columns.Add(Utilities.buildColumn("LastName", "Last Name"));
oGrid.Columns.Add(Utilities.buildColumn("WorkPhone", "Direct"));
oGrid.Columns.Add(Utilities.buildColumn("WorkPhoneExt", "Ext"));
oGrid.Columns.Add(Utilities.buildColumn("MobilePhone", "Cell"));
oGrid.Columns.Add(Utilities.buildColumn("Office", "Office"));
oGrid.Columns.Add(Utilities.buildColumn("PrimaryDept", "Primary Dept"));
oGrid.Columns.Add(Utilities.buildColumn("SecondaryDept", "Secondary Dept"));

this.Controls.Add(lblMessage);
this.Controls.Add(ddDepartment);
this.Controls.Add(ddOffice);
this.Controls.Add(txtSearchFN);
this.Controls.Add(txtSearchLN);
this.Controls.Add(txtSearchEmployee);
this.Controls.Add(txtSearchInitials);
this.Controls.Add(txtSearchPhone);
this.Controls.Add(btnSearch);
this.Controls.Add(btnClear);
this.Controls.Add(oGrid);

this.oGrid.PageSize = 10;
this.oGrid.AllowPaging = true;

this.oGrid.PageIndexChanging += new GridViewPageEventHandler(oGrid_PageIndexChanging);

this.oGrid.PagerTemplate = null;  // Must be called after Controls.Add(oGrid)

this.lblMessage.Width = new Unit("400px");
this.ddDepartment.Width = new Unit("180px");
this.ddOffice.Width = new Unit("180px");
this.btnSearch.Width = new Unit("80px");
this.btnClear.Width = new Unit("80px");
this.txtSearchFN.Width = new Unit("180px");
this.txtSearchLN.Width = new Unit("180px");
this.txtSearchEmployee.Width = new Unit("180px");
this.txtSearchInitials.Width = new Unit("180px");
this.txtSearchPhone.Width = new Unit("180px");

this.oGrid.Width = new Unit("800px");

}

void oGrid_PageIndexChanging(object sender, GridViewPageEventArgs e)
{

oGrid.PageIndex = e.NewPageIndex;
//oGrid.DataBind();
bindGrid(String.Empty);

}
protected void btnSubmit_Click(object sender, EventArgs e)
{
bindGrid(String.Empty);
}
protected void btnClear_Click(object sender, EventArgs e)
{
txtSearchFN.Text        = string.Empty;
txtSearchLN.Text        = string.Empty;
txtSearchEmployee.Text  = string.Empty;
txtSearchPhone.Text     = string.Empty;
txtSearchInitials.Text  = string.Empty;
ddDepartment.SelectedIndex = 0;
ddOffice.SelectedIndex = 0;
Utilities.BindGridView(oGrid,true);
}

private void bindGrid(string sort)
{

string sFN = txtSearchFN.Text.Trim().Replace(" ", "%");
string sLN = txtSearchLN.Text.Trim().Replace(" ", "%");
string sEM = txtSearchEmployee.Text.Trim().Replace(" ", "%");
string sPH = txtSearchPhone.Text.Trim().Replace(" ", "%");
string sIN = txtSearchInitials.Text.Trim().Replace(" ", "%");
string sDept = string.Empty;

if (ddDepartment.SelectedIndex > 0)
sDept = "%" + ddDepartment.SelectedValue.ToString() + "%";

string sOffice = string.Empty;
if (ddOffice.SelectedIndex > 0)
sOffice = ddOffice.SelectedValue.ToString();

oDataset = Employee.searchEmployees(sFN, sLN, sIN, sPH, sOffice, sDept, sEM);
oView = new DataView(oDataset.Tables[0]);
oGrid.DataSource = oView;

if (Utilities.hasData(sort))
oView.Sort = sort;

//oGrid.DataBind();
Utilities.BindGridView(oGrid, oView, true);

}

void oGrid_Sorting(object sender, GridViewSortEventArgs e)
{

string lastExpression = "";

if (ViewState["SortExpression"] != null)
lastExpression = ViewState["SortExpression"].ToString();

string lastDirection = "asc";

if (ViewState["SortDirection"] != null)
lastDirection = ViewState["SortDirection"].ToString();

string newDirection = "asc";

if (e.SortExpression == lastExpression)
newDirection = (lastDirection == "asc") ? "desc" : "asc";

ViewState["SortExpression"] = e.SortExpression;
ViewState["SortDirection"] = newDirection;

string sSort = e.SortExpression + " " + newDirection;
bindGrid(sSort);

}

}

}

// Utilities.cs

using System;
using System.Collections.Generic;
using System.Text;
//add
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
using System.Data.Common;
using System.Web.Configuration;
using System.Data.SqlTypes;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint;
using System.IO;

namespace BWEmpDir
{
class Utilities
{

static private string _connR  = WebConfigurationManager.ConnectionStrings["IntranetUserR"].ConnectionString;
static private string _connRW = WebConfigurationManager.ConnectionStrings["IntranetUserRW"].ConnectionString;

static public SqlConnection getConnR()
{
return (new SqlConnection(_connR));
}
static public SqlConnection getConnRW()
{
return (new SqlConnection(_connRW));
}

static public bool hasData(string f)
{
bool bReturn = false;

if (f != null &amp;&amp; f.Trim().Length > 0)
bReturn = true;

return bReturn;
}

static public bool hasData(TextBox f)
{
bool bReturn = false;

if (f != null &amp;&amp; f.Text.Trim().Length > 0)
bReturn = true;

return bReturn;
}

static public bool hasNoData(string f)
{
bool bReturn = false;

if (f == null || f.Trim().Length == 0)
bReturn = true;

return bReturn;
}

static public bool hasNoData(TextBox f)
{
bool bReturn = false;

if (f == null || f.Text.Trim().Length == 0)
bReturn = true;

return bReturn;
}

static public void BindGridView(SPGridView gv, bool bRebind)
{
gv.DataSource = new string[] { }; //clear
if (bRebind)
gv.DataBind();
}

static public void BindGridView(SPGridView gv, DataSet ds, bool bRebind)
{
gv.DataSource = new string[] { }; //clear
gv.DataSource = ds;
if (bRebind)
gv.DataBind();
}
static public void BindGridView(SPGridView gv, DataView ds, bool bRebind)
{
gv.DataSource = new string[] { }; //clear
gv.DataSource = ds;
if (bRebind)
gv.DataBind();
}

static public BoundField buildColumn(string sData, string sHeader, string SortExp)
{
BoundField col = new BoundField();
col.DataField = sData;
col.HeaderText = sHeader;
col.SortExpression = SortExp;
return (col);
}

static public BoundField buildColumn(string sData, string sHeader)
{
return(buildColumn(sData, sHeader, sData));
}

}

}

26
Jan
09

#20 Some helpful links for tracking down & fixing SP errors

Event Viewer 10016 error (application log)

“The application-specific permission settings do not grant Local Activation permission…”

http://www.cleverworkarounds.com/2007/10/25/dcom-fun-with-sharepoint/


The blasted ‘An unexpected error has occurred’ error page with nothing in any log that you can find.

http://blog.thekid.me.uk/archive/2007/02/15/a-solution-to-quot-an-unexpected-error-has-occurred-quot-in-wss-v3.aspx


CAS errors on SqlClient (System.Data.SqlClient.SqlClientPermission). Use your c:\inetpub\wwwroot\wss\VirtualDirectories\<port number>\web.config to locate your active Security Policy config file rather than the following post’s suggestion.

http://www.mysharepointblog.com/2007/03/default.aspx

14
Jan
09

#19 Employee Directory Sharepoint Webpart Pt 1 – Stored Procedure

Starting with a new proc to select data of off the EM, Employee Custom Tab Fields and a union with a Auxilary data table to add in such things as printers, conference rooms, local police,  fire etc. I will build on this stored procedure defining a datagrid with filter controls in a Sharepoint webpart.

Virtualized Dev Environment: SQL 2005, Windows 2003 server, Visual Studio 2008, Sharepoint Extensions

This proc allows wildcard searches on fields and does not filter if a null is passed.  The union to the auxiliary table poses some challenges so I created a UDF dbo.IgnoreNullParm to return ‘1′ or ‘0′ to effectively turn off the union ‘leg’ when we are passed a filter parm that does not exist for that table (i.e. Initials).

Proc Def:

Create Procedure [dbo].[searchEmployees]
(
@FirstName        nvarchar(50)
,@LastName        nvarchar(50)
,@Initials              nvarchar(03)
,@Phone               nvarchar(20)
,@Office                nvarchar(50)
,@Dept                  nvarchar(50)
,@EmpNum        nvarchar(04)
)
as
Select
EM.Employee
, isNull(EM.PreferredName,EM.FirstName) 		as FirstName
, (RTRIM(EM.LastName) + ' ' + isNull(Suffix,'')) 	as LastName
, EM.MiddleName
, EM.Org                                                    as PrimaryDept
, EM.Region
, EM.WorkPhone
, EM.WorkPhoneExt
, EM.MobilePhone
, ECTF.Cust5ULPhysical                                as Office
, ECTF.custSecondaryDepartment                as SecondaryDept
From
EM
Join EmployeeCustomTabFields ECTF on ( ECTF.Employee = EM.Employee )
Where
EM.Status = 'A'
And    (         EM.FirstName     like  Case When (@FirstName is null)    Then '%' Else RTRIM(@FirstName)    + '%' End
OR    EM.PreferredName      like  Case When (@FirstName is null)    Then '%' Else RTRIM(@FirstName)    + '%' End
)
And    EM.LastName         like  Case When (@LastName is null) Then '%' Else RTRIM(@LastName)    + '%' End
And    SUBSTRING(EM.FirstName,1,1)
+  RTRIM(Case When(DATALENGTH(EM.MiddleName) = 0) Then '' Else  SUBSTRING(EM.MiddleName,1,1) End )
+  SUBSTRING(EM.LastName,1,1)  LIKE Case When (@Initials is null) Then '%' Else  @Initials  End
And    (        EM.WorkPhone    like '%' + isNull(@Phone,'%') + '%'
OR    EM.WorkPhoneExt like '%' + isNull(@Phone,'%') + '%'
OR    EM.MobilePhone    like '%' + isNull(@Phone,'%') + '%' )
And ECTF.Cust5ULPhysical = isNull(@Office, ECTF.Cust5ULPhysical)
And ( EM.Org like '%' + isNull(@Dept,'%') + '%'
OR ECTF.custSecondaryDepartment like '%' + isNull(@Dept,'%') + '%'  )
And EM.Employee like  isNull(@EmpNum,'%') + '%'
 UNION ALL
Select  EmpNum                     as Employee
, FirstName
, LastName
, ''                            as MiddleName
, ''                            as PrimaryDept
, ''                            as Region
, Phone                        as WorkPhone
, PhoneExt                        as WorkPhoneExt
, ''                             as MobilePhone
, ECTF_Cust5ULPhysical            as Office
, ''                            as SecondaryDept
From OfficeAux OA
Where
OA.FirstName        like  Case When (@FirstName is null) Then '%' Else RTRIM(@FirstName)    + '%' End
And    OA.LastName         like  Case When (@LastName is null)     Then '%' Else RTRIM(@LastName)        + '%' End
And '1'    = dbo.IgnoreNullParm(@Initials)        <em> -- if parm is null ignore it otherwise this effectively 'turns off union' if parm is not null</em>
And '1'    = dbo.IgnoreNullParm(@Dept)           <em>-- if parm is null ignore it otherwise this effectively 'turns off union' if parm is not null</em>
And    (        OA.Phone        like '%' + isNull(@Phone,'%')  + '%'
OR    OA.PhoneExt    like '%' + isNull(@Phone,'%')  + '%')
And ECTF_Cust5ULPhysical = isNull(@Office, ECTF_Cust5ULPhysical)
And EmpNum  like  isNull(@EmpNum,'%') + '%'


UDF


Create function [dbo].[IgnoreNullParm]
(
@Field  nvarchar(50)
)
Returns bit
-- Sends back True '1' if Parm is null
-- Setup in where clause as Where '1' = IgnoreNullParm(@parm)
-- Allows you to effectively turn off a union 'leg' if a parm is not null and ignore it if not null
as

Begin

Declare @bReturn as  bit

Select  @bReturn = Case When (@Field is null) Then '1' Else '0' End

Return @bReturn

End

Auxilary Table:


CREATE TABLE [dbo].[OfficeAux](
[ID] [uniqueidentifier] NOT NULL,
[ECTF_Cust5ULPhysical] [varchar](20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[XName] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[EmpNum] [char](3) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[FirstName] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[LastName] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[PhoneExt] [nvarchar](10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Phone] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[MobilePhone] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[isActive] [bit] NULL,
[lastUpdated] [datetime] NULL,
[lastUpdater] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]
End
01
Oct
08

#18 SQL Reporting Viewer on page passing credentials

This code presents a report viewer on an asp.net page and allows you to call a class that encapsulates the needed calls to get & pass credentials, report path, report name and parms to the SQL Reporting Server. The more static parameters like report server and authenticating ID & password are read in from the web.config file.

asp.net page code holding ReportViewer control:

<%@ Register Assembly=”Microsoft.ReportViewer.WebForms, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”
Namespace=”Microsoft.Reporting.WebForms” TagPrefix=”rsweb” %>

<rsweb:ReportViewer ID=”ReportViewer1″ BackColor=”#efefef” runat=”server” Width=”100%” Height=”800px”>
</rsweb:ReportViewer>


asp.net.cs code

protected void launchReport()
{
SRS _srs = new SRS();
List<ReportParameter> paramList = new List<ReportParameter>();
paramList.Add(new ReportParameter("Username", "***", false));
paramList.Add(new ReportParameter("ClientID", "****", false));
_srs.launchReportInViewer(ref ReportViewer1, "ReportFolder", "ReportName", paramList);

}

SRS class used to wrap the calls to the report server. This will require you add a reference to Microsoft.ReportViewer.WebForms.dll in the GAC or add into your /Bin dir. (check C:\Program Files\Microsoft Visual Studio 8\ReportViewer to locate the dlls if not installed in the GAC)

using System;
using System.Configuration;
using Microsoft.Reporting.WebForms;
using System.Collections.Generic;

/// <summary>
/// Summary description for SQL Reporting Viewer class
/// </summary>
public class SRS
{
public SRS ()
{

}

public void launchReportInViewer(ref ReportViewer RV, string sFolder, string sReportName, List<ReportParameter> paramList)
{
RV.ServerReport.ReportServerCredentials   = new ReportViewerCredentials();
RV.ServerReport.ReportServerUrl           = new Uri(ConfigurationSettings.AppSettings["ReportServer"].ToString());
RV.ServerReport.ReportPath                = @"/" + sFolder + @"/" + sReportName;
RV.ServerReport.SetParameters(paramList);
RV.ShowRefreshButton                      = true;
RV.ShowPageNavigationControls             = true;
RV.ShowToolBar                            = true;
RV.Visible                                = true;
RV.ProcessingMode                         = ProcessingMode.Remote;
}

}

Credit due for ReportServerCredentials class beloworiginal link This class was converted to C# and slightly modified. Please note the GetFormsCredentials method has to be implemented to meet the interface definition but is stubbed out.

ReportViewerCredentials class:
using Microsoft.Reporting.WebForms;
using System.Net.Security;
using System.Net;
using System.Configuration;

public class ReportViewerCredentials : IReportServerCredentials
{
private string _userName;
private string _password;
private string _domain;

public ReportViewerCredentials()
{
_userName   = ConfigurationSettings.AppSettings["ReportViewerUser"].ToString();
_password   = ConfigurationSettings.AppSettings["ReportViewerPassword"].ToString();
_domain     = ConfigurationSettings.AppSettings["ReportViewerDomain"].ToString();
}

public ReportViewerCredentials(string userName, string password, string domain)
{
_userName = userName;
_password = password;
_domain = domain;
}

public System.Security.Principal.WindowsIdentity ImpersonationUser
{
get { return null; }
}

public System.Net.ICredentials NetworkCredentials
{
get { return new NetworkCredential(_userName, _password, _domain); }
}

/// <summary>
/// Not Used
/// </summary>
public bool GetFormsCredentials(out System.Net.Cookie authCookie, out string userName, out string password, out string authority)
{
userName = _userName;
password = _password;
authority = _domain;
authCookie = null;
return false;
}

}

web.config entries:

<appSettings>
<add key="ReportViewerUser" value="***"/>
<add key="ReportViewerPassword" value="***"/>
<add key="ReportViewerDomain" value="***"/>
<add key="ReportServer"  value="***"/>
</appSettings>
27
Jun
08

#17 Thinking of converting to VS 2008 ?

### Update ###

The SQL 2008 Business Intelligence Development Studio (VS subset) that ships with SQL Server 2008 imports the 2005 VS  rdl files without any problems. I have not tested this extensively but all looks same-same.

D Gorman 1/14/09

####

(see update above) Be aware that your VS 2005 Sql Reporting Projects don’t convert.  I just ran a conversion (after backing up the code and solution files) and it just drops the SRS (.rptproj) project. I tried opening a .rdl file and it does not handle it correctly.  I will have to look at what is next in regards to this but for now you have to keep VS2005 around for SRS reporting and/or figure out VS 2008 new process for handling BI (BIDS).  Post a comment if you know a better way.

After searching around I found these posts:

http://geekswithblogs.net/juang/archive/2007/12/12/visual-studio-2008-will-not-support-sql-server-2005-reporting.aspx

http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=3336504&SiteID=1

Apart from this the other features in VS2008 are very nice & the ability to switch frameworks (sans the usual 1.x)  works flawlessly. I moved a web project from 2.0  to 3.5 and down to 3.0 without a problem.

25
Jun
08

#16 Flipping a SQL report from/to Prod. & Test systems

To flip an existing report definition (stored in rds/rdl files) via Visual Studio:

1. Create an alternate (shared) data source (.rds) for the other system.

2. Take the existing report and copy it off  and rename it (control-C & control-V/ rename should do that)

3. Open this new report definition (step #2) & create a new dataset (part of the .rdl) using this new data source (step #1)

4. Copy the old query or stored procedure reference into this new dataset.

5. Clean up any direct dataset references in the cell expressions.

25
Jun
08

#15 Workflow to Custom Method calls

1. Use Visual Studio 2003 to create the standalone 1.1 framework DLL

2. Copy the dll generated (located under the /bin directory) to your webserver hosting Deltek:
Program Files\Deltek\Vision\Workflow

3. Once the dll is loaded it is visible to Deltek’s WF. You can then configure your WorkFlow by using the  left navigation:: Configuration | WorkFlow | User Initiated Workflow

4. Select Projects from the Application dropdown to get the Project Info Center WFs

5. WF has a top level and sublevels so you can group things anyway you want – we have a few top categories and many sublevels under each categories separated by  New & Edit  which are the 2 distinctions since these are actually DB triggers (at least that is what I think launches these)  executed on insert, update and delete commands in SQL.  Lots here see normal doc and that pdf from the Insight Class.

6. Select Invoke Custom Method from the choices and you will see the following dialog box which “sees” all the dlls in that Workflow directory.

a. Select the dll which is labeled Assembly

b. Select the class from that dll

c. Select the method call from that class

7. The rest is mapping parameters which are all send via strings (ie. no Boolean objects or primitives here checkboxes just send ‘Y’ or ‘N’)

a. To add a parm you cannot just type in the field name like you’d expect . First slide the vertical line between name and value to the left a little so you can see the ellipsis (…) on the far right of each row in the parm grid. Click on that and you get yet another dialogue box. Select your field and make sure you click the Add Column button then OK. You can type in the expression box directly just be careful. If you do this a lot you can save off the field names in ‘[:name]‘ format in text file & cut/paste.

Lastly check the Invoke after all changes are saved checkbox to ensure all your parms are good.

I have noticed timing issues on parms that are filled in from other workflows so show care there. Also be aware these WF can significantly slow down save performance.

Stored Procedures ::

1. Create a viable SP

2. WF “sees” all the SPs so no other migration is needed

3. Select Stored Procedure & load parms the same way as above.