CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Brendan Tompkins [MVP]

Blog First. Ask Questions Later.

March 2004 - Posts

  • DataAdapter for Active Directory/LDAP?

    I'm writing a bunch of AD code for adding users, groups, etc. and I got to thinking, “Wouldn't it be cool if there was an AD DataAdapter for managing AD objects using DataSets?”  You can, of course, load AD data into DataSets through linked servers, but AFAIK, there's no DataAdapter for automatically handling the updates/inserts/deletions. Does anyone know of anything out there that does this?

    -Brendan

  • Cool Tool: Reflector for .NET

    This thing's pretty neat, Lutz Roeder's Reflector for .NET .

    Reflector is a class browser for .NET components (assemblies). It supports assembly and namespace views, type and member search, C# XML documentation viewer, reference search, IL disassembler, VB and C# decompiler, dependency trees, supertype/subtype hierarchies and resource viewers. Function prototypes are displayed in C# and VB syntax.

    -Brendan

  • Windows Server 2003 AD Schema Refresh Issue - Fix

    We recently deployed a web application here on our intranet which uses Windows authentication.  During development, on an XP machine, the application worked fine.  When we pushed it into production on a 2003 server machine, we started getting this error:

    The directory datatype cannot be converted to/from a native DS datatype

    The thing was, the application would work for a while and then stop working.  Well, we tracked this issue down to the following problem, discussed in KB Article 241981:

    “With ADSI version 2.0, ADSI forces a schema cache update every time ADSI fails to get the syntax of attribute from the LDAP server, which is represented by the error message above. In ADSI version 2.5, the dynamic schema cache update was removed for performance reasons, and because the forced refresh was thrashing the RootDSE on LDAP version 2.0 servers“

    The problem with this KB article is that it discusses how to manually refresh the schema cache, but it's in loosely typed script code. So, after some research, I found a method of the SchemaEntry object that will do the refreshing.  Here's one example of how to to do this:

    public string GetProperty(DirectoryEntry de, string PropertyName)
    {    
       
    de.SchemaEntry.RefreshCache(
    new string [] {PropertyName});
       
       
    if(de.Properties.Contains(PropertyName)){
          
    return de.Properties[PropertyName][0].ToString() ;
        }
        
       
    return null;
    }

    This works, but we found that the web server also had to be “Trusted for Delegation“ by the domain controller machine.  Now, I had our network guy do this, and the combination of the Schema refresh and the trusting did the trick! 

    -Brendan

  • Going Direct 101 : Getting Your Ducks in a Row

    Here's part II of Going Direct 101.  Start here for background and also to have a look at my questionnaire to find out if you're able to go direct.  If you think you can do it, here are some tips that worked for me:  

    Plan ahead:  Start talking to key people months in advance, testing the waters to see if your current client organization would support you as a direct, corp-corp contractor. 

    Review your employment agreement:  This is the only document that should concern you.  Your placement company may have policy against this and that, but what you agreed to is what you are legally bound to do.  

    Decide for yourself if doing this operates within your own personal ethical structure:  If you are hourly employee or a subcontractor, here's my take on the ethics of this:  You are a commodity, you should have the right to trade your skills fairly.  Would your placement company trade you in for a better deal if they could?  Most likely the answer is yes. 

    Get the full-support of your client manager:  Make sure that your client manager knows why and when you plan to attempt the go direct.  If possible, get them to verbally commit that they'd hire your as a consultant from another company or directly were you to become available.

    Approach client managers well in advance, more than once and when they're in a good mood:  Especially good is to approach them after an exceptionally successful project.  Talk to them on a Friday afternoon when they're not as busy.  Avoid Tuesdays - they are usually the most hectic for upper managers.

    Don't badmouth your placement company:  This does no one any good.  I don't think I have to explain this one..

    Keep in on the down low:  Don't go around telling everyone what you want to do.  Tell just enough people to ensure that you have support.

    Be consistent about your reasons for going direct and discuss them with the key people at your client company:  Your best option here is to make your long-term career the major issue.  You should only make career moves that are forward looking and have positive long-term benefits. 

    Next time: Executing the Deal

    -Brendan

  • Going Direct 101

    As we're going through this off-shoring trend, our jobs are getting less and less secure.   If you're a contractor/software engineer, you may be analyzing your long-term career options.  Perhaps you've decided to fight this trend by writing letters to the government.  Perhaps you've looked into working for local contract firms that don't have an off-shoring practice.   Perhaps you've decided to be one of those engineers that are going to support off-shoring by being one of the “local“ people on an off-shored team (good luck BTW). 

    I want to try to relate some of my experiences with another option: Being a self-employed independent contractor.  Chances are you've considered becoming an independent contractor and working for your own company.  Chances are you've wondered if it's possible to do this with a client you are already working with current company. 

    Welcome to Going Direct 101.  By going direct, I'm referring to working as a contractor for an existing client directly, bypassing your placement company.  This is admittedly hard to do and has some thorny issues, but also has some great rewards.

    I should mention that I'm not advocating that anyone attempt to go direct.  Doing so should be a decision that you make with your family, professional advisers, and possibly a good lawyer.  I have looked for other sources that discuss the whole issue and I really couldn't find any.  In fact, at least in the US, the subject is largely taboo.  You won't find people talking about it in the open, but that may be and should be changing.  Think about it this way: If what we do has been commoditized to such an extent that it can be sent overseas, we should have the right to trade our skills on the free market.

    So, I thought I'd offer up some advice.  Now I'm not a lawyer, so take everything you read here knowing that I'm really no expert.  However, I have gone direct with a client and know people who have done so multiple times.  So for what it's worth, I thought I'd give some pointers for anyone interested.

    Going direct isn't for everyone.  First of all, if you're a full-time employee of your placement company you should stop reading this right now.  Full-time employees usually have a non-compete clause in their employment agreement legally prohibiting a going direct to a client.  Ethical reasons also come into play when you're full-time.  Being full-time implies a two-way commitment between you and your employer that often supersedes going direct.

    If you have moral and or ethical problems with any of this, then it's not for you.  This should not be read as a general advocation of everyone “cutting out the middleman.”  What I am trying to get across is that it is legal, and often  perfectly fair.  It all depends on the situation at hand.     

    So, is this possible for you?  Can you offshore-proof yourself by being self-employed?   If you can answer yes to the following questions it may be more than possible, it may be relatively easy.

    1) Does the client you are looking to go direct with think highly of you and your work? 

    For an client organization to go through this process, they've got to be willing to go through some uncomfortable discussions with your placement company.  To do this, they've got to see you as a unique and hard to find resource.

    2) Is  the client free to hire any contracting company?

    Often a client will only be able to hire from a select few “preferred vendor“ consulting firms.  If this is true, forget it unless you want to work for one of the other preferred companies.  In order to be independent,  you're going to have to set up a C-corp, LLC or use a pass-through company.  You'll never get your company on the client's preferred vendor list. 

    3) Is your client willing to shake up the water with your placement company? 

    This is key.  You've got to have the support of your client manager 100%. Is the president of your placement companies buddies with the client's CEO? If so, they may value their relationship over and above anything you would want to do.

    4) Can the client manager make big decisions? 

    You need to find out if your client manager can get contracts signed.  If you're working for someone lower on the totem pole, chances are they'll have to go up the chain to get something signed.  The more people that get involved, the more chance there is for something to go wrong. 

    5) Have you checked your employment agreement to make sure there are no prohibitions?

    Hopefully you still have a signed copy of your latest employment agreement.  Often placement companies update their boilerplate agreements, so key is having the exact copy you signed.  Have a lawyer look it over.

    6) Does your client have a contract with your placement company that prohibits them from hiring you direct? 

    Chances are, they have a non-solicitation clause specifying a finder's fee for hiring direct.  This may only apply to them hiring you full-time and it can be overcome in two ways.  1) There's usually a pay off amount finder's fee that the client may have to pay to the placement company.  A typical range would be $15,000 to a max of 1/2 the employees salary. 2) If the company has multiple people placed at the client, they may agree to such a flip without the payoff, just to keep from rocking the waters.

    6) Are you willing to look for another job if the deal goes south? 

    This has to be the most important question you ask yourself.  If you're confident in your job finding abilities, no worry here.

    7) Do you have a plan for lining up your next contract if the deal works out and your contract ends? 

    As you know, contract jobs can be short-term.  Are you willing to beat the pavement looking for a new client to go direct with?  Do you think you'll be able to?  Remember they'll be no existing client next time! 

    If you answered YES to all these questions, you should, with the right finesse, be able to go direct.  Stay tuned for Part 2 : Getting Your Ducks in a Row

    Brendan

  • Active Directory Schema Cache Refresh Issue?

    Does anyone know anything about how to get the AD Schema to refresh under IIS6 on Windows Server 2003 using Windows Authentication?

    Specifically, we get the error when using the following code to get the properties of an AD User:

     

    We've been struggling for days on this, and the problem seems to be somehow related to the way IIS connects to AD using Windows Authentication. Can't figure out if it is a permissions problem or what.  I've checked the impersonation and even if we impersonate a local admin account for w3wp we still get the error.  If we logon to app using Forms Authentication, everything works for a while under Windows Authentication until  1) the AD Schema Cache refreshes or 2) we recycle the IISAdmin Service. 

     

  • What to do About Bad KB Code?

    I'd rather have bad KB code than none at all, but the following article's code is terrible!  Stuff is commented out, like someone's in mid thought.  There's stale comments that don't have anything to do with the code that's obviously from some other sample code.  It's driving me crazy! 

    http://support.microsoft.com/default.aspx?scid=kb;en-us;316337 

    This artilcle is a how to on converting a dataset to an ADO Recordset XML and is in VB.NET so I'm porting it to C#. I'm going to post the ported code when I'm done. 

  • Off-Topic : "Bassing"

    This guy's post on “Bassing“ is really funny.  Most of all it's funny because I secretly love bassing.  I don't have a good subwoofer in my car or anything, but I still get enormous amounts of pleasure rolling up to pick up my 6-year old from his snooty elementary school with a good Jurassic 5 tune pumpin'.

    But, funnier is that I know a few good developers who also like to turn up the tunes.  Even funnier was that scene in Office Space where Michael Bolton is bassing on the highway. 

    Funniest is that we're all these geeky software developers just like the Michael Bolton character.  What is it that makes us do this?  It's admittedly a really obnoxious thing to do.  Why are we driven to it? 

  • Support No IntelliSense Day...

    This is a good idea. Kind of like when Yoda forced Luke to fight blindfolded.

    http://weblogs.asp.net/jkey/archive/2004/03/17/91622.aspx

  • Offshore Outsourcing : I Quit.

    Today, I tendered my resignation with my consulting firm.  I had a bunch of excellent reasons for doing this, but the process has been accelerated over the last couple of weeks primarily because of this offshore outsourcing issue.  See, a couple of weeks ago, I received an email from our CEO stating that the company will be lobbying the government in support of offshore outsourcing.  If you've been following my posts, you already know that this has led me on a campaign to better understand the issues surrounding outsourcing.  Well, I've come to the realization that my previous firm is interested in only one thing, and that one thing has nothing to do with my long-term professional career.  I wish I could issue the following press release:

    Large Consulting Firm Loses Local Software Engineer Because of Offshore Outsourcing

    NORFOLK, Virginia.- March -17th 2004 - Fearing for his long term career, a local software engineer today quit his consulting job with a large, multi-national software engineering firm.   “I just couldn't give another dime to help fund the loss of US jobs overseas“ said the engineer.  An anonymous spokesman for the large corporation declined to comment.

    UPDATE:   I need to clairify something.  Although I did quit my job at ___ today, and yes, the offshore thing pushed me in the direction, I have been thinking about leaving for about a year, for completely selfish reasons.  I'm not a martyr for the cause or anything like that.  And believe me, I didn't quit without first lining up something else!  Sorry if I misled anyone..

  • Computerworld Article : Google's Offshore R&D

    An article in COMPUTERWORLD (March 1, 2004) talks about offshoring of R&D to India. Specifically, they mention Google's offshoring of some of it's R&D. There's a quote from a guy at Google.  He says:

    “Bangalore is the so-called Silicon Valley of India, and there is a large pool of talented software engineers there.“

    Google's position is that they're doing it for the talent, not the costOf course there are tons of talented engineers overseas, but do you believe that they are not doing it for the cost?  Have they reached the bottom of the barrel of talented US engineers?  Are big software companies learning how to “spin” press like our political leaders? Weren't the Google founders Stanford University grad students when they created Google?  Has Stanford stopped producing high-quality software engineers?  Could I ask any more questions in one post?

  • A Scalable ASP.NET Expanded User Properties Model

    OBSOLETE CONTENT
    The author of this post has determined that this content is obsolete. Use at your own risk! Blog posts are a point-in-time snapshot of the blogger's thinking and should not be assumed to represent this blogger's current opinions. This post was left up for historical purposes.

    Like most of you doing serious ASP.NET development, I've based my security and authentication model around the System.Security.GenericPrincipal object.   Pretty simple stuff, on authentication of any web request, I restore a cookie-based principal, and authenticate or require login. This is all standard stuff.

    Well, if you are working on a complex web application you may have several different types of users.  Examples may be customers, partners, employees, etc.  Often times, one or all of these different types of users will have user-type specific information that may be needed throughout the entire application.  For an example of this, lets say that partners have a "Partner Code" and employees have an employee #.  Now, if you're an employee you obviously don't have a “Partner Code” and vice-versa.  Often times, this information is expensive to fetch, so you will want to store this in a cache somewhere.  An obvious, brute force method of doing this would be to expand your GenericPrincipal object with a bunch of typed properties to store all the different possible information a user may have.  The big problem with this method is that you end up with a big bloated Principal object.   Another solution would be to sub-class for each different types.  This may sound good, but without multiple inheritance it would be difficult to have a customer that was also a partner. 

    So this is the general problem that I was faced with here at the work.  We have a bunch of different types of users, and they each have different, sometimes shared properties.  These properties are often expensive to retrieve and involve calls to legacy data sources.   I came up with a design pattern and model that works really well.   It's all based on an interface I named IExpandedUserInfoProvider.  Here's the interface:

    public interface IExpandedUserInfoProvider
    {
      
    object GetExpandedInfo(GenericPrincipal user);
       ExpandedUserInfoType ExpandedType {
    get;}
    }

    This is all pulled together through a class that lazy-loads itself from session.  I have a reference to this class in my PageBase, so that it is easy to get to. I called this class ExpandedUserInfo  It takes a reference to the session in it's constructor so that you can have this class live in your base web dll.

    public class ExpandedUserInfo

       public const string SESSION_KEY = "EXPANDED_USER_INFO_HASHTABLE";
       private HttpSessionState m_session;
       
       
    public ExpandedUserInfo(
            IExpandedUserInfoProvider [] providers, 
           
    GenericPrincipal user, 
           
    HttpSessionState   session)
         {
               
    this.m_session = session;
               
    if(!this.IsInitialized) {
                    foreach(IExpandedUserInfoProvider provider in providers) { 
                        ExpandedUserInfoType providerType = provider.ExpandedType;
                       
    object o = provider.GetExpandedInfo(user);
                       
    if(o != null)
                        {
                                int prevContainedTypes = this.ConatinedTypes;
                               
    this.ConatinedTypes = prevContainedTypes |= (int)providerType;
                               
    this[providerType] = o;
                        }
                    }
                    this.IsInitialized = true;
                }
        }

        public bool HasType(ExpandedUserInfoType type) 
        {
           
    return Convert.ToBoolean((int)type & this.ConatinedTypes); 
       
    }

        public bool IsInitialized
        {
           
    get {
                
    return(this.ExpandedUserInfoHash["INITIALIZED"] != null &&
                Convert.ToBoolean(
    this.ExpandedUserInfoHash["INITIALIZED"]));
            }
           
    set {
               
    this.ExpandedUserInfoHash["INITIALIZED"] = value;
            }
        }

        public object this [ExpandedUserInfoType type] 
        {
            get { return this.ExpandedUserInfoHash[type.ToString()]; }
           
    set {this.ExpandedUserInfoHash[type.ToString()] = value;}
        }

        private int ConatinedTypes
        {
           
    get
           
    {
               
    return (ExpandedUserInfoHash["ContainedTypes"] == null
                    ?
      0 : (int) ExpandedUserInfoHash["ContainedTypes"];
            }
           
    set{ ExpandedUserInfoHash["ContainedTypes"] = value;}
        }

        private Hashtable ExpandedUserInfoHash 
       
    {
           
    get
               
    if(this.m_session[SESSION_KEY] == null)
                   
    this.m_session[SESSION_KEY] = new Hashtable();
               
    return (Hashtable) this.m_session[SESSION_KEY];
            }
           
    set{ this.m_session[SESSION_KEY] = value;}
       
    }
    }

    For each new provider you have, you are going to have to add a type to an enum that keeps track of all of the possible types.  The enum is called ExpandedUserInfoType, and mine looks like this:

    public enum ExpandedUserInfoType
    {
        TruckerInfo      = 0x01,
        ShiplineInfo     = 0x02,
        BrokerInfo        = 0x04,
        CompanyInfo  = 0x08
    }

    Our phony example version looks like this:

    public enum ExpandedUserInfoType
    {
        PartnerInfo      = 0x01,
        CustomerInfo     = 0x02,
        EmployeeInfo        = 0x04
    }

    You can have as many types as you need to add, just remember that this type is going to be used as a bitflag, so you need to make sure the values you add are bitfields.  See my post here for more info on this.

    Okay, so how does this all get used?  Lets take the Partner Code example.  You would need to do the following: 

    1. Create your Partner Code Provider class that implements IExpandedUserInfoProvider
    2. Optionally create a type that actually holds the partner code (for simplicity I'm going to use a basic string but note that you can return any type)
    3. Add a new enumerated value to the ExpandedUserInfoType enumeration
    4. When you need your expanded info, access it through an instance of the ExpandedUserInfo class.  Remember, this class will lazy load all of the types it needs.

    So, in air-code, here's an implementation example of my PartnerCodeProvider:

    public class PartnerCodeProvider : IExpandedUserInfoProvider
    {
       public object GetExpandedInfo(GenericPrincipal user) {
         // Go get your Partner Code Here
         return “Expensive Partner Code“;
       }

      public ExpandedUserInfoType ExpandedType
      {
        
    get { return ExpandedUserInfoType.PartnerCode;}
      }
    }

    And here's how to use it. Keep in mind that you can simplify this by keeping a reference to the ExpandedUserInfo class in you page base with a list of all providers you want to support:

    ExpandedUserInfo eui = new ExpandedUserInfo( 
        new IExpandedUserInfoProvider [] {new PartnerCodeProvider()},
       
    this.CurrentUser,  this.Session);

    // Check to see if this user has this expanded type

    if
    (eui.HasType(ExpandedUserInfoType.PartnerCode))
    {
        String strPartnerCode = (String)this.CurrentUserExpandedInfo[ExpandedUserInfoType.PartnerCode];

       // Now, do something really cool with your Partner Code!
    }

    That's about it.  I hope I didn't leave anything out.  If you can get this set up, it's well worth it when later on you realize that you have to scale your user information.

    -Brendan

  • Even my Grandmother thinks Offshore Outsourcing is Bad...

    I had dinner with my family last night.  Well, it was a special occasion and my grandmother was there.  Getting her out of the nursing home is a task, and well, anyway, let's just say she doesn't get out much.  Well, the funny thing is that what she does do is watch CNN practically 24 hours a day.   She never talks about politics, though, so I've often wondered if she is actually watching, or if it's just on for background noise.   Well, last night someone asked me about work, and I mentioned offshore outsourcing.  My grandma, who often times is not listening to the conversation at all, said “I know all about that, Lou Dobbs has been talking about it lately.”  Well, I was floored that even my grandmother, who most of the time can't remember the name “Saddam” had all this knowledge about how bad offshore outsourcing is for our country. 

    I mention this, because I realized that this is an issue that Americans, even my grandmother, are taking seriously.  A lot of people have been replying to my earlier posts about this too.  This is good stuff.

    -Brendan

  • Info World Cover Story - .NET Gets a Good Report Card...

    Well, I'm so proud.  I picked up a copy of InfoWorld at work today, and the cover story is titled “.NET Report Card”   In case you can't get your copy, here's how .NET did:

    • Advancing the state of the Windows programming Art: B
    • Software deployment: A-
    • Security: B-
    • Richness, reach and next-generation UI: incomplete (they're waiting for Whidbey and ClickOnce)
    • Web Services: A

    The cool thing about this article is that it's geared towards decision makers, and should get read by a lot of CIO types...

    -Brendan

  • Offshore Outsourcing Continued - I need to call Michael Moore...

    4/22/04 UPDATE: Before you read this, you may want to see my post here.  It looks like Michael Moore may not be the one to call, after all. 

    So, I'm still trying to wrap my hands around this offshore outsourcing issue.  I've gotten more information about my company's plans for their PAC.  Indeed, they are going to lobby for offshore-favoring laws and candidates.   I also found out that a job I was considered for a year ago here locally has been outsourced to India.  They have 16 offshore developers, and some people locally.  I'm not feeling too good about this. 

    I've talked to a bunch of people, and have gotten some interesting responses.  First, I mentioned this to a Consultant that works for the same company that I do.  He relayed to me our company's official line - that local consultants will always be needed to manage and design apps.  You know, weeks of use-case and design docs sent off to the design team.  Well, from everything I've been reading about modern software engineering methodologies, I just can't see how this will work.  In fact, InfoWorld has a good artice here about this very thing.

    Second, I mentioned this to the Network Ogre.  His response was interesting.  You see, he and I are always going back and forth about cars.  He drives a Ford.  I drive a Hyundai.  My wife drives a Hyundai too.  He said to me “You're something else! You're worried about losing your job overseas, but you've bought cars that are made in Korea. You're a hypocrite!”  Well, since he said that, I've been wondering if he's right...  Is this issue the same as the US loosing out to foreign auto makers?  I can think of a couple of reasons why these issues aren't the same.    For one, we're not losing software jobs because of poor product quality, I don't think anyone would discount the quality of  US software developers.  Second, when we buy cars, a lot of money comes back into the local economy (gas, taxes, repairs, etc.)

    I saw this great documentary filmed by the much hated Michael Moore called Roger & Me where he really exposed the Detroit Auto makers for irresponsible business practices (offshoring).  I'd love to know what he thinks about all this...

    -Brendan 

    IMPORTANT UPDATE : As of  3/10/04, I have spelled “losing” correctly.  Thank you to the courageous anon, who stuck her/his neck out to point this out to me.

More Posts Next page »

Our Sponsors