Backing up and fail-safing your ADAM / LDS instance

This could potentially be very long post, but I am going to stick to the high-level objectives only. Leave a comment if you want more details and I will reply to you.

OBJECTIVE: Your users are stored in an ADAM database and your ASP.net website sits on top of this utilizing the ASP.Net membership framework to interface with ADAM to authenticate users. You want to make sure that you are covered in case of any disaster scenarios (like disk corruption, ADAM server blowing up, and manually unintended corruption by your system admins)

PROBLEM: If you notice carefully, we are talking two different things here.

  • Hardware failures – i.e Poof!!!! and your ADAM instance just disappears. Panic your website is down!!!
  • Manual data corruption – So, if your sysadmin does something foolish and say he updates all users with the same last name using a vbs script or something. This is more insidious because your website is not down, ADAM is not down but your user data is corrupt.

SOLUTION: So although we have two distinct ways of getting into trouble, the end result is the same and the solutions are also the same. But first let us talk about what is required at the minimum to recover from a failure scenario.

ADAM Replication – Fortunately, for us, ADAM (or LDS) comes out of the box with support for replication. What this means, is once your main ADAM instance is up and running you can install multiple ADAM instances on other servers as “replicated instances” and all these servers magically know how to talk to each other and keep their data in sync with each other.

Plus, it gives you the flexibility of turning on “two way” replication. i.e you change data on the replicated instance and the main ADAM server reflects these changes. You have the option of staggered replication. i.e the replicated instances will receive deltas from the main server only after XX minutes or hours. Any light bulbs yet on how you will use this to recover from bad things happening?

Windows Backups – I know, I know. Nobody uses Windows Backup and Restore. But this is the perfect place to use it. You simply setup a backup job which backs up your ADAM directory to a file server. We have done it where I work and this gives us nightly backups for every day going back to last 60 days. Also, ADAM has a lock on the files on disk, but Windows Backup used Volume Shadow Copy which takes care backing up files even if they are locked by a process. We use the append option, so backups are not overwritten every night, but are appended (Keep an eye on that backup file though…it can grow pretty fast !!!)

So, now that we know the proper way to protect us from bad things. Here is how you will apply it to various situations:

  1. Hardware failures – If your main ADAM server blows up, you could simply point your website to the replicated instance since it has the latest and greatest data.
  2. Data Corruption by SysAdmin – So, if your sysadmin writes a script which updates every one’s SSN to 000-00-0000 for example, you could either restore the ADAM data from last night’s backup (believe me it is amazing simple to overwrite ADAM data from backup and get up and running in no time). Or, if you had staggered replication setup (i.e replicated instances receive change deltas only after 1 hour and your sysadmin reports the data corruption to you in time, you can shutdown the main ADAM instance and point your website to the replicated instances because they still have good data.

Bottom-line, you can use replicated instances for instantly recovering from the failure scenario, while you are busy building the main instance from the backups. If you have two way replication setup then when you bring the main instance online, the replicated instances will send their deltas back to the main instance (so for example 100 users signed up before you could restore the main instance from backups), these 100 users are only in the replicated instance now. But the moment you bring back the main ADAM instance up, replication will send these users back to the main instance and you will be in sync.

Control ctl00_ContentMain_ xxxxx of type ‘GridView’ must be placed inside a form tag with runat=server

Recently I wrote some simple code to Export the contents of a GridView to Excel. You know, the basic stuff like changing the type to application/ms-excel content and removing Images from the GridView (so that they don’t appear as missing images in the Excel sheet) and converting Hyperlinks to Labels.

The Problem : But when I ran my code, I got the dreaded error :Control ctl00_ContentMain_ xxxxx of type ‘GridView’ must be placed inside a form tag with runat=server

The Solution :  Just place this code in your codebehind. And that will fix ya! :

public override void VerifyRenderingInServerForm(Control control) {}

The Explanation :
Asp.net calls VerifyRenderingInServerForm to ensure that every single server control is being rendered inside a <form runat=”server”> tag. Which makes sense for a web page.  But it doesn’t make sense for an Excel sheet. Since, we just want to send the Gridview contents to the client and not the Form tag.

All we are doing here is overriding this Method and falsely reporting to Asp.Net that our Control is actually being rendered inside a <Form Runat=’server’> tag.

Hope it helps…

Get rid of Regsvr32, Regasm, Gacutil… A Shellextension for .Net and COM dlls

I had originally written a Shellextension for COM dlls, which would give you the option of registering/unregistering a dll (if it is a com dll) by right clicking on it. Here is the original post :https://nishantpant.wordpress.com/wp-admin/post.php?action=edit&post=11

After several years, I finally took out some time and created a Shellextension which works for .Net assemblies as well. These are the few features it has :

1. If you right click on a DLL and if it is a COM Plus dll it will show you the following menu.

COM Plus DllsIf you click on a COM dll but it is not installed in COM+, then you will get all above options except, the last 3 options which are relevant to COM+ only. Also, if you right clik a COM only dll, then it WILL give you an option called “Create COM+ package”.

2. IF you Right click on a dll which is a .Net assembly and is Strong Named as well, you will see the following menu :

If you right click on an Assembly which is not Strong Named, you will see all options except GACUTIL

3. If you hover your mouse over a dll which is a .Net dll, you will see some brief information about the dll like below :

4. If you right click on an Assembly, you will see a menu option called “Open with Lutz Reflector”. In case you dont know what Lutz Reflector is, it is an awesome free tool written by Lutz Roeder which disassembles any .Net assembly and shows you the source code in a very easy to view typelibrary browser. Since you could have downloaded Lutz Reflector anywhere in your PC, my shellextension will prompt you for the location just once when you first click on this option. It will then remember the location and will just open the Reflector with your assembly loaded in it.

Tested with Lutz Reflector 5.1

UPDATE (8/21/08) – Just heard from Lutz Roeder, that his software will be further developed and maintained by Red-Gate software from now on. (It will still be free though). See link for details –>Click to see article

5. If you go to the thumbnail view of any folder which has dlls, the shellextension analyzes the dlls and puts and changes their icon which helps you identify them. The Shellextension can distinguish between a regular dll, COM dll, .Net 1.0, 1.0, 2.0, 3.0 and 3.5 assembly. See below :

6. Last but not the least, you can customize the behavior of the dll and turn the ShellExtensions off or on. You can toggle, IconHandler extension, Right Click context menu extension and ToolTip extension. Here is a snapshot of the configuration screen :

This is the first time I am releasing this ShellExtension, so there may be a few bugs in it. I would really appreciate if you can report the bugs to me by leave a comment in this post. I will try to work on them as soon as I can find time.

DOWNLOAD/Setup :

An enhanced UpdateProgress control, which shows an animation at the point where mouse was clicked

Also Check Out: My latest venture. http://loqly.me – a way for you to ask questions and get answers about local businesses around you. iTunes link:http://bit.ly/e5u4jv (only available in US for now)

WHY DO IT ???

Before you read the post, let us answer why did I waste time in changing the behavior of the UpdateProgress control. Here is the deal. Suppose, you have 5 or 6 controls on your page, which when clicked result in an Ajax call. You know that the UpdateProgress control is pretty much static, meaning, wherever you put the <asp:UpdateProgress> tags, that is the place where the progressbar will show up when your Ajax call is in progress. So, no matter which control the user clicks the progressbar is being shown in a fixed place. Why may some people consider this bad ???

  • You or anyone looking at the screen, may lose track of why you are waiting because the progressbar just shows that you are waiting not what has triggered the wait.
  • If the page is long, and the progress bar is at a fixed place, there is a possibility that you clicked a control which is a scroll length away from where the progressbar will show.
  • If the control which was clicked can give a feedback for the user to wait, it prevents the user from clicking the same button twice.

So, much for justifying why I wrote this control. But those were just a few thoughts behind it. Let us get back to the nitty gritties. Btw, here is a YouTube vide of how it looks (video is a little fuzzy but it shows what I am trying to communicate)

The Code :

I will not go into too much detail explaining the code, because I am sharing the source code with you. But here is the high level overview :

  • Create a new control, which inherits from UpdateProgress control
  • Embed two resources in your control assembly. (the default hourglass image and the javascript used to make this control work)
  • Override Render method, and inject javascript. The javascript will hook into the AJAX InitializeRequest and EndRequest events, by calling add_initializeRequest() and add_endRequest() methods of Sys.WebForms.PageRequestManager class.
  • The first Image control in the <ProgressTemplate> of the UpdateProgress control will be assumed to be the hourglass image, and if you haven’t set an ImageURL value for it, a default image will be supplied. You can create your own hourglass images from this awesome website : http://www.ajaxload.info/#preview

That is it. Do leave comments and suggestions if you find this control useful. I am also attaching the source code and the assembly. If you don’t want to see the code, just use the assembly and things should work right away.

Use declarative security to show a Security trimmed navigation Menu along with enforcing role based security for your website

Hi All,

Here is what we are trying to achieve in this article.

  • Provide side-wide security without writing a single line of code
  • Show navigation menus to the user, which automatically hide the options which the user doesn’t have access to (also called Security Trimming)
  • Use declarative syntax in web.config to tighten your security so that even if the user knows a particular URL, he cannot get to it, unless he is explicitly granted access to the URL.

Background :-
I have this hierarchy of folders
/
|—UserManagement

|—Default.aspx

|—ChangePass.aspx

|—AdminPage.aspx (Only admins should have access to this page, and the menu control shouldn’t show this option)

I am using a ASP:Menu control and I want all logged in users to be able to see all menu options except the AdminPage link, but I want the administrator to be able to see every single menu option.

Here is a snapshot of the relevant tags from my web.config file —————————————————————-

<!–In this case my Roles are stored in an XML file, your roles can reside in SQL Server or AD or ADAM, it doesn’t matter–>

<add name=AzManPolicyStore connectionString=msxml://C:/Azman.xml />

<!–Here is how we enable the role manager. In this case the built in ASP.Net website config tool will automatically read and write Roles and their membership info in the file mentioned above. i.e Azman.xml–>

<roleManager enabled=true defaultProvider=RoleManagerProvider>

<providers>

<add name=RoleManagerProvider

type=System.Web.Security.AuthorizationStoreRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, publicKeyToken=b03f5f7f11d50a3a

connectionStringName=AzManPolicyStore

applicationName=TestApp/>

</providers>

</roleManager>

 


<!– To make security trimming and declarative security work, we need to follow the pessimistic approach. i.e first we will deny everyone access to our website–>

<authorization>

<deny users=*/>

</authorization>

<!– Then we selectively start permitting users and or Roles access to folders/files–>

<location path=UserManagement>

<system.web>

<authorization>

<allow roles=“Administrators, Managers, Users”/>

</authorization>

</system.web>

</location>

<!– Deny access to everyone except Admin on the Admin only page–>

<location path=UserManagement/AdminPage.aspx”>

<system.web>

<authorization>

 

<deny users=*/>

<allow roles=“Administrators”/>

</authorization>

</system.web>

</location>

Here is the excerpt from my Default.aspx page, which has the menu control ———————————–
<asp:Menu ID=Menu1 runat=server DataSourceID=SiteMapDataSource1

Orientation=Horizontal>

</asp:Menu>


<!–Note that I am explicitly mentioning Sitemapprovider=”” attribute, although if I dont mention it, it should pick up the default provider. But this is what made the security trimming work for me. If you don’t do this, the Security trimming in menus will not work !! –>

 

<asp:SiteMapDataSource ID=SiteMapDataSource1 runat=server SiteMapProvider=XmlSiteMapProvider />


 

 

Here is my Web.Sitemap file—————————–

 

<?xml version=1.0 encoding=utf-8 ?>

<siteMap xmlns=http://schemas.microsoft.com/AspNet/SiteMap-File-1.0>

<siteMapNode url=~/Default.aspx title=Home description=“”>

<siteMapNode url=~/UserManagement/Default.aspx title=Manage security settings description=“”/>

<siteMapNode url=~/UserManagement/ChangePass.aspx title=Change your password description=“”/>

<siteMapNode url=~/UserManagement/AdminPage.aspx title=Admin Only Functions description=“”/>

</siteMapNode>

</siteMap>

 

 

 

Thats it. Just by following these simple steps, you will have rock solid security for your website. And you don’t have to write a single line of code too.

 

AZMan Rolemanager keeps roles cached and does not reflect changes for a long time

If you have found this article, you already know who Mr. Azman is and what I am talking about here. So, I will not go into the details to explain you what asp.net 2.0 Rolemanager is and what all options it gives us to store role and membership information.

Here is the excerpt from my web.config file :

<!–In this case my Roles are stored in an XML file, your roles can reside in SQL Server or AD or ADAM, it doesn’t matter–>

<add name=AzManPolicyStore connectionString=msxml://C:/Azman.xml />

<!–Here
is how we enable the role manager. In this case the built in ASP.Net
website config tool will automatically read and write Roles and their
membership info in the file mentioned above. i.e Azman.xml–>

<roleManager enabled=true defaultProvider=RoleManagerProvider>

<providers>

<add name=RoleManagerProvider

type=System.Web.Security.AuthorizationStoreRoleProvider,
System.Web, Version=2.0.0.0, Culture=neutral,
publicKeyToken=b03f5f7f11d50a3a

connectionStringName=AzManPolicyStore

applicationName=TestApp/>

</providers>

</roleManager>

 

You must have noticed that in this example my Role data store is c:azman.xml file. The problem that I was facing was that, whenever I would make changed to my role membership by using ASP.Net web configuration tool, it would update the .xml file perfectly fine, but ASP.net would still continue using the cached roles that it had loaded when I started my application.

After some research I found out that, the the default behavior of Rolemanager is to cache roles in memory for 60 minutes. This might be unacceptable for some people. So, the solution for this is to add cacheRefreshInterval=”x” to your RoleManagerProvider node. The X can be as low as 1 which would mean 1 minute, but you can change to whatever suits you best.

<add name=RoleManagerProvider

type=System.Web.Security.AuthorizationStoreRoleProvider,
System.Web, Version=2.0.0.0, Culture=neutral,
publicKeyToken=b03f5f7f11d50a3a

connectionStringName=AzManPolicyStore

cacheRefreshInterval=”1

applicationName=TestApp/>

How to provide ASP.NetWebadminfiles (WSAT) like user management for your hosted or online site

I recently was working on a ASP.net 2.0 website. I used the ActiveDirectoryMembershipProvider and used the membership API along with Login controls to provide a nice experience to the user with features like Sign up as new user, change password, password reset, login and all related functionality which any website offers you.
When my code was in development, I had the built in WSAT (ASP.Net website administration tool), which I could launch from Visual Studio.Net and I could easily administer my website. You can launch this tool using the Website–>ASP.Net configuration menu. This tool is really cool and without writing a single line of code you can easily manage all the security and settings for your website.
But the problem arises when you move your code to production. The WSAT tool only works locally (i.e via localhost). By default, it prohibits remote access.
In this post, I will explore two ways of managing your website security remotely.

Option 1 :

Make changes to the WSAT tool to make it work remotely
The WSAT tool with source code is located in your C:WINDOWSMicrosoft.NETFrameworkv2.0.50727ASP.NETWebAdminFiles folder. To make it accessible on the network, all you have to do is go to IIS–>Create new virtual directory–>Point to the above folder and remove anonymous access from directory settings page.

Then you need to access it the same way your local ASP.Net configuration tool is accessed i.e via a URL which resembles something like :
http://SERVER/AdminTool/default.aspx?applicationPhysicalPath=C:Inetpubwwwrooottestsite&applicationUrl=/testsite

But you will notice, as soon as you try to access it, it will spit out an ugly error “This tool cannot be remotely accessed.“. This is because by default the tool is locked down for local access only. To fix this, all you need to do is open C:WINDOWSMicrosoft.NETFramework64v2.0.50727ASP.NETWebAdminFilesApp_CodeWebAdminPage.cs file in a text editor and change line#488 FROM >> if (!application.Context.Request.IsLocal) { << TO if(false){

Once you save your file, the tool will allow remote access.

Option 2

:
Some people may not allow you to mess with the production webserver like above, becasue it involves changing a .net framework file and it can be a security risk. 4guysfromrolla.com has done a nice thing, they have written a generic user management piece which works just like WSAT and you can easily include it as part of your website. Just package it with your website, since it comes with source code (although the source code is in C#). You just have to follow a few steps to make it work for you. You can find the article which talks about the custom tool here : http://aspnet.4guysfromrolla.com/articles/052307-1.aspx and download the source code here http://aspnet.4guysfromrolla.com/code/ezdeploy.zip

Here are few things I had to do to make it work for my website:

  • Copy the source code to a subfolder in my site
  • Delete the web.config from the root level which comes with the source code
  • Move the 4guys.master file to the root of my website (this is mentioned in the article)
  • Move images from the i folder to the images folder of my website and change links which point to these images (this is mentioned in the article)
  • Change the stylesheet link in 4guys.master file to point to the correct location.
  • Move _controls folder to the root of my website
  • Delete all subfolders except admin from the source code. We dont need these.
  • Changed the 4guys.master to remove menu links to pages which are irrelevant for the security piece.
  • NOTE: If you are using ActiveDirectoryMembershipProvider, you will get bunch of errors like
    The property 'LastLoginDate' is not supported by the Active Directory membership provider.]
    
    System.Web.Security.ActiveDirectoryMembershipUser.get_LastLoginDate()

To solve this all you have to do is remove following lines in all the .aspx pages.
<asp:BoundField DataField=”lastlogindate” HeaderText=”Last Login Date” />
<asp:BoundField DataField=”lastactivitydate” HeaderText=”Last Activity Date” />
<asp:BoundField DataField=”isonline” HeaderText=”Is Online” />