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

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.

Migrating Sourcesafe database from one server to another in 5 steps

UPDATE: The easiest way to move a VSS database to a new server is to copy the whole database in one shot. If your database is small this works like a charm. See this MS KB article for details. The only gotchas are :

  1. This involves copying the complete VSS folder over the network. This may be slooooow and the file copy may even fail suddenly for no reason.
  2. If the VSS db is real big then even winzip will stop at 65K files, so rule out that option if the no of files > 65K. Even winrar doesn’t work. I haven’t tried Lharc or ARJ yet.

    —————————————————————————————-

    Original Post

    If you have found this article, it means you haven’t had much luck trying to find how to migrate VSS from one machine to another. Also, many of you must have noticed that MS KB article http://support.microsoft.com/kb/q176875/ is bogus and the syntax for ssarc does not work. So, how do you actually move your VSS sourcesafe database ????

    STEP 1: Use SSARC.EXE to archive your existing database.
    Here is the syntax which I got working for me after umpteen trial/errors :
    ssarc “-s\\vssserver\vssfolder” d:\Archive.SSA $

    1. Notice that -s is inside the quotes
    2. $ means the whole VSS should be archived starting from root. You can specify sub branches too. eg. $/Projects or $/Project/Project1
    3. Make sure you enter ‘N’ (NO) when ssarc asks you if you want to delete the existing database after it has been archived.

    STEP 2: Run SSRESTOR.EXE to restore the database on the new server.
    ssrestor “-s\\NewServer\VSS” d:\ArchivedProjects.ssa “$/PathYouWantToRestoreTo”

    STEP 3: Copy existing users from your current VSS installation.
    Copy VSS\Users folder, VSS\Users.txt file and Um.dat file to the new installation

    STEP 4: Run Analyze -F “C:\Program Files\Microsoft Visual Studio\VSS\Data. This will re-generate the rights for all the users based on um.dat. Remember you just cannot simply copy rights.dat file to do this.

    STEP 5: You can either change the current srcsafe.ini to point to the new database, so that developers don’t get a broken link. Or you can just shutdown the server and tell people to reload their projects from the new server.

    Thats it. When you complete step 5….your VSS migration is complete !!!!

    Further Reading:—————

    Problems/Fixes for integrating VSS with Interdev:
    http://www.codeproject.com/asp/VSS_and_VID.asp?df=100&forumid=136229&select=1313406&msg=1313406

    User right setup for VSS:
    http://support.microsoft.com/kb/131022/EN-US/

    Use of http://codebetter.com/blogs/darrell.norton/archive/2004/04/15/11493.aspx vss binding remover on developer’s machines to get rid of .scc files

    LDAP Query to search a user in AD using his partial last name

    Dim User as object

    Set User = GetUserObjectFromPartialName(’doe’)

    Msgbox User.FullName & User.sAMAccountName

    —————————————————————————————————-

    Public Function GetUserObjectFromPartialName(ByVal PartialName As String) As Object
    On Error Resume Next
    Set rs = CreateObject(”adodb.recordset”)
    rs.ActiveConnection = “provider=adsdsoobject”

    rs.Open “<LDAP://dc=sl,dc=ad,dc=csx,dc=com>;(&(objectCategory=Person)” & _
    “(objectClass=OrganizationalPerson)(name=” & PartialName & “*));adspath;subtree”

    If Not rs.EOF Then
    Set GetUserObjectFromPartialName = GetObject(rs(0))
    End If
    End Function

    Recursive LDAP function to get nested groups

    Here is a simple recursive function that I wrote which will give you nested groups and members for any given Active Directory group. Try it….it works! U can bind it to a tree later on to show it on the screen. I have also included an output of how it looks when bound to an iewc Treeview.

    tree.jpg

    Dim AdsPath as string
    Dim XMLRoles as string

    AdsPath = GetAdsPathOfGroupThroughADO(”Domain Admins”)

    XMLRoles = GetRoleMembers(Adspath)

    ———————————————————————–

    Public Function GetAdsPathOfGroupThroughADO(ByVal Group As String) As String
    On Error Resume Next
    Set rs = CreateObject(”ADODB.RecordSet”)
    rs.Open “;(sAMAccountName=” & Group & “);adspath”, “provider=ADsDSOObject”

    If Not rs.EOF Then
    s = rs(0).Value
    End If

    GetAdsPathOfGroupThroughADO = s
    End Function
    ———————————————————————–

    Public Function GetRoleMembers(ByVal RoleAdsPath As String) As String
    Dim eu As Object
    Dim XML As String

    Set eu = CreateObject(”ess.user”)
    Set Group = GetObject(RoleAdsPath)
    XML = “”

    For Each member In Group.Members
    If member.Class = “Group” Then
    XML = XML & vbCrLf & GetRoleMembers(member.ADsPath)
    ElseIf member.Class = “foreignSecurityPrincipal” Then
    On Error Resume Next
    Set u = GetObject(”LDAP://=” & eu.SidStringToHexString(member.cn) & “>”)
    If Err.Number = 0 Then
    XML = XML & vbCrLf & “”
    End If
    End If
    Next

    XML = XML & vbCrLf & “”
    GetRoleMembers = XML
    End Function

    ———————————————————————–

    input.jpgTreetransform.XSLT
    eg. TreeView1.TreeNodeSrc = “XML returned by GetRoleMembers()….”
    TreeView1.TreeNodeXsltSrc = Server.MapPath(”Treetransform.xslt”)�
    ———————————————————————–

    WordPress statistics not updating with Blogstat, firestat or Statpress

    I moved my WordPress blog to my Home machine recently. The main motivation was to have full control over wordpress. As most of you would already know that WordPress is free!, which means that you can download the entire wordpress software with source code and run it from your home machine. All you need is a webserver. I use IIS but there are several free webservers out there. By the way IIS is also free depending on the operating system you have. eg. Windows XP Pro comes with IIS. Or Windows Vista Business and above also come with IIS.

    Anyway, I installed at least 15 free plugins when I moved my blog to my own machine. Yes, thats what you get for hosting your own blog. If you have a wordpress.com or wordpress.org blog, you will not even see the menu option called ‘plugins’. But, the real power of wordpress lies in plugins. Once you start seeing the plugins available out there, you will literally freak out.

    So, I installed 3 plugins just to track my stats (i.e how many people are visiting my blog, what blog posts they are reading, what country they are comning from, what Google search terms they are using to get to my blog etc etc). But, I was really frustrated the first few days, because all the stats plugins showed me was 0 vistors, 0 hits….and I knew that this couldn’t be true. So, now I am sharing the one line of code which was causing all my stats plugins to malfunction. I found out that the “theme” that I was using for my Blog had a missing line of code in the header.php file. So, I just added this line of code and wallah!!!! all the plugins started showing me stats instantly. This is what I did to start making it work…………

    <div id=”sitetitle”>
    <h1><a href=”<?php bloginfo(’url’); ?>”><?php bloginfo(’name’); ?></a></h1>
    <h2><?php bloginfo(’description’); ?></h2>
    </div>

    <div id=”menu”>
    <ul>
    <li><a href=”<?php bloginfo(’url’); ?>”>home</a></li>
    <?php wp_list_pages(’title_li=’); ?>
    </ul>
    </div>
    <?php wp_head(); ?> <– This is the line I changed.

    Leave a comment if this does or doesn’t work for you.

    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:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ASP.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:\Inetpub\wwwrooot\testsite\&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:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\ASP.NETWebAdminFiles\App_Code\WebAdminPage.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” />

    Sprint Mogul with the leaked EVDO Rev A and unlocked GPS ROM update

    UPDATE : HTC Has finally released the official promised ROM update on Monday, March 10th 2008. Get it here : http://www.htc.com/us/FAQ_Detail.aspx?p_id=75&act=sd

    I recently bought a new Sprint Mogul. I am loving the device so far. Yeah, I know it is not very sleek and is a tad bit thicker than what I had hoped for, but the phone is a neat piece of machinery. Has a nice dual core CPU, and as far as I know it is the only Windows Mobile phone so far which has a Qualcom 400 mhz processor, rather than the regular Intel XScale or samsung or any of those older and much slower processors. The phone is such a pleasure to use, no time lags in menus or applications opening up. Sprint’s EVDO network is unbelievably fast and internet surfing rocks on this phone. I was easily getting speeds upto 400 kbps!! which is awesome!

    So, how can it be “awesomer than this”…Well, greed has no limits..right? The more you get the more you want. You all must have heard that SPRINT has been promising since last year that they will come out with an official ROM update which will unlock the hidden GPS in the phone and will also upgrade the phone to the new EVDO Rev A. But it is already March 2008, and no news of the ROM yet. So, I went to good old Google and started hunting for any interesting ROMs out there. I found out that apparently the ROM update that SPRINT and HTC are preparing has already been leaked out in its BETA and is widely available on the internet. Found several sites, which had a link to the ROM and the required utilities to apply this update to your phone.

    And I decided to take the plunge on my 1 day old phone. Of course, I was impatient in reading the instructions and I bricked the phone initially. For several hours I was stuck at the infamous tri-color bootloader screen. But then I figure out that I needed to CID unlock the phone first (CID unlocking will allow the phone to accept any new ROM images, otherwise it just rejects the images). So, i found a utility (titan_exitbl.exe) which kicked my phone out of the tri-color screen, then I CID unlocked it (Hard-SPL-240-MFG.exe)
    and applied the ROM update(RUU_TITAN_SPRINT_WWE_3[1].16.651.0_435009_RS3_27_00_SPCS_NV124).

    PS: The reason why I have mentioned the cryptic EXE names above for the utilities is that you can simply google for those keywords and you will find several places and articles where you can download and read about them.

    Folks, below is what I have now….

    The boot up after applying the ROM update. You can easily see that it says “TEST ROM, NOT FOR SALE”

    Using Google Maps on the phone with the in-built GPS. Nice !

    Using www.dslreports.com to test the internet speed. Can you believe, I am getting North of 950K/Sec now! Unfreakinbelievable!

    Show multiple columns in a dropdown with proper alignment

    The problem : We have an ID column and a Name column in our database. We want to show both in a dropdown but if you concatenate both, you will notice that the alignment goes out of whack.

    eg. 1
    ———————–
    1 - Item one
    2 - Item two
    20 - Item twenty
    100 -Item hundred
    3 - Item 3

    See what I mean. The alignment is completely out of whack. What we want to achieve here should kinda look like below.


    eg. 2
    ———————–
    1   - Item one
    2   - Item two
    20  - Item twenty
    100 - Item hundred
    3   - Item 3

    So we have multiple problems here. One is that in most of the fonts every character takes up a different amount of space. eg. A will take more space on the screen than lower caps a. The other problem, is how to write our stored procedure in a way that it pads the extra spaces as in e.g 2 above

    The Solution :
    1. The solution to the problem with characters taking different screen space is very simple. All we need to do is use something called a Monospace font. Create a style like below :
    /* Monospace font - same width for all characters */
    .monospace{ FONT-SIZE: 8pt; font-family: monospace;}

    If you are using ASP.Net just set your dropdown’s cssClass=”monospace”. If your are using plain html, just set the class=”monospace”

    2. That takes care of problem #1. Now, let us kill the 2nd bird.
    In your stored proc, do something like this :

    SELECT
    [Id],
    [Name],
    LEFT(LEFT(Name,25) + REPLICATE(’.',25),26) + Cast([Id] as varchar(3)) As IDName,

    That is it. The IDName column will give you the perfectly aligned characters and Dots will be stuffed in between the name and id so that they align up nicely. The output is something like this (for someone reason wordperss is messing up the formatting..but I hope you get what I mean):

    Item1…………1
    Item number t….2
    Item# 20 ……..20
    Item # hundred…100

    If you want the output, flipped around. i.e IDs showing first and Names showing later, change your select to this :
    SELECT
    [Id],
    [Name],

    LEFT(Cast([Id] as varchar(3)) + REPLICATE(’.',4),5) + Left([Name],25) As IDName,

    This will give you output like this :
    ——————————–
    1……Item1
    2……Item number 2
    30…..Item 30
    299….Item 299

    Hope you find this useful. Happy coding!!!