The Pavement
Web Design and Application Develop

Adding and Removing Users from AD Groups

August 3, 2007 11:48 by Shaun

Many organisations use their Active Directory services to assign security policies to their internal software and the one I’m currently working for is no different. The web application I’m currently developing extracts the username from the HTTP header and then queries the Active Directory service to see if that user belongs to a particular AD group. I have been implementing functionality to allow the application to add and remove users from this group and I thought I’d give a brief overview of how this is done…

The first thing you need is a service account username and password that has full control of the AD group you wish to modify, you can then implement the following to add a user to this group, just plug in the correct strings for your particular setup:

public void AddUserToRAPSGroup(string userName)
{
   //Retrieve entry using LDAP
   DirectoryEntry LDAPentry = new DirectoryEntry("LDAP://" + <AD Server Name>);
   LDAPentry.Username = <AD Server Name> + @"\" + <AD Username>;
   LDAPentry.Password = <AD Password>;
  
   //Set up a search object using the userName as a filter
   DirectorySearcher dsUser = new DirectorySearcher();
   dsUser.SearchRoot = LDAPentry;
   dsUser.PropertyNamesOnly = true;
   dsUser.PropertiesToLoad.Add("sAMAccountName");
   dsUser.Filter = "(&(objectCategory=person)(objectClass=user)(sAMAccountName=" + userName + "))";
  
   //execute the search and retrieve the user
   SearchResult srUser = dsUser.FindOne();
   DirectoryEntry deUser = srUser.GetDirectoryEntry();

   //now get the ad group
   DirectorySearcher dsGroup = new DirectorySearcher();
   dsGroup.SearchRoot = LDAPentry;
   dsGroup.Filter = "(&(objectClass=group) (cn=" + <AD GroupName> + "))";
   SearchResultCollection results = dsGroup.FindAll();
   bool isGroupMember = false;
   if (results.Count > 0)
   {
      DirectoryEntry group = GetDirectoryEntry(results[0].Path);

      object members = group.Invoke("Members",null);
      foreach ( object member in (IEnumerable) members)
      {
         DirectoryEntry x = new DirectoryEntry(member);
         if (x.Name != deUser.Name)
         {
            isGroupMember = false;
         }
         else
        {
            isGroupMember = true;
            break;
         }
      }
  
      if (!isGroupMember)
      {
         group.Invoke("Add", new object[] {deUser.Path.ToString()});
      }

      group.Close();
   }
}
Tags: Tags:
Categories: .NET
Actions: E-mail | Permalink | Comments (2) | Comment RSSRSS comment feed

Converting a String to an Enum

July 31, 2007 09:35 by Shaun

I’ve come across the need to covert a string to an enum value on numerous projects in the past, each time I google the answer, implement it and then completely forget!  One solution I found was to construct a huge switch statement, this is obviously a bad idea.  For one it’s a waste of energy typing it all out plus it won’t deal with any future changes to the enum.  Instead have a look at the following code:

object Enum.Parse(System.Type enumType, string value, bool ignoreCase);

 Here’s  an example for a colour enum:

(Colour) Enum.Parse(typeof(Colour), "Green", true);

Easy huh!

Tags: Tags: ,
Categories: .NET
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

CommandField Causing IsPostback = False

July 30, 2007 12:12 by Shaun

I’ve just spent the whole morning trying to get to the bottom of some really strange page behaviour on my current project.  I have a gridview control with a command field being used to fire the RowDeleting event.  I noticed that when the delete button was clicked the IsPostback property was returning false.  This caused all of my page initiation code to be executed for a second time.  After hours of trying to find the problem it turns out this is an ASP.NET 2.0 bug that occurs when the commandfield has a button type of ‘Image’. 

<asp:CommandField ButtonType="Image" HeaderText="Delete" ShowDeleteButton="true"
                DeleteImageUrl="~/Images/delete.png" />

After changing the attribute to ‘Link’ the IsPostback property correctly returns True.  The problem with this solution is that you loose any nice icons being used and are left with text.  To fix this you can add an image tag to the DeleteText attribute as shown below:

<asp:CommandField ButtonType=Link HeaderText="Delete" ShowDeleteButton="true"
                 DeleteText="<img src='Images/delete.png' style='border:none;' />" />

Hope this saves someone a bit of time in the future…

Tags: Tags: ,
Categories: .NET
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

Wildcard String Replacement in C#

July 23, 2007 17:31 by Shaun

I was recently faced with the task of removing a bunch of tags from a string I was manipulating in C#. The string class has a whole bunch of inbuilt methods that can be used to manipulate its contents, one of those being the .Replace method. I was hoping that this method could deal with wildcards, this would make the removal of any html tags easy using syntax such as:

thestring = theString.Replace("<a>*</a>");

Unfortunately there didn’t seem to be any such functionality. So I started to write my own utility method to do such a task.  This turned out to be more complex that I first reckoned, the code I have included below works just fine when removing <a> tags that contain an href attribute.  The code can be called as so:

theString = Utils.WildCardReplace(theString, @"<a href="*>", string.Empty);

And here’s the implementation:

public static string WildCardReplace(string strString, string strOldValue, string strNewValue)
       {
            bool oldValueFound = true;

            //split out the start and end values using the wildcard
            string strStart = strOldValue.Substring(0, strOldValue.IndexOf('*'));
            string strFinish = strOldValue.Substring(strOldValue.IndexOf('*') + 1);

            while (oldValueFound)
            {
                //get the index of the first occurance of this string
                int indexOfStart = strString.IndexOf(strStart);
                int indexOfEnd;
                if (indexOfStart != -1)
                {
                    //get the index of the first appearance of the end string
                    indexOfEnd = (strString.IndexOf(strFinish, indexOfStart)) - indexOfStart + 1;
                }
                else
                {
                    indexOfEnd = -1;
                }

                ////did we get matches
                if (indexOfStart == -1 ||
                    indexOfEnd == -1)
                {
                    //no so jump out of the loop
                    oldValueFound = false;
                }
                else
                {

                    //yes, get the complete substring to replace
                    string strBitToReplace = strString.Substring(indexOfStart, indexOfEnd);

                    //do the replace
                    strString = strString.Replace(strBitToReplace, strNewValue);
                }

            }

            return strString;
        }

This will remove the opening a tag. The standard Replace method can then be used to remove all the orphaned closing tags.

Please feel free to reuse/improve the code as you wish.

Tags: Tags: ,
Categories: .NET
Actions: E-mail | Permalink | Comments (2) | Comment RSSRSS comment feed

Bug in CollapsiblePanelExtender - Flashing in IE6

July 19, 2007 16:31 by Shaun

This is a word of warning for anybody developing with the AJAX Control Toolkit using IE7. I deployed my code onto a test server today and started to run through it before unleashing it to the test team. The company I am developing for use IE6 across their estate but I had been developing and testing using IE7. Its only when I clicked through the app using IE6 I discovered that partial page updates no longer work. After a lot of searching on the internet I discovered this is a bug that has yet to be fixed with the CollapsiblePanelExtender within IE6. The page is correctly performing a partial page update but the browser decides to redraw the whole page anyway.. very frustrating!

Does anybody know of a workaround for this? Or an alternative CollapsiblePanel control?

Tags: Tags: , ,
Categories: .NET
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

Validation Summary Control Not Playing Nicely With Ajax

July 19, 2007 13:26 by Shaun

Today I’ve been having a few problems with the validation summary control when nested within and AJAX UpdatePanel. I have implemented an AJAX.NET Update panel on my master page wrapping all content that falls within it. When I added a validation summary control to one of the content pages I started to see a javascript error stating “’null’ is null or not an object” which wasn’t particually helpful!

After a bit of googling I came across this article explaining that the old validation controls are not compatible with the new way of registering client side script, the article explains that “WindowsUpdate will soon include a version of System.Web that can take advantage of the new APIs” however I’m yet to see this update appear! There is a link to some custom validator controls that work with partial rendering but I was not keen on changing the page so I looked for an alternative..

I eventually came across Microsoft’s Pilot program for downloadable hot fixes, the issue can be resolved easily by downloading and installing the following fix:

http://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=6106

Hope this helps..

Tags: Tags: , ,
Categories: .NET
Actions: E-mail | Permalink | Comments (2) | Comment RSSRSS comment feed

Freezing GridView Headers and Columns

July 18, 2007 01:53 by Shaun

I am currently developing an ASP.NET web based planning application for a client. The application is very data heavy with a lot of pages displaying large amounts of data in a tabular format. As you would expect I’ve implemented this using a combination of SQL stored procedures, .NET DataTables and finally a GridView on the page itself. I thought I was almost done until a resent review meeting where the client suggested it would be great if they could freeze the table headers and left most columns just like Excel so that they could view the large tables more easily.

After a bit of googling I found a number of examples of how this can be done to html tables all using a combination of CSS and javascript expressions contained within the style sheet itself. A great example can be found here. However when I tried to apply this to an ASP.NET GridView it didn’t work without a fair bit of tweaking! I thought I’d step through what I did to help anybody out faced with a similar demanding clients!

There are three parts to setting this up:

  1. The Mark-up
  2. The CSS
  3. The server side code to apply the relevant styles

The Mark Up

The main issue is that by default the GridView does not render its table header cells as <th> elements instead using the <td> element (Bad Microsoft!). However there is a way around this, by adding the UseAccessibleHeader="True" attribute to the datagrid we can force the control to render in a more compliant way and use the <th> elements. We also need to wrap the Gridview control in a div element to provide the scroll functionality.

<div id="GridViewScrollContainer">
   <asp:GridView UseAccessibleHeader="true" ID="GridView1" runat="server" OnRowDataBound="GridView1_RowDataBound">
    </asp:GridView>
</div> 

The CSS

The following CSS is then used to implement the frozen elements, one thing to note is that if you change the name of the surrounding Div in your mark-up make sure you also change the name in the getElementById expressions.

#GridViewScrollContainer
{
    width: 97%;
    height: 400px;
    overflow: auto;
    margin-left: 5px;
} div#GridViewScrollContainer table th
{
    width: 100px;
} #GridViewScrollContainer th
{
    top: expression(document.getElementById(   "GridViewScrollContainer" ).scrollTop-2);
    z-index: 20;
} #GridViewScrollContainer td.locked, #GridViewScrollContainer th.locked
{
    left: expression(document.getElementById(   "GridViewScrollContainer" ).scrollLeft);
    position: relative;
    z-index: 100;
    border: solid 1px white;
}
#GridViewScrollContainer th, #GridViewScrollContainer th.locked
{
    position: relative;
    cursor: default;
    border: solid 1px white;
}
#GridViewScrollContainer th.locked
{
    z-index: 110;
}

The Server side code

Finally on the RowDataBound event of the GridViewControl we can allocate the columns that we wish to freeze the relevant CssClass.

protected void gvResults_RowDataBound(object sender, GridViewRowEventArgs e)
{
  //lock the first 3 columns
  e.Row.Cells[0].CssClass = locked;
  e.Row.Cells[1].CssClass = locked;
  e.Row.Cells[2].CssClass = locked;
}

One major thing to note is that this solution will not work in IE7 if you mark your page with an XHTML 1.0 doc type,  I believe this is due to the lack of support for the CSS expressions  going forward. To solve the problem change the doc type from XHTML 1.0 to the old HTML 4.0 shown below:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

This obvisly isnt ideal because you are essentially throwing the browser back into ‘qwerks’ mode but for my particular page this didn’t have any adverse effects, plus the application will be running in a closed envirnment where IE6 and 7 are the only browsers in use.

I Hope this helps people and please let me know if you have any comments / suggestions for a more cross browser solution.

Tags: Tags: ,
Categories: .NET
Actions: E-mail | Permalink | Comments (15) | Comment RSSRSS comment feed