Friday, April 15, 2011

Access Active Directory in .NET

During one of my client requirements, I played a lot with active directory to display user data in a web application from active directory.

Here goes a generic class with some functions to get get user information from active directory:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.DirectoryServices;
using System.Collections;

namespace Common
{
public class ActiveDirectory
{
string domainPath = "GC://YourGC/DC=YourDomain,dc=YourOU,dc=com";

//Get Single user info
public DataTable GetUserInfo(string sLogonName)
{
/*Getting user data from active directory*/
DirectoryEntry entry = new DirectoryEntry(domainPath);
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.Filter = "(&(objectClass=user)(sAMAccountName=" + sLogonName + "))";
SearchResult result = searcher.FindOne();

/*Creating a datatable to store user data*/
DataTable resultTable = new DataTable("UserData");
resultTable.Columns.Add("givenname");
resultTable.Columns.Add("sn");
resultTable.Columns.Add("title");
resultTable.Columns.Add("telephoneNumber");
resultTable.Columns.Add("company");
resultTable.Columns.Add("mail");
resultTable.Columns.Add("department");
resultTable.Columns.Add("manager");

DataRow resultRow = resultTable.NewRow();

if (result.Properties.Count > 0)
{
try
{
resultRow["givenname"] = result.Properties["givenname"][0].ToString();
}
catch (Exception)
{
resultRow["givenname"] = string.Empty;
}
try
{
resultRow["sn"] = result.Properties["sn"][0].ToString();
}
catch (Exception)
{
resultRow["sn"] = string.Empty;
}
try
{
resultRow["title"] = result.Properties["title"][0].ToString();
}
catch (Exception)
{
resultRow["title"] = string.Empty;
}
try
{
resultRow["telephoneNumber"] = result.Properties["telephoneNumber"][0].ToString();
}
catch (Exception)
{
resultRow["telephoneNumber"] = string.Empty;
}
try
{
resultRow["company"] = result.Properties["company"][0].ToString();
}
catch (Exception)
{
resultRow["company"] = string.Empty;
}
try
{
resultRow["mail"] = result.Properties["mail"][0].ToString();
}
catch (Exception)
{
resultRow["mail"] = string.Empty;
}
try
{
resultRow["department"] = result.Properties["department"][0].ToString();
}
catch (Exception)
{
resultRow["department"] = string.Empty;
}
try
{
resultRow["manager"] = result.Properties["manager"][0].ToString();
}
catch (Exception)
{
resultRow["manager"] = string.Empty;
}
resultTable.Rows.Add(resultRow);
}
else
{

}
return resultTable;
}

//Get all domain users multiple properties in data table
public DataTable GetAllUserInfo()
{
/*Getting user data from active directory*/
DirectoryEntry entry = new DirectoryEntry(domainPath);
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.PageSize = 1000;

searcher.Filter = "(&(objectClass=user)(objectCategory=person))"; //to get users only
SearchResultCollection resultCollection = searcher.FindAll();

/*Creating a datatable to store user data*/
DataTable resultTable = new DataTable("UserData");
resultTable.Columns.Add("givenname");
resultTable.Columns.Add("sn");
resultTable.Columns.Add("title");
resultTable.Columns.Add("telephoneNumber");
resultTable.Columns.Add("company");
resultTable.Columns.Add("mail");
resultTable.Columns.Add("department");

SearchResult result;
if (resultCollection != null)
{
for (int counter = 0; counter < resultCollection.Count; counter++)
{
DataRow resultRow = resultTable.NewRow();

result = resultCollection[counter];
if (result.Properties.Contains("givenname"))
{
resultRow["givenname"] = result.Properties["givenname"][0].ToString();
}
if (result.Properties.Contains("sn"))
{
resultRow["sn"] = result.Properties["sn"][0].ToString();
}
if (result.Properties.Contains("title"))
{
resultRow["title"] = result.Properties["title"][0].ToString();
}
if (result.Properties.Contains("telephoneNumber"))
{
resultRow["telephoneNumber"] = result.Properties["telephoneNumber"][0].ToString();
}
if (result.Properties.Contains("company"))
{
resultRow["company"] = result.Properties["company"][0].ToString();
}
if (result.Properties.Contains("mail"))
{
resultRow["mail"] = result.Properties["mail"][0].ToString();
}
if (result.Properties.Contains("department"))
{
resultRow["department"] = result.Properties["department"][0].ToString();
}
resultTable.Rows.Add(resultRow);
}
}
return resultTable;
}


//Get all domain users single property in array list
public ArrayList GetAllADDomainUsers()
{
ArrayList allUsers = new ArrayList();

DirectoryEntry searchRoot = new DirectoryEntry(domainPath);
DirectorySearcher search = new DirectorySearcher(searchRoot);
search.Filter = "(&(objectClass=user)(objectCategory=person))";

SearchResult result;
SearchResultCollection resultCol = search.FindAll();
if (resultCol != null)
{
for (int counter = 0; counter < resultCol.Count; counter++)
{
result = resultCol[counter];
if (result.Properties.Contains("samaccountname"))
{
allUsers.Add((String)result.Properties["samaccountname"][0]);
}
}
}
return allUsers;
}
}
}



Happy Coding!!!

Wednesday, April 13, 2011

Error & information logging; event viewer or text file

We can log different errors or information while writing code for any .NET application, here is a generic class written for logging:

Code:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Security.Permissions;

namespace Common
{
/*This Class is used for logging messages to either a custom EventViewer or in a plain text file located on web server.
* Owner : Deepak Solanki
* Year : 2011 */

public class Logging
{
#region "Variables"

private string sLogFormat;
private string sErrorTime;

#endregion


#region "Local methods"

/* Write to Txt Log File*/
public void WriteToLogFile(string sErrMsg)
{
try
{
//sLogFormat used to create log format :
// dd/mm/yyyy hh:mm:ss AM/PM ==> Log Message
sLogFormat = DateTime.Now.ToShortDateString().ToString() + " " + DateTime.Now.ToLongTimeString().ToString() + " ==> ";

//this variable used to create log filename format "
//for example filename : ErrorLogYYYYMMDD
string sYear = DateTime.Now.Year.ToString();
string sMonth = DateTime.Now.Month.ToString();
string sDay = DateTime.Now.Day.ToString();
sErrorTime = sYear + sMonth + sDay;

//writing to log file
string sPathName = "C:\\Logs\\ErrorLog" + sErrorTime;
StreamWriter sw = new StreamWriter(sPathName + ".txt", true);
sw.WriteLine(sLogFormat + sErrMsg);
sw.Flush();
sw.Close();
}
catch (Exception ex)
{
WriteToEventLog("MySite", "Logging.WriteToLogFile", "Error: " + ex.ToString(), EventLogEntryType.Error);
}
}

/* Write to Event Log*/
public void WriteToEventLog(string sLog, string sSource, string message, EventLogEntryType level)
{
//RegistryPermission regPermission = new RegistryPermission(PermissionState.Unrestricted);
//regPermission.Assert();

if (!EventLog.SourceExists(sSource))
EventLog.CreateEventSource(sSource, sLog);

EventLog.WriteEntry(sSource, message, level);
}

#endregion
}
}


Happy Coding!!!

Web part to show data from list

Requirement is to show news on web page, data saved in custom list . A webpart to get data from list and show on page:

1. Open Visual Studio and create a class file or webpart (if sharepoint extension is there with VS.
2. Code of ShowNews.cs file below:


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 System.Drawing;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;

namespace MyWebParts
{
[Guid("6e1a7cf2-bf98-4926-81c9-0c0184ba6a60")]
public class ShowNews : System.Web.UI.WebControls.WebParts.WebPart
{

//Controls
private Label lblTitle;
private Label lblNews;

// A table that is used to layout the controls
private Table tbMain;
private TableRow tRow;
private TableCell tCell;

#region "Web Part Properties"

private const string defaultSiteCollection = "NewTeamSite";
private string _siteName = defaultSiteCollection;
[Personalizable(PersonalizationScope.Shared), WebBrowsable(true),
WebDisplayName("Site Name"),
WebDescription("Site from where to fetch News")]

public string SiteName
{
get { return this._siteName; }
set { this._siteName = value; }
}

private const string defaultList = "News";
private string _listName = defaultList;
[Personalizable(PersonalizationScope.Shared), WebBrowsable(true),
WebDisplayName("List Name"),
WebDescription("List from where to fetch News")]

public string ListName
{
get { return this._listName; }
set { this._listName = value; }
}
#endregion

public ShowNews()
{
}

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

// TODO: add custom rendering code here.
tbMain = new Table();
tbMain.BorderStyle = BorderStyle.Double;
tbMain.BorderColor = Color.Silver;
tbMain.BackColor = Color.WhiteSmoke;


lblTitle = new Label();
lblTitle.Text = "News";
lblTitle.Font.Bold = true;

tRow = new TableRow();
tCell = new TableCell();
tCell.VerticalAlign = VerticalAlign.Top;
tCell.HorizontalAlign = HorizontalAlign.Center;
tCell.Controls.Add(lblTitle);
tRow.Controls.Add(tCell);
tbMain.Controls.Add(tRow);


lblNews = new Label();
lblNews.Text = "Blank";

tRow = new TableRow();
tCell = new TableCell();
tCell.VerticalAlign = VerticalAlign.Top;
tCell.HorizontalAlign = HorizontalAlign.Left;
tCell.Controls.Add(lblNews);
tRow.Controls.Add(tCell);
tbMain.Controls.Add(tRow);

this.Controls.Add(tbMain);

CreateNewsHtml();
}

private void CreateNewsHtml()
{
SPList newsList;
SPListItemCollection listitemcoll;

try
{
using (SPSite site = new SPSite(this.Context.Request.Url.ToString()))
{
using (SPWeb web = site.AllWebs[this._siteName])
{
newsList =web.Lists[this._listName];
listitemcoll = newsList.Items;
if (newsList.ItemCount > 0)
foreach(SPListItem item in listitemcoll)
{
lblTitle.Text = item["Title"].ToString();
lblNews.Text = item["News"].ToString();
}

}
}
}
catch (Exception ex)
{

}
}
}
}


3. Create ShowNews.webpart file (get created itself with Sharepoint extension)

<?xml version="1.0" encoding="utf-8"?>
<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type name="MyWebparts.ShowNews, ShowNews, Version=1.0.0.0, Culture=neutral, PublicKeyToken=XXXXXXXXXXXXXXXXX" />
<importErrorMessage>Cannot import ShowNews Web Part.</importErrorMessage>
</metaData>
<data>
<properties>
<property name="Title" type="string">ShowNews Web Part</property>
<property name="Description" type="string">Show News from List on Page</property>
<property name="AllowZoneChange" type="bool">True</property>
<property name="AllowHide" type="bool">True</property>
</properties>
</data>
</webPart>
</webParts>


4. Now, your webpart is ready, deploy it either [1] manually; GAC the DLL, upload webpart file to webpart gallery and made safecontrol entry for webpart in web.config file. or [2] create a deployment package to deploy the webpart.

Happy Coding!!!

Friday, April 8, 2011

User Control for Tab Navigation

While developing a portal we came across a requirement where a tab navigation to be created and added in master page of the site. Here are the simple steps of how to create a tab navigation using ASP MENU control.

1. Go to your site/project and add a user control as new item.
2. There will be added one .ASCX file and one code file .ASCX.CS
3. We are not using code file here so delete code file (.ascx.cs)
4. Also delete code file reference from <%@ Control ... directive line (first line in file).

write the code to add asp menu and SiteMapDataSource
code below:

<%@ Control Language="C#" AutoEventWireup="true" %>
<div id="TabDiv" runat="server">
<table cellpadding="0" cellspacing="0" border="0" width="100%" class="TabMenuContainer">
<tr>
<td>
<asp:Menu CssClass="TabMenu" DataSourceID="CampaignPortalSiteMap" HideSelectElements="True"
ID="Menu2" Orientation="Horizontal" runat="server">
<StaticSelectedStyle CssClass="TabMenuItemSelected" />
<StaticMenuItemStyle CssClass="TabMenuItem" />
<StaticMenuStyle CssClass="SiteStaticMenu" />
<StaticHoverStyle CssClass="TabMenuItemHover" />
<DataBindings>
<asp:MenuItemBinding DataMember="SiteMapNode" Depth="0" NavigateUrlField="Url" TextField="Title"
ToolTipField="Description" />
</DataBindings>
</asp:Menu>
</td>
<td class="TabMenuSpacer" width="100%">
</td>
</tr>
</table>
</div>
<asp:SiteMapDataSource ID="CampaignPortalSiteMap" runat="server" ShowStartingNode="false"
SiteMapProvider="PortalSiteMap" />


In the code above:
ASP Menu control create navigation, it takes either a sitemap source as data source that can be bind to it, or menu items (statically or through code).

SiteMapDataSource is the sitemap provider reference, sitemap provider will be specified in web.config file of application.

There are many CSS classes for styling of tabs, that will be there in application's CSS file.

5. Now add the CSS file to define style classes, style sheet below:

body
{
font-family: Tahoma;
}

#MasterContainer
{
border: solid 1px black;
}

#BannerContainer
{
padding: 5px 5px 5px 5px;
font-weight: bold;
font-size: large;
}

.TabMenuContainer
{
border-top: solid 1px black;
}

.TabMenuItem
{
background-color: #FFFFBC;
text-align:center;
font-size: xx-small;
border: solid 1px black;
border-left: none;
padding: 3px 3px 3px 3px;
}
.TabMenuItemSelected
{
background-color: White;
text-align:center;
font-size: xx-small;
border-right: solid 1px black;
border-bottom: none;
border-top: none;
border-left: none;
padding: 5px 3px 5px 3px;
}
.TabMenuItemHover
{
color:Black;
font-weight: bold;
}
.SiteStaticMenu
{
margin: -1px 0px 0px 0px;
background-color: Black;
}
.TabMenuSpacer
{
background-color: #222222;
padding: 5px 5px 5px 5px;
}

#SiteContent
{
padding: 5px 5px 5px 5px;
margin: 10px 10px 10px 10px;
width: 100%;
}

.SiteContentSpacer
{
height: 200px;
visibility: hidden;
}#FooterContainer
{
font-size: xx-small;
border-top: solid 1px black;
}

Till now we are done with menu control and its look and feel, now we need to define the data source for that menu control.

6. Open web.config file of web application, go to section and add a provider that we had specified in used control.

<providers>
<add name="PortalSiteMap" type="System.Web.XmlSiteMapProvider" siteMapFile="portal.sitemap" />
</providers>

The last thing left now is to define sitemap file "portal.sitemap" from where asp menu would pick it's menu items.

7. Add a new sitemap item in project, naming portal.sitemap and put links, titles... of pages in specified xml format, sitemap xml below:

<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/ AspNet/SiteMap-File-1.0" >
<siteMapNode url="" title="" description="" roles="*">
<siteMapNode url="~/Home.aspx" title="Home" description="The home page" roles="*" />
<siteMapNode url="~/default2.aspx" title="Tab 1" description="The first tab" roles="*" />
<siteMapNode url="~/default.aspx" title="Google" description="Google search" roles="*" />
<siteMapNode url="http://www.yahoo.com" title="Yahoo" description="Yahoo search" roles="*" />
</siteMapNode>
</siteMap>


All set now, put this user control on your master page or page, wherever required and navigate...Cheers :-)

Happy Coding!!!

Wednesday, February 16, 2011

Receive repeated logon windows - loopback check in Windows Server 2003

It was something which took lots of time and I couldn't find a valid reason or solution for the problem, finally it turned out as a security feature with Windows Server 2003, that is Loopback check.

One of my old .NET web applications was hosted on Windows Server 2000, since Microsoft doesn't support 2000 servers anymore, I had to move my application to 2003 servers. It was a simple web site with windows integrated security. After creating site on new 2003 server, IIS 6, mapping home directory, putting DLLs, components etc in place, tried to browse site from IIS and received repeated logon window, finally ended up with "You are not authorized....". Tried opening the site in browser (IE) on web server, again same problem. Then on other machine in same network, tried opening the site; no problem, site opened successfully with my windows credentials, it was a great relief. :)

So, the problem was- i was not able to open the site from host machine but it was opening perfectly on any other machine. Tried many tricks; adding to trusted site, intranet zone..etc.. but nothing worked. Finally, after searching lots of article, reading many MSDN pages, found the MS KB for this.

There is a security feature with Windows Server 2003 SP1, named loopback check functionality. By default, loopback check functionality is turned on in Windows Server. This cause repeated Login Windows receive. The solution is simple, go in system registry and disable it.

The loopback check functionality is stored in the following registry subkey:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\DisableLoopbackCheck

Here is the KB link for details on reason and solution:
http://support.microsoft.com/kb/926642

Hope it works for you..
Cheers!!!!

Saturday, January 22, 2011

Enable Sharing & Security Tab - Windows

Sometimes you want to share a folder or to implement\change some security settings or access rights but you wonder, in folder properties, where the Security tab is? It could happen to you even if you have administrator rights. Here are few simple steps to solve the problem.

So to see and unhide the Security tab, just use the following steps:
1. Launch Windows Explorer or My Computer.
2. Click on the Tools at the menu bar, and then click on Folder Options.
3. Click on View tab.
4. In the Advanced Settings section at the bottom of the list, uncheck and unselect (clear the tick) on the “Use simple file sharing (Recommended)” check box.
5. Click OK.

Security tab is available only to Administrator or users with administrative rights. So make sure you login as one. And security can only be set in an NTFS partition. If you’re still having problem to reveal or display the Security tab on files or folder properties, check out the following registry hack and set the value to 0 or simply delete the key:
Hive: HKEY_CURRENT_USER
Key: Software\Microsoft\windows\CurrentVersion\Policies\Explorer
Name: Nosecuritytab
Type: REG_DWORD
Value: 1

I hope it works for you..

To take ownership of a file or folder

Take Ownership:
Are you not able to access or delete a file\folder from your computer even you are administrator?
Don’t worry; take ownership of that file or folder.

How to take ownership of a file
You must have ownership of a protected file in order to access it. If another user has restricted access and you are the computer administrator, you can access the file by taking ownership.

To take ownership of a file, follow these steps:
1. Right-click the file that you want to take ownership of, and then click Properties.
2. Click the Security tab, and then click OK on the Security message (if one appears).
3. Click Advanced, and then click the Owner tab.
4. In the Name list, click Administrator, or click the Administrators group, and then click OK.

The administrator or the administrators group now owns the file.
To take ownership of a folder, follow these steps:
1. Right-click the folder that you want to take ownership of, and then click Properties.
2. Click the Security tab, and then click OK on the Security message (if one appears).
3. Click Advanced, and then click the Owner tab.
4. In the Name list, click your user name, or click Administrator if you are logged in as Administrator, or click the Administrators group. If you want to take ownership of the contents of the folder, select the Replace owner on subcontainers and objects check box.
5. Click OK, and then click Yes when you receive the following message:
You do not have permission to read the contents of directory folder name. Do you want to replace the directory permissions with permissions granting you Full Control?
All permissions will be replaced if you click Yes.

Note folder name is the name of the folder that you want to take ownership of.
Click OK, and then reapply the permissions and security settings that you want for the folder and its contents.