Friday, 21 May 2010

C# - Managing Active Directory Security Principals in the .NET Framework 3.5

Managing Directory Security Principals in the .NET Framework 3.5
This article is based on a prerelase version of Visual Studio 2008. All information herein is subject to change.

This article discusses:
  • The System.DirectoryServices.AccountManagement class
  • Active Directory Domain Services
  • Active Directory Lightweight Directory Services (AD LDS)
  • Managing user, computer, and group principals
  • This article uses the following technologies:
    - The .NET Framework 3.5, Visual Studio 2008 Contents
  • Directory Services Programming Architecture
  • Establishing Context
  • Creating a User Account
  • Creating Groups and Computers
  • Managing Group Membership
  • Finding Ourselves
  • Finding Matches
  • Difficult Search Operations Made Easy
  • Authenticating Users
  • Extensibility Model
  • Final Thoughts

Directories are an important though rarely mastered component of enterprise application development. For the Windows® platform, Microsoft provides three primary directory platforms: Active Directory® Domain Services, the local Security Account Manager (SAM) data store on every Windows computer, and the relatively new Active Directory Lightweight Directory Services or AD LDS (which you may have previously known as Active Directory Application Mode or simply ADAM). While most enterprise developers know at least the basics of SQL programming, far fewer have experience programming directory services.
The original version of the Microsoft® .NET Framework provided a set of classes for programming directory services within the System.DirectoryServices namespace. These classes were a simple managed interop layer over an existing COM-based OS component (specifically, the Active Directory Service Interfaces or ADSI). While the programming model was reasonably powerful, it was more generalized and pared down than the full ADSI model.
In the .NET Framework 2.0, Microsoft has added features to its System.DirectoryServices and provided two new namespaces: System.DirectoryServices.ActiveDirectory and System.DirectoryServices.Protocols. (We will refer to these as the ActiveDirectory namespace and the Protocols namespace, respectively, throughout this article.) The ActiveDirectory namespace introduced a wealth of new classes for strongly typed management of directory infrastructure-level components, such as servers, domains, forests, schema, and replication. The Protocols namespace went in a different direction, providing an alternative API for programming Lightweight Directory Access Protocol (LDAP). This worked directly with the Windows LDAP subsystem (wldap32.dll), skipping over the ADSI COM interop layer entirely (see Figure 1).

Figure 1 Microsoft Directory Services Programming Architecture (Click the image for a larger view)
Still, developers missed some of the strongly typed interfaces in ADSI that they had used for managing security principals, such as Users and Groups. You could perform most of these tasks using the more general classes in System.DirectoryServices, but these were not as easy to use as they should have been, and many tasks were downright obscure. Microsoft addressed this problem in the .NET Framework 3.5 by adding a new namespace designed specifically for managing security principals: System.DirectoryServices.AccountManagement. (We'll refer to System.DirectoryServices.AccountManagement as the AccountManagement namespace throughout this article.)
This new namespace has three primary goals: to simplify principal management operations across the three directory platforms, to make principal management operations consistent regardless of the underlying directory, and to provide reliable results for these operations so you are not required to know each and every one of the caveats and special cases.
By waiting a few years for the .NET landscape to gel, Microsoft has actually outdone its previous work in ADSI by providing an even better API for these features that takes advantage of .NET capabilities while also providing much better support for new directory platforms such as AD LDS.

Directory Services Programming Architecture
Before you continue, see this article's code download for prerequisites you should already have in place in order to use these techniques. Now let's begin. Figure 1 depicts the overall programming architecture of System.DirectoryServices. The AccountManagement namespace, like the ActiveDirectory namespace, is an abstraction layer on top of System.DirectoryServices. And System.DirectoryServices is itself an abstraction layer on top of ADSI. The AccountManagement namespace also relies on the Protocols namespace for a small set of its features, such as high-performance authentication. The dark blue shading in Figure 1 shows the parts of the directory services programming architecture on which AccountManagement relies.
Figure 2 shows key types in the AccountManagement namespace. Unlike the namespaces added in the .NET Framework 2.0, AccountManagement has a relatively small surface area. With the exception of some supporting types, such as enumerations and exception classes, the namespace is composed of three primary components: a tree of Principal-derived classes representing strongly typed User, Group, and Computer objects; a PrincipalContext class used to establish a connection to the underlying store; and a PrincipalSearcher class (with supporting types) used for finding objects in the directory.

Figure 2 Key Classes in System.DirectoryServices.AccountManagement (Click the image for a larger view)
Under the hood, the AccountManagement namespace uses a provider design pattern for operating over the three supported directory platforms. As a result, the members of the various Principal classes behave similarly, regardless of the underlying directory store. This design is the key to providing simplicity and consistency.

Establishing Context
You use the PrincipalContext class to establish a connection to the target directory and specify credentials for performing operations against the directory. This approach is similar to how you would go about establishing context with the DirectoryContext class in the ActiveDirectory namespace.
The PrincipalContext constructor has a variety of overloads for providing the exact options you need for establishing context. If you've worked with the DirectoryEntry class in System.DirectoryServices, many of the PrincipalContext options will look familiar. However, three of the PrincipalContext options—ContextType, name, and container—are much more specific than the input parameters you use with the DirectoryEntry class. This specificity ensures that you use proper input parameter combinations. In System.DirectoryServices and ADSI, these three parameters of the PrincipalContext constructor are combined into a single string called the path. With these components separated, it's easier to understand what is intended by each and every part of the path.
You use the ContextType enum to specify the type of target directory: Domain (for Active Directory Domain Services), ApplicationDirectory (for AD LDS), or Machine (for the local SAM database). In contrast, when using System.DirectoryServices, you use the provider component of the path string (typically "LDAP" or "WinNT") to specify the target store. ADSI then reads this value under the hood to load the appropriate provider.
The classes in the AccountManagement namespace make this task easier and more consistent by ensuring that you only use providers supported by the Framework. It also avoids annoying provider misspellings and incorrect case issues common in ADSI and System.DirectoryServices programming. That said, AccountManagement does not support less popular ADSI providers, such as IIS and Novell Directory Services.
You use the name parameter on the PrincipalContext constructor in order to provide the name of the specific directory to connect to. This can be the name of a specific server, machine, or domain. It's important to note that if this parameter is null, AccountManagement will attempt to determine a default machine or domain for the connection based on your current security context. However, if you want to connect to an AD LDS store, you must specify a value for the name parameter.
The container parameter allows you to specify the target location in the directory for establishing context. You must not specify this parameter when using Machine ContextType, as the SAM database is not hierarchical. Conversely, you must provide a value when using ApplicationDirectory since AD LDS does not publish a defaultNamingContext attribute to be used when trying to infer the directory root object. This parameter is optional with Domain ContextType, and if it's not specified, AccountManagement will use defaultNamingContext.
The additional parameters (username, password, and the ContextOptions enum) let you supply plain text credentials if necessary and specify the various connection security options to be used.
All of the directories support the Windows Negotiate authentication method. If no option is specified for the Machine store, Windows Negotiate authentication is used. The default for Domain and ApplicationDirectory, however, is Windows Negotiate with both signing and sealing.
Note that Active Directory Domain Services and AD LDS also support LDAP simple bind. You generally want to avoid using this with Active Directory Domain Services, but it may be necessary with AD LDS if you want a user in the AD LDS store to perform principal operations.
If you specify null for the user name or password parameters, AccountManagement will use the current Windows security context. If you do specify credentials, the formats supported for user name are SamAccountName, UserPrincipalName, and NT4Name. Figure 3 shows three ways to establish context.
Figure 3 Three Examples of Establishing Context
// create a context for a domain called Fabrikam pointed
// to the TechWriters OU and using default credentials
PrincipalContext domainContext = new PrincipalContext(
ContextType.Domain,"Fabrikam","ou=TechWriters,dc=fabrikam,dc=com");

// create a context for the current machine SAM store with the
// current security context
PrincipalContext machineContext = new PrincipalContext(
ContextType.Machine);

// create a context for an AD LDS store pointing to the
// partition root using the credentials for a user in the AD LDS store
// and SSL for encryption
PrincipalContext ldsContext = new PrincipalContext(
ContextType.ApplicationDirectory, "sea-dc-02.fabrikam.com:50001",
"ou=ADAM Users,o=microsoft,c=us",
ContextOptions.SecureSocketLayer ContextOptions.SimpleBind,
"CN=administrator,OU=ADAM Users,O=Microsoft,C=US ", "pass@1w0rd01");

There is another subtle but important distinction between the AccountManagement PrincipalContext and the System.DirectoryServices DirectoryEntry classes when the bind operation occurs. PrincipalContext connects and binds to the underlying directory upon object creation, whereas DirectoryEntry doesn't bind until you perform another operation that forces the connection. As a result, with PrincipalContext, you get immediate feedback about whether a connection is successfully bound to a directory.

Creating a User Account
Now you should have a fairly good understanding of how AccountManagement uses PrincipalContext to connect and bind to a container. Next we will discuss a typical DirectoryServices operation—creating a user account. In the process, each code sample assigns a value to one mandatory attribute, adds two optional attributes, sets a password, enables the user account, and commits the changes to the directory.
Here we use the domainContext variable that was introduced in example 1 of Figure 3 to create a new UserPrincipal:
// create a user principal object
UserPrincipal user = new UserPrincipal(domainContext,
"User1Acct", "pass@1w0rd01", true);

// assign some properties to the user principal
user.GivenName = "User";
user.Surname = "One";

// force the user to change password at next logon
user.ExpirePasswordNow();

// save the user to the directory
user.Save();
The domainContext establishes the connection to the directory and the security context used to perform the operation. Then, in a single line of code, we create a new user object, set the password, and enable it. After that, we use the GivenName and Surname properties to set the corresponding directory attributes in the underlying store. Before saving the object to the underlying directory store, the password expires, forcing the user to change the password upon first logon.
By comparison, Figure 4 demonstrates the equivalent steps required to create a user account in System.DirectoryServices. The container variable in the first code line is a DirectoryEntry class object, which uses a path for its connection. The path specifies the provider, a domain, and container (TechWriters OU). It also connects using the current user's security context. The container variable is similar to the domainContext in the previous example of creating a user principal.
Figure 4 Create an Account with System.DirectoryServices
DirectoryEntry container =
new DirectoryEntry("LDAP://ou=TechWriters,dc=fabrikam,dc=com");
// create a user directory entry in the container
DirectoryEntry newUser = container.Children.Add("cn=user1Acct", "user");

// add the samAccountName mandatory attribute
newUser.Properties["sAMAccountName"].Value = "User1Acct";

// add any optional attributes
newUser.Properties["givenName"].Value = "User";
newUser.Properties["sn"].Value = "One";

// save to the directory
newUser.CommitChanges();

// set a password for the user account
// using Invoke method and IadsUser.SetPassword
newUser.Invoke("SetPassword", new object[] { "pAssw0rdO1" });

// require that the password must be changed on next logon
newUser.Properties["pwdLastSet"].Value = 0;

// enable the user account
// newUser.InvokeSet("AccountDisabled", new object[]{false});
// or use ADS_UF_NORMAL_ACCOUNT (512) to effectively unset the
// disabled bit
newUser.Properties["userAccountControl"].Value = 512;

// save to the directory
newUser.CommitChanges();

Aside from the fact that this code is quite a bit longer than the AccountManagement example, it is also more complex. We need to know more about the underlying data model in the directory and we need to know how to handle certain account management features, such as setting an initial password and enabling a user object by undoing the disabled flag. This gets a bit clunky when you have to use the reflection-based Invoke and InvokeSet methods to call underlying ADSI COM interface members. It is this complexity that has made directory services programming so frustrating for many developers.
In addition, if we were trying to create the same user account in AD LDS or the local SAM database, there would have been even more differences. AD LDS and Active Directory Domain Services use a different mechanism for enabling user accounts (the msds-userAccountDisabled attribute in AD LDS rather than the userAccountControl attribute in Active Directory Domain Services), while the SAM store requires you to call an ADSI interface member. This lack of consistency among the account management features of the three directory stores was one of the key design challenges that the AccountManagement namespace had to overcome. Now, by simply changing the PrincipalContext used to create the UserPrincipal object, you can easily switch between directory stores and get one consistent set of account management features.
The Protocols namespace introduced in the .NET Framework 2.0 doesn't address any of these needs. Its purpose is to provide systems-level LDAP programmers with a more powerful and flexible API for building LDAP-based applications. However, it provides even less abstraction over the LDAP model than System.DirectoryServices, and it does nothing to simplify the differences among various directories. In addition, it is not intended for use with the local SAM database (which is not an LDAP directory). The online code samples that accompany this article include a sample similar to the AccountManager example following Figure 3. It performs the same task but takes three times as many lines of code.
The PrincipalContext in Figure 5 shows the ContextType enumeration referring to a machine in order to target a SAM store. The next parameter targets the actual machine by name (or IP address), and the last two values provide the credentials of an account that can perform the account creation.
Figure 5 Creating a SAM Database User Account
PrincipalContext principalContext = new PrincipalContext(
ContextType.Machine. "computer01", "adminUser", "adminPassword");

UserPrincipal user = new UserPrincipal(principalContext,
"User1Acct", "pass@1w0rd01", true);

//Note the difference in attributes when accessing a different store
//the attributes appearing in IntelliSense are not derived from the
//underlying store
user.Name = "User One";
user.Description = "User One";
user.ExpirePasswordNow();
user.Save();
We set the Name and Description properties because the SAM store does not contain givenName, sn, or displayName attributes, as in Active Directory Domain Services. Even though AccountManagement attempts to provide a consistent experience across all three directory stores, there are differences in the underlying models. However, it will throw an InvalidOperationException if you attempt to get an attribute that is not available in the underlying store.
Figure 3 and Figure 5 are two examples of creating user accounts; they show the consistent programming model inherent in the AccountManagement namespace when operating against any store. The PrincipalContext in Figure 6 uses ContextType.ApplicationDirectory to target an AD LDS store, as was shown in Figure 3. The next parameter shows the AD LDS server. In this case, sea-dc-02.fabrikam.com is the Fully Qualified Domain Name (FQDN) of the server hosting the AD LDS instance, and the instance is listening on port 50001 for SSL communications. Note that the code download uses non-SSL communications over port 50000. This is not secure but is fine for your own testing.
Figure 6 Creating an ADAM or AD LDS User Account
PrincipalContext principalContext = new PrincipalContext(
ContextType.ApplicationDirectory,
"sea-dc-02.fabrikam.com:50001",
"ou=ADAM Users,o=microsoft,c=us",
ContextOptions.SecureSocketLayer ContextOptions.SimpleBind,
"CN=administrator,OU=ADAM Users,O=Microsoft,C=US",
"P@55w0rd0987");

UserPrincipal user = new UserPrincipal(principalContext,
"User1Acct", "pass@1w0rd01", true);

user.GivenName = "User";
user.Surname = "One";

user.Save();

The next parameter designates the container where you want to perform a CRUD (Create/Read/Update/Delete) operation. This example specifies a user stored in AD LDS for performing our CRUD operations, so it must use an LDAP simple bind, and it's combined with SSL for security. Even though AD LDS supports secure DIGEST authentication natively, ADSI itself does not. Once again, our example is practically identical to the two previous examples with only the PrincipalContext being significantly different.
The AccountManagement namespace provides a comprehensive set of account management features such as password expiration and account unlock. We don't have space here to demonstrate all of them, but the bottom line is that they work consistently and reliably across directory stores, and they take the hassle out of implementing such capabilities.

Creating Groups and Computers
You've seen that creating a user account is simple and consistent from one DirectoryServices store to another. This consistency extends to creating the other two supported DirectoryServices objects, groups, and computers. Like the UserPrincipal class, the GroupPrincipal and ComputerPrincipal classes inherit from the Principal abstract class and operate similarly. For example, to create a group named Group01 in Active Directory Domain Services, AD LDS, or the SAM account database, you can use this code:
GroupPrincipal group = new GroupPrincipal(principalContext,
"Group01");
group.Save();
In each case, differences are contained in the PrincipalContext class that establishes context with the different stores. The code used to create a computer object follows a similar pattern of creating the principal object using a context and then saving the object to the target of the principal context:
ComputerPrincipal computer = new ComputerPrincipal(domainContext);
computer.DisplayName = "Computer1";
computer.SamAccountName = "Computer1$";
computer.Enabled = true;
computer.SetPassword("p@ssw0rd01");
computer.Save();
Once again, AccountManagement takes care of unifying the interaction model for all of the supported identity stores. This sample shows the proper syntax for creating a computer object that can be joined to the domain (which requires a trailing $ in the sAMAccountName attribute) but sets the display name and common name so the $ is not included. Note that since the SAM database and AD LDS do not contain the computer class, AccountManagement will only allow you to create this type of object inside a domain-based PrincipalContext. Additionally, only Active Directory Domain Services contains a variety of group scopes—global, universal, and domain local—and contains both security and distribution groups. Therefore, the GroupPrincipal class provides nullable properties that allow you to set these values when necessary.

Managing Group Membership
The AccountManagement namespace also simplifies managing group membership. Before AccountManagement, there were lots of idiosyncrasies and inconsistencies among managing groups in different stores. Managing groups with many members was programmatically difficult. In addition, you had to use COM interop to manage SAM group membership and use LDAP attributes to manage Active Directory Domain Services and AD LDS groups. But now, the Members property of the GroupPrincipal class lets you enumerate a group's membership and manage its members. It all just works.
Another seemingly simple operation that is actually difficult to achieve is getting all the groups to which a user belongs. AccountManagement provides several methods to help you. The Principal base class includes two GetGroups methods and two IsMemberOf methods that, respectively, get the group membership of any Principal type and check to see if that principal is a member of a group. Also, UserPrincipal provides a special GetAuthorizationGroups method that returns the fully expanded security group membership of any UserPrincipal type. Figure 7 shows how you can use the GetAuthorizationGroups method.
Figure 7 Using the GetAuthorizationGroups Method
string userName = "user1Acct";

// find the user in the identity store
UserPrincipal user =
UserPrincipal.FindByIdentity(
adPrincipalContext,
userName);

// get the groups for the user principal and
// store the results in a PrincipalSearchResult object
PrincipalSearchResult results =
user.GetAuthorizationGroups();

// display the names of the groups to which the
// user belongs
Console.WriteLine("groups to which {0} belongs:", userName);
foreach (Principal result in results)
{
Console.WriteLine("name: {0}", result.Name);
}

Yet another tricky operation made simple with AccountManagement is the task of expanding group membership across trusted domains or with foreign security principals. The GetGroups(PrincipalContext) method on the Principal class does the heavy lifting for you.

Finding Ourselves
Another task programmers often struggle with is finding objects in the directory. While LDAP is not a particularly complex query language compared to the syntaxes that developers tackle routinely, it is nonetheless unfamiliar. Additionally, even if you know the rudiments of LDAP, it is often difficult to figure out how to use it to perform common tasks.
Once again, AccountManagement makes these tasks a breeze by helping you find objects with the FindByIdentity method. This method is part of the Principal abstract class from which the UserPrincipal, GroupPrincipal, and ComputerPrincipal classes inherit. Therefore, whenever you need to search for one of these principal types, FindByIdentity is a good friend to have.
FindByIdentity contains two overloads, both of which take a PrincipalContext and value to find. For the value, you can specify any of the supported identity types: SamAccountName, Name, UserPrincipalName, DistinguishedName, Sid, or Guid. The second overload also allows you to explicitly define the identity type you will specify as the value.
Starting with the simpler overload, here's how you can go about using FindByIdentity to return the user account we created in the previous examples:
UserPrincipal user = UserPrincipal.FindByIdentity(principalContext, "user1Acct");
Once you have a context (stored in the principalContext object), you use the FindByIdentity method to retrieve the principal object, in this case a UserPrincipal. After establishing context to any supported identity store, the code for finding the identity is always the same.
The second FindByIdentity constructor allows you to be explicit about the identity format you will specify. When you use this constructor, you must match the value's format to the identity type you specify. For instance, this code will properly return a UserPrincipal using its distinguished name provided the object exists in the directory and in the specified location:
UserPrincipal user = UserPrincipal.FindByIdentity(
adPrincipalContext,
IdentityType.DistinguishedName,
"CN=User1Acct,OU=TechWriters,DC=FABRIKAM,DC=COM");
In contrast, this code will not return a UserPrincipal since the IdentityType enumeration specifies a DistinguishedName format, but the value is not in this format:
UserPrincipal user = UserPrincipal.FindByIdentity(
adPrincipalContext,
IdentityType.DistinguishedName,
"user1Acct");
Format is important. For example, if you decide to use the GUID or SID IdentityTypes, you must use the standard COM GUID format and the Security Descriptor Description Language (SDDL) format, respectively, for the value. The code download for this article provides two methods (FindByIdentityGuid and FindByIdentitySid) that show the proper format. Note that you must change the GUID or SID values in these methods in order to find a match in your directory store. Obtaining either format is easy using the PrincipalSearcher class, as we'll show you in just a moment.
Now that you've found a Principal object and bound to it, you can easily perform operations on it. For example, you can add a user to a group, like so:
// get a user principal
UserPrincipal user =
UserPrincipal.FindByIdentity(adPrincipalContext, "User1Acct");
// get a group principal
GroupPrincipal group =
GroupPrincipal.FindByIdentity(adPrincipalContext, "Administrators");
// add the user
group.Members.Add(user);
// save changes to directory
group.Save();
Here, we use the FindByIdentity method to first find a user and then a group. Once the code obtains these principal objects, we call the Add method of the group's Members property to add the user principal to the group. Finally, we call the group's Save method to save the change to the directory.

Finding Matches
You can also use the powerful Query by Example (QBE) facility and the PrincipalSearcher class to find an object based on defined criteria. We will explain more about QBE and the PrincipalSearcher class, but first we want to examine a simple search example. Figure 8 shows how you can find all user accounts beginning with a name/cn prefix of "user" that are disabled.
Figure 8 Using PrincipalSearcher
// create a principal object representation to describe
// what will be searched
UserPrincipal user = new UserPrincipal(adPrincipalContext);

// define the properties of the search (this can use wildcards)
user.Enabled = false;
user.Name = "user*";

// create a principal searcher for running a search operation
PrincipalSearcher pS = new PrincipalSearcher();

// assign the query filter property for the principal object
// you created
// you can also pass the user principal in the
// PrincipalSearcher constructor
pS.QueryFilter = user;

// run the query
PrincipalSearchResult results = pS.FindAll();

Console.WriteLine("Disabled accounts starting with a name of 'user':");
foreach (Principal result in results)
{
Console.WriteLine("name: {0}", result.Name);
}

The PrincipalContext variable, adPrincipalContext, points to an Active Directory domain, but it could just as easily point to an AD LDS application partition. After establishing context, notice that the code creates a new UserPrincipal object. This is an in-memory representation of the principal for the search operation. Once you've created this principal, you then set the properties that limit the search results. The next two code lines demonstrate some limits you can set—all disabled user accounts where the user name begins with some value. Note that the property value for the Name attribute supports wildcards.
If you're already familiar with the LDAP dialect for setting up search filters, you'll immediately appreciate why QBE is a novel and more intuitive alternative. With QBE, you set up an example object that you then use for the query operation. To clearly demonstrate that QBE is simpler than the typical DirectoryServices search dialect, here's the LDAP dialect for setting up a filter equivalent to the QBE object created in Figure 8:
(&(objectCategory=person)(objectClass=user)(name=user*)(userAccount
Control:1.2.840.113556.1.4.803:=2))
As you can see, the LDAP dialect is quite a bit more complicated, and it won't work for AD LDS because the Active Directory LDS user schema uses the msDS-UserAccountDisabled attribute instead of the userAccountControl attribute shown in the LDAP dialect. Once again, AccountManagement handles these differences for us behind the scenes.
After setting up the QBE object shown in Figure 8, we create a PrincipalSearcher object and assign its QueryFilter property that the Principal object created earlier in the code. Note that you can also pass the user principal in the PrincipalSearcher constructor, rather than setting the QueryFilter property. We then run the query, calling the FindAll method of the PrincipalSearcher and assigning the returned results to the PrincipalSearchResult generic list. The PrincipalSearchResult list stores the returned Principal objects. Lastly, the code enumerates the list of principals and displays the Name attribute of each returned principal.
Note that QBE does not work for referential attributes. That is, attributes that are not owned by the QBE object cannot be used to configure your in-memory representation of the object.
You can do a lot more in the foreach loop. For example, you can enable the disabled user accounts or delete them. If you're after just read operations, keep in mind that if you do point to some other identity store, the attributes you return must exist in that store. For example, since an AD LDS user doesn't contain the sAMAccountName attribute, it wouldn't make sense to try to return this attribute in the results.

Difficult Search Operations Made Easy
There are other powerful FindBy methods that, when coupled with the PrincipalSearchResult class, can retrieve information about user and computer principals that is otherwise difficult to retrieve. Figure 9 demonstrates how to retrieve the name of each user who changed his password today. This example uses the FindByPasswordSetTime method and the PrincipalSearchResult class. Without AccountManagement, this operation is complicated because the underlying pwdLastSet attribute is stored in the directory as a Large Integer.
Figure 9 Retrieving Users Who Reset Their Password Today
// get today's date
DateTime dt = DateTime.Today;

// run a query
PrincipalSearchResult results =
UserPrincipal.FindByPasswordSetTime(
adPrincipalContext,
dt,
MatchType.GreaterThanOrEquals);

Console.WriteLine("users whose password was set on {0}",
dt.ToShortDateString());
foreach (Principal result in results)
{
Console.WriteLine("name: {0}", result.Name);
}

The code download for this article contains examples of using other FindBy methods. They all operate similarly to that which we've shown you in Figure 9.
FindBy methods are convenient shortcuts to information that is otherwise hard to retrieve. However, they are not appropriate if you need to further filter the results using the QBE facility. An important nuance here is that the associated attribute is read-only and therefore cannot be set on a QBE object, just as it cannot be set by a user on the object to which the QBE refers. To use the QBE, you use the equivalent read-only property in your example principal object combined with the AdvancedSearchFilter property. More about that will come later. Figure 10 lists more FindBy methods and shows the equivalent read-only properties that you can use instead of the FindBy method in a search.
Figure 10 Other FindBy Methods

Method Name Read-Only Property Description
FindByLogonTime LastLogonTime Accounts that have logged on within the specified time.
FindByExpirationTime AccountExpirationDate Expired accounts within the specified time.
FindByPasswordSetTime LastPasswordSetTime Accounts whose password was set within the specified time.
FindByLockoutTime AccountLockoutTime Accounts locked out within the specified time.
FindByBadPasswordAttempt LastBadPasswordAttempt Bad password attempts within the specified time.
No equivalent method BadLogonCount Accounts that have attempted to logon the specified number of times but have failed to logon.
You can't set a value on a read-only property when configuring a QBE. So how can you work with the property in a search operation? You can retrieve a result set and then perform a conditional test using the read-only property when enumerating the result set. Just keep in mind that this approach is not advisable for potentially large resultsets since the code must first retrieve results unfiltered for the read-only property and then filter the returned resultset by the read-only property. The PrincipalSearchEx6v2 method in the code download demonstrates this less-than-ideal approach.
The Directory Services team addressed this QBE limitation by adding the AdvancedSearchFilter property to the AuthenticablePrincipal class. AdvancedSearchFilter allows you to search based on the read-only properties and then combine them with other properties you can set using the QBE mechanism. Figure 11 demonstrates how you can use the LastBadPasswordAttempt read-only property of the UserPrincipal class to return a list of users who had a bad password attempt today.
Figure 11 AdvancedSearchFilter with a Read-Only Property
DateTime dt = DateTime.Today;

// create a principal object representation to describe
// what will be searched
UserPrincipal user = new UserPrincipal(adPrincipalContext);

user.Enabled = true;

// define the properties of the search (this can use wildcards)
user.Name = "*";

//add the LastBadPasswordAttempt >= Today to the query filter
user.AdvancedSearchFilter.LastBadPasswordAttempt
(dt, MatchType.GreaterThanOrEquals);

// create a principal searcher for running a search operation
// and assign the QBE user principal as the query filter
PrincipalSearcher pS = new PrincipalSearcher(user);

// run the query
PrincipalSearchResult results = pS.FindAll();

Console.WriteLine("Bad password attempts on {0}:",
dt.ToShortDateString());
foreach (UserPrincipal result in results)
{
Console.WriteLine("name: {0}, {1}",
result.Name,
result.LastBadPasswordAttempt.Value);
}


Authenticating Users
Developers who build directory-based applications often need to authenticate the credentials of users stored in the directory, especially when using AD LDS. Before the .NET Framework 3.5, programmers accomplished this task using the DirectoryEntry class in System.DirectoryServices to force an LDAP bind operation under the hood. However, be careful: it is exceedingly easy to write poor versions of this code that are not secure, that are slow, or that are just plain clunky. Additionally, ADSI itself is not designed for this type of operation and can fail under high-use conditions due to the way it caches LDAP connections internally.
As we've already discussed, the System.DirectoryServices.Protocols assembly in the .NET Framework 2.0 contains lower-level LDAP classes that use a connection-based programming metaphor. This design allows you to overcome the inherent limitations in ADSI but at the expense of having to write more complicated code.
In the .NET Framework 3.5, AccountManagement delivers both the power and ease of use offered by the ActiveDirectoryMembershipProvider implementation in ASP.NET to programmers working in any environment. Additionally, the AccountManagement namespace allows you to authenticate credentials against the local SAM database if needed.
The two ValidateCredentials methods on the PrincipalContext class provide credential validation. You first create an instance of a PrincipalContext using the directory you wish to validate against and specify the appropriate options. After getting context, you test whether ValidateCredentials returns true or false based on the supplied user name and password values. Figure 12 shows an example of authenticating a user in AD LDS.
Figure 12 Authenticating a User in AD LDS
// establish context with AD LDS
PrincipalContext ldsContext =
new PrincipalContext(
ContextType.ApplicationDirectory,
"sea-dc-02.fabrikam.com:50000",
"ou=ADAM Users,O=Microsoft,C=US");

// determine whether a user can validate to the directory
Console.WriteLine(
ldsContext.ValidateCredentials(
"user1@adam",
"Password1",
ContextOptions.SimpleBind +
ContextOptions.SecureSocketLayer));

This approach is most useful when you want to validate many different sets of user credentials quickly and efficiently. You create a single PrincipalContext object for the directory store in question and reuse that object instance for each call to ValidateCredentials. The PrincipalContext can reuse the connection to the directory, which results in good performance and scalability. And calls to ValidateCredentials are thread-safe, so your instance can be used across threads for this operation. It's important to note that the credentials used to create the PrincipalContext are not changed by calls to ValidateCredentials—the context and method call maintain separate connections.
By default, AccountManagement uses secure Windows Negotiate authentication and attempts to use SSL when performing a simple bind against AD LDS. We recommend that you always be explicit with the type of authentication you want to perform and the connection protection you wish to use (if applicable), but at least the defaults err on the side of caution.
Active Directory Domain Services in Windows Server® 2003 and later and AD LDS both include fast concurrent binding, which is designed for high-performance authentication operations. It validates a user's password without actually building a security token for the user. Unlike in a normal bind operation, with fast concurrent binding the state of the LDAP connection remains unbound. You can use fast concurrent binding to perform bind operations on the same connection repeatedly and simply check for a failed password attempt. This feature is not an available option through ADSI or System.DirectoryServices, but it is exposed as an option in the Protocols namespace.
AccountManagement uses fast concurrent binding whenever possible and enables this option automatically. This is the reason that the AccountManagement layer also appears above the Protocols layer in Figure 1. Note that it only works in simple bind mode, which passes plain text credentials on the network. Therefore, fast concurrent binding should always be combined with SSL for security.

Extensibility Model
Directory Services Resources
.NET Framework 3.5 Beta 2 Download
System.DirectoryServices.AccountManagement Namespace Overview
System.DirectoryServices.AccountManagement Namespace Documentation
About Active Directory Lightweight Directory Services
Windows Server 2003 Active Directory Application Mode
Introduction to System.DirectoryServices.Protocols
Introduction to System.DirectoryServices.ActiveDirectory

Another area where AccountManagement really shines is its extensibility model. Many developers will choose to use the various Principal-derived classes for building custom provisioning systems for both Active Directory Domain Services and AD LDS. In many cases (especially with AD LDS), an organization will add custom schema extensions to the directory to support its own metadata for users and groups.
Using the .NET Framework object-oriented design and attribute-based extensible metadata, AccountManagement makes it easy to create custom security principal classes that support your custom schema. By simply inheriting from one of the Principal-derived classes and marking your class and properties with the appropriate attributes, your custom principal class can read and write these directory attributes as well as the attributes already supported by the built-in types.
An important nuance worth noting is that the extensibility mechanism provided by AccountManagement is designed for use by security principals stored in Active Directory Domain Services or AD LDS. It doesn't have a focus on non-Microsoft LDAP directories. If you wish to build a framework for provisioning in non-Microsoft LDAP directories, you should use the lower-level classes in the Protocols namespace. (In addition, the extensibility model is not intended for use with local SAM accounts, as the SAM schema is not extensible.)
Consider an AD LDS directory that uses the standard LDAP user class for storing security principals for an application. In addition, the LDAP directory schema is extended to support a special attribute for identifying user objects called msdn-subscriberID. Figure 13 demonstrates how to create a custom class that can provision user objects and also provide create, read, and write operations against this attribute.
Figure 13 Our Sample MsdnUser Class
[DirectoryObjectClass("user")]
[DirectoryRdnPrefix("CN")]
class MsdnUser : UserPrincipal
{
public MsdnUser(PrincipalContext context)
: base(context) { }

public MsdnUser(
PrincipalContext context,
string samAccountName,
string password,
bool enabled
)
: base(
context,
samAccountName,
password,
enabled
)
{
}

[DirectoryProperty("msdn-subscriberID")]
public string MsdnSubscriberId
{
get
{
object[] result = this.ExtensionGet("msdn-subscriberID");
if (result != null) {
return (string)result[0];
}
else {
return null;
}
}
set { this.ExtensionSet("msdn-subscriberID", value); }
}
}

Notice that the code inherits from the UserPrincipal class and is decorated with two attributes: DirectoryObjectClass and DirectoryRdnPrefix. Both of these attributes are required for principal extension classes. The DirectoryObjectClass attribute determines the value the supported store (Active Directory Domain Services or AD LDS) uses for the objectClass directory attribute when creating instances of this object in the directory. Here, this is still the default AD LDS user class, but in reality it could be anything. The DirectoryRdnPrefix attribute determines the RDN (relative distinguished name) attribute name to use for naming objects of this class in the directory. Under Active Directory Domain Services, you cannot change the RDN prefix—it is always CN for security principal classes. Under AD LDS, however, there is more flexibility and you can use a different RDN if desired.
Our class has a property called MsdnSubscriberID that returns a string. This class is marked with the DirectoryProperty attribute, specifying the LDAP schema attribute used to store the property value. The underlying framework uses this value for optimizing search operations against this Principal type.
Our property get and set implementations use the protected ExtensionGet and ExtensionSet methods of the Principal base class to read and write values to the underlying property cache. These methods support storing values in memory for objects that have not yet been persisted to the database/identity store. In addition, these methods support reading and writing values from existing objects. Since LDAP directories support attributes of various types and also allow an attribute to contain multiple values, these methods use the object[] type for reading and writing values. This flexibility is nice, but if you want to provide a strongly typed scalar string value on top of an array of object types, you have to do a little extra work, as our implementation demonstrates. The result for consumers of our custom MsdnUser class is an interface that is very easy to program.
The ability to provide strongly typed values on top of our directory schema is one of the most useful features of this extensibility model. Beyond simple string types, you can also use the rich type system offered by the .NET Framework to do such things as represent the Active Directory Domain Services jpgPhoto attribute as a System.Drawing.Image or a System.IO.Stream instead of the default byte[] that you would usually get by reading the value from System.DirectoryServices.
The code download for this article provides a few more samples to demonstrate these capabilities. It also has some schema extensions (via a standard LDIF formatted file, msdnschema.ldf) that you can use to extend your test directory with the MsdnUser class. We also provided some valuable links in the "Directory Services Resources" sidebar.

Final Thoughts
AccountManagement is a much-needed managed code addition to the rich directory services programming model offered by Microsoft. With the AccountManagement namespace, developers now have a set of strongly typed principals for common CRUD and search operations.
The namespace encapsulates directory service programming best practices to help you write secure and high-performance managed code. In addition, AccountManagement is extensible, allowing you to fully interact with your custom directory objects in Active Directory Domain Services and AD LDS.

Thursday, 4 March 2010

Design Patterns Links

http://www.c-sharpcorner.com/UploadFile/questpond/DP109212008014904AM/DP1.aspx

http://www.dofactory.com/Patterns/Patterns.aspx

http://www.techfaq360.com/oops_interview_questions.jsp

http://www.codeproject.com/KB/aspnet/SoftArchInter1.aspx

Wednesday, 3 March 2010

FAQ's - DotNet Framework

What is CLR? Who loads the CLR into a process?

Common Language Runtime - It is the implementation of CLI(Common Language Infrastructure). The core runtime engine in the Microsoft .NET Framework for executing applications. The common language runtime supplies managed code with services such as cross-language integration, code access security, object lifetime management, resouce management, type safety, pre-emptive threading, metadata services (type reflection), and debugging and profiling support. The ASP.NET Framework and Internet Explorer are examples of hosting CLR. The CLR is a multi-language execution environment. There are currently over 15 compilers being built by Microsoft and other companies that produce code that will execute in the CLR. 
The CLR is described as the "execution engine" of .NET. It's this CLR that manages the execution of
programs. It provides the environment within which the programs run. The software version of .NET is
actually the CLR version.

What is an Application Domain?Application domains help in providing isolation, unloading, and security boundaries for executing managed code. These Application Domains are very similar to the operating system concept Process. The isolation of applications is achieved using Application Domains. This will help them to see that they do not affect each other.

What is a GC?In C#, Garbage Collector will collect variables(Weak & no reference objects) from generations. Initially, when a variable is declared, it will be into generation 0, When GC is collecting variables for garbage collection, it will move all variables which are uncollected to its higher generation. So, all uncollected variables in Generation 0 will move to Generation 1 and Generation 1 variables to Generation 2. Currently Garbage collector has 3 generations, Generation 0,Generation 1 and Generation 2.You can find maximum number of generations that CLR will have by using1.System.GC.MaxGeneration

What is a CTS and CLS?
• CTS (Common Type System)It defines “How object should be declared”. CLS is the subset of CTS.


• CLS (Common Language Specification)It provides, set of specification TO BE adhered by new language writer/compiler writer for .Net Framework to ENSURE interoperability. ‘cause .net supports 32 languages.For example Asp.Net application written in C#.Net language. Now we can refer any other DLL which has been written in any other language supported by .Net Frame Work.

What is GAC?The Global Assembly Cache (GAC) stores assemblies specifically designated to be shared by several applications on the computer. Assemblies deployed in the global assembly cache must have a strong name. When an assembly is added to the global assembly cache, integrity checks are performed on all files that make up the assembly. GAC physically creates directories for each version of the assembly. The Global Assembly Cache (GAC), when viewed using Explorer, has its view rendered in a special manner by the OS shell. When an Assembly is added to GAC these are the attributes that it takes.
• Assembly Name – Name of the Assembly
• Version – Version [Major-Minor-Revision-Build]
• Culture – Culture will be null for normal Assembly
• Public Key Token - This is a 64-bit hash of the public key which makes the assembly name unique.
• Processor Architecture – Either MSIL or x86

What is an Assembly?
An assembly is a basic building block for any application in the .NET Framework. It is a fundamental unit of deployment, version control, reuse, activation scoping, and security permissions. An assembly is a collection of types and resources that are built to work together and form a logical unit of functionality. An assembly provides the Common Language Runtime (CLR) with the information it needs to be aware of type implementations. During runtime, a type does not exist outside the context of an assembly.
The contents of an assembly are the following.
• CIL – Common Intermediate Language (formerly MSIL - Microsoft Intermediate Language)
• Assembly Manifest – The Assembly Manifest has the information like Name, Version number, Culture, Strong Name information, etc.
• Type Metadata
• Resources

What are the different types of assemblies?
1) Private Assembly
2) Public/Shared Assembly
3) Satellite Assembly

What is a Shared Assembly?
Shared Assemblies are kept in Global Assembly Cache. Client application using Shared Assemblies need not have its own copy of dll. Shared Assemblies are present in C:\WINDOWS\assembly folder.
Steps to create Shared Assembly:
1. Create a .dll file. (Here i am using my existing HappyNewYear.dll)2. Now let me create unique assembly name using SN utility(Shared Name utility).  The syntax for it is: sn -k filename.snk
Here sn stands for strong name, -k stands for key and key is stored in filename.snk .


What is a Satellite Assembly?
Satellite Assembly is a .NET Framework assembly containing resources specific to a given language. Using a satellite assembly, we can place resources of different languages in different assemblies and the correct assembly is loaded into memory only if the user elects to view the application in that language.

What is a .NET module? How is a .NET module different from an Assembly?
A .NET module is a portable executable file of type.dll or .exe consisting of one or more classes. This is similar to a .NET assembly which consists of classes, namespaces, etc.
A .NET module can not be deployed alone. It has to be linked into an assembly. This can be done by using compiler’s /add module switch (if the compiler supports it), al.exe, or in .NET Framework 2.0, link.exe.

What is CodeDOM in .NET used for?
CodeDOM is an API that helps in creating and compiling a programming structure at Runtime. Creating a programming structure involves creation of Namespace, Type – Class, Interface and even methods at the Runtime. The implementation of CodeDOM can be divided in the two ways shown below. The namespace for the CodeDOM is System.CodeDOM.
• Compiling or Building the Programs at the Runtime
• Using CodeDOM for generating a Program structure

Meaning for Assembly Version?
1:2:3:4 -- (Major : Minor : Build : Revision)

Install/Uninstall the assembly in GAC or converting a private assembly as a shared assembly?
Ex: gacutil /i assemblyname.dll (Add)
gacutil /u assemblyname.dll (Add)

FAQ's - SQL Server

FAQ's - ASP.NET

Life cycle of ASP.NET 2.0 Page ?
Life cycle of the page is defined as the list of events that get fired from the Page initialization to page rendering. The list of events is illustrated along with the descriptions.
Name of the Event - When does the event fire
PreInit - Occurs at the beginning of page initialization.
Init - Occurs when the server control is initialized, which is the first step in its lifecycle.
InitComplete - Occurs when page initialization is complete.
PreLoad - Occurs before the page Load event.
Load - Occurs when the server control is loaded into the Page object.
PreRender - Occurs after the Control object is loaded, but prior to rendering.
PreRenderComplete - Occurs before the page content is rendered.
SaveStateComplete - Occurs after the page has completed saving all view state and control state information for the page and controls on the page.
LoadComplete - Occurs at the end of the load stage of the page's life cycle.
Unload - Occurs when the server control is unloaded from memory.

What is the Pre-Compilation feature of ASP.NET 2.0? How does the new folder structure help for the same?
By default, ASP.NET Web pages and code files are compiled dynamically when users first request a resource such as a page from the Web site. After pages and code files have been compiled the first time, the compiled resources are cached, so that subsequent requests to the same page are extremely efficient. This was in previous versions of ASP.NET, but in ASP.NET 2.0 we have a feature called as pre-compilation. With this, ASP.NET can also pre-compile an entire site before it is made available to users. We have some pre-defined folder structures for enabling this feature of pre-compilation. Let us list down some of the folders with a brief description of what they are meant for.
• App_Code – meant for storing classes
• App_Themes – meant for storing CSS files, Images, etc.
• App_Data –meant for storing XML files, Text Files, etc.
• App_GlobalResources – meant for storing all the resources at global level E.g. resx files, etc
• App_LocalResources – meant for storing all the resources at local/Page level

What is the class name for accessing the Configuration in .NET 2.0?
The class name used for accessing configuration in .NET 2.0 is ConfigurationManager. The ConfigurationManager class is a static class which has all the methods for accessing application configuration file
. For web applications we have WebConfigurationManager class. The WebConfigurationManager allows us to access machine and application information.

What is Authentication in ASP.NET?
Authentication is the process of identifying a user with identification credentials like User name and Password with some authority. Generally after authentication the system gets to know who the user is. ASP.Net has some authentication providers. Let us discuss some of them.
Windows Authentication Provider - Windows authentication in conjunction with Microsoft Internet Information Services (IIS) authentication to secure ASP.NET applications
Forms Authentication Provider – An application-specific login form and performs authentication using user code.
Passport Authentication provider – Centralized authentication service provided by Microsoft offers a single login and core profile service for member sites.

What is Authorization in ASP.NET?
Authorization determines whether an identity/user should be granted access to a specific resource. Authorization requires that the authentication is already done. There are 2 ways to authorize access to a given resource:
• File authorization - File authorization is performed by the FileAuthorizationModule. It checks the access control list (ACL) of the .aspx or .asmx handler file to determine whether a user should have access to the file.
• URL authorization - URL authorization is performed by the UrlAuthorizationModule, which maps users and roles to URLs in ASP.NET applications.
Ex:

<[allow|deny] users roles verbs />


What is the difference between Response.Redirect() and Server.Transfer()?
Redirect Method:
- Client knows about the redirection of the URL.
- ASP.net can force reauthorization by using the Redirect method instead of the Transfer method.
- Response.Redirect is little bit slower, but it retains the new URL.
- Cannot use HTTPContext.Items.

Transfer Method:
- Client does not know anything about the transfer. It appears to be the same old URL for the client.
- ASP.NET does not verify that the current user is authorized to view the resource delivered by the Transfer method. You need to have a Custom logic for the same.
- Server Transfer is faster as it reduces 1 less trip to the client.
- HTTPContext.Items are accessible.

FAQ's - C#


Does C# support multiple-inheritance?
No.

Who is a protected class-level variable available to?
It is available to any sub-class (a class inheriting this class).

Are private class-level variables inherited?
Yes, but they are not accessible. Although they are not visible or accessible via the class interface, they are inherited.

Describe the accessibility modifier “protected internal”?
It is available to classes that are within the same assembly and derived from the specified base class.

What’s the top .NET class that everything is derived from?
System.Object.

What is the difference between Int.Parse , Convert.ToInt() and Int.TryParse()?
Int32.Parse Method
Converts the string representation of a number to its 32-bit signed integer equivalent.
-When s is a null reference, it will throw ArgumentNullException.
-If s is other than integer value, it will throw FormatException.
-When s represents a number out of range, it will throw OverflowException.

Convert.ToInt32(string)
Converts the specified string representation of 32-bit signed integer equivalent. This calls in turn Int32.Parse () method.
-When s is a null reference, it will return 0 rather than throw ArgumentNullException.
-If s is other than integer value, it will throw FormatException.
-When s represents a number out of range, it will throw OverflowException.

Int32.TryParse Method
Converts the specified string representation of 32-bit signed integer equivalent to out variable, and returns true if it is parsed successfully, false otherwise.
-When s is a null reference, it will return 0.
-If s is other than an integer value, the out variable will have 0.
-When s represents a number out of range, the out variable will have 0.


What does the term immutable mean?
The data value may not be changed.
Note: The variable value may be changed, but the original immutable data value was discarded and a new data value was created in memory.

What’s the difference between System.String and System.Text.StringBuilder classes?
System.String is immutable. System.StringBuilder was designed with the purpose of having a mutable string where a variety of operations can be performed.

What’s the advantage of using System.Text.StringBuilder over System.String?
StringBuilder is more efficient in cases where there is a large amount of string manipulation. Strings are immutable, so each time a string is changed, a new instance in memory is created.

Can you store multiple data types in System.Array?
No.

What’s the difference between the System.Array.CopyTo() and System.Array.Clone()?
The Clone() method returns a new array (a shallow copy) object containing all the elements in the original array. The CopyTo() method copies the elements into another existing array. Both perform a shallow copy. A shallow copy means the contents (each array element) contains references to the same object as the elements in the original array. A deep copy (which neither of these methods performs) would create a new instance of each element's object, resulting in a different, yet identacle object.

How can you sort the elements of the array in descending order?
By calling Sort() and then Reverse() methods.

What’s the .NET collection class that allows an element to be accessed using a unique key?
HashTable.

What class is underneath the SortedList class?
A sorted HashTable.

Will the finally block get executed if an exception has not occurred?­
Yes.

What’s the C# syntax to catch any possible exception?
A catch block that catches the exception of type System.Exception. You can also omit the parameter data type in this case and just write catch {}.

Can multiple catch blocks be executed for a single try statement?
No.
Once the proper catch block processed, control is transferred to the finally block (if there are any).

Explain the three services model commonly know as a three-tier application?
Presentation (UI), Business (logic and underlying code) and Data (from storage or other sources).

What is the difference between int and Int32?
Int32 is a class of namespace System. Keyword "int" is the alias of the class. So there is no real difference.

What does mutable and immutable means?
Immutable objects (read-only) are objects whose value cannot be modified once it has been created. Methods that appear to modify an immutable object actually return a new object that contains the modification (the previous object remains in memory until garbage collected).
Mutable Objects are objects whose value can be modified.

What is the difference between String class and StringBuilder class? Which one is better?
String Class is immutable and StringBuilder class is mutable. If the object has many operations involved then StringBuilder class is a better option.

What are delegates?
A delegate in C# is similar to a function pointer in C or C++. Using a delegate allows the programmer to encapsulate a reference to a method inside a delegate object. The delegate object can then be passed to code which can call the referenced method, without having to know at compile time which method will be invoked. Unlike function pointers in C or C++, delegates are object-oriented, type-safe, and secure.

What is difference between delegates and Events?
A delegate is a reference to a method. A delegate is raw in its nature, but an event is hooked up with a control; it acts based on the behaviour of the control. An event is a delegate, but a delegate is not an event. Event = Delegate + Event handling logic.

What is a partial class?
A Partial class is a class that can be split into two or more classes. This means that a class can be physically separated into other parts of the class within the same namespace. All the parts must use the partial keyword. All the other classes should also have the same access modifier. At the compile time, all the partial classes will be treated as a single class. Let us list some advantages of having partial classes.
• Allows a clean separation of business logic layer and the user interface.
• The UI code can be hidden from the developer.
• Makes the debugging easier.

What is a Sealed Class? Where is it used?
A sealed class is a class for which there will be no derived class. The keyword sealed ensures no overriding of members.
In general all the API and framework classes are made to be sealed classes.

What are Generics?
Generics are classes, structures, interfaces, and methods that have placeholders (type parameters) for one or more of the types they store or use. Using Generics, the type safety check burden will be on the compiler rather than developer. Hence, the Developer needs to write the code explicitly for checking type safety.
Ex:
public class Generic
{
public T Field;
}
Generic g = new Generic();
g.Field = "Some Value";

Example shows a simple example of Generics. The generic class defined has a field of the type T. The type T is initialized to be string.


http://en.csharp-online.net/CSharp_FAQ:_Are_CSharp_constructors_inherited

http://blogs.crsw.com/mark/articles/252.aspx

http://www.devbistro.com/tech-interview-questions/.NET.jsp

http://blogs.crsw.com/mark/articles/254.aspx

http://www.interviewqsn.com/asp_net-2008-features.html

http://msdotnetsupport.blogspot.com/2007/11/22-new-features-of-visual-studio-2008.html



Sudhakar has given:



http://venkataspinterview.blogspot.in/2008/07/aspnet-interview-questions.html

http://www.aspdotnet-suresh.com/











DotNet Framework - Understanding the Application Domains and CLR host

Introduction
Process was the basic unit of execution and isolation for running applications in Traditional Windows application development. The advantage with the model was that each application running was loaded into a separate process that automatically isolated each application from the other. For example, if an error occurred in an application, that would not affect the other applications running on the system. Also, process is defined as a security boundary that prevents applications from talking directly with each other.

This worked fine with the Traditional windows development. Things have changed a bit with the arrival of .NET runtime. The concept is much more enhanced with a new entity called "Application Domain." Application Domains are much like processes. The Application Domain is designed to act like a security boundary and confines errors and faults to a specific domain. Although, it is similar to the process, the Application Domain has some different characteristics.

What are Application Domains?
Let us understand the Application Domains (By differentiating them with a process wherever necessary).

·Application Domain is much lighter than the traditional Windows based processes.

·Application Domains are perfect for application scenarios as they require isolation without the heavy overhead associated with the traditional application process.

·The Application Domain is a virtual process that isolates applications. This guarantees that each application is independent and is not able to directly access resources within another domain.

·Application domain can have a domain level

Application Domains and CLR Hosts – Loading Default Domains
The Common Language Runtime (CLR) is the foundation upon which the Microsoft .NET strategy is built. The CLR provides an execution environment that manages running code and provides services that make software development easier. In order to start running managed code in a process, the CLR must be loaded and initialized. The host is responsible for loading the CLR. Most hosts consist of both unmanaged and managed code.

·The unmanaged code is responsible for loading the CLR into a process and converting the program into managed code.

·The managed portion of the host is responsible for creating and managing the application domains.

There are mainly 2 reasons for hosts to have managed code and unmanaged code. The primary reason is a performance issue. There is a performance associated with calling a managed code from unmanaged code or vice versa. Hence, it is a better to call the unmanaged code and then go ahead with managed code (instead of transitioning from unmanaged host code to managed user code). It is also easy to implement/manage.

These are some of the hosts:

· ASP.NET

· Internet Explorer

· Shell Executables

· SQL Server 2005

Unmanaged Portion of CLR Hosts
Let us discuss more about the unmanaged code portion of the hosts before we go into the managed portion of code. All hosts must start with an unmanaged stub. The .NET Framework provides a set of unmanaged API's the host can use to get the CLR running.

As discussed above, the unmanaged portion of CLR hosts is responsible for loading the CLR into the process. Hosts use the CorBingToRunTimeEx API to load the CLR into the process. The CorBingToRunTimeEx API takes four parameters for loading the CLR. Let us discuss each parameter in detail. The code shown below is the unmanaged API CorBindToRuntimeHost.

Listing 1

HRESULT CorBindToRuntimeHost (
[in] LPCWSTR pwszVersion,
[in] LPCWSTR pwszBuildFlavor,
[in] LPCWSTR pwszHostConfigFile,
[in] VOID* pReserved,
[in] DWORD startupFlags,
[in] REFCLSID rclsid,
[in] REFIID riid,
[out] LPVOID FAR *ppv
);· Version - As shown in Listing 1, the pwszVersion is the parameter that determines which version of Common Language Runtime is to be loaded.

· Server versus workstation - As shown in Listing 1, pwszBuildFlavor specifies whether to load the server or the workstation build of the Common Language Runtime.

· Concurrent GC - StartupFlags specifies a set a predifined flags that control garbage collection.

1. STARTUP_CONCURRENT_GC - Specifies that concurrent garbage collection should be used.

· Loader optimization - Controls whether assemblies are loaded domain-neutrally. A domain neutral assembly is an assembly that can be shared by different application domains.

1. STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN - No assemblies are loaded as domain-neutral. [Except mscorlib] This setting is called single domain because it is commonly used when the host is running only a single application in the process.

2. STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN - All assemblies are loaded as domain-neutral.

3. STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN_HOST All strong-named assemblies are loaded as domain-neutral.

Managed Portion of CLR Hosts
Now, the unmanaged portion of CLR host has loaded the CLR into the process. A default domain is created automatically by the CLR after it is loaded into the process. This default domain will be unloaded only after the process shuts down. This is the reason that most hosts do not run user code in the default domain as it cannot be shut down independently of the process. The ICorRuntimeHost is the interface that exposes some methods for creating application domains and unloading the same. Let us discuss some of the important methods of ICorRuntimeHost in detail. This will help us to understand ICorRunimeHost in a better manner.



Method Name
Description

CreateDomain
Creates an application domain. Gets an interface pointer of type System._AppDomain. Takes a friendly name of the Application domain.

CreateDomainEx
Creates an application domain. This method extends the functionality of the CreateDomain method by allowing the caller to pass the instance of IAppDomainSetup. IAppDomainSetup provides properties that allow the host to configure an AppDomain before calling ICorRuntimeHost::CreateDomainEx to create it. It has properties like ApplicationBase, Application Name, LicenseFile, etc.

Start
Starts the common language runtime.

Stop
Unloads the common language runtime from the current process.

UnloadDomain
Unloads the application domain represented by pAppDomain from the current process. Takes the reference of the application domain as the parameter.

EnumDomains
Returns an enumerator for the domains in the current process.

CurrentDomain
Returns an interface pointer to the AppDomain running on the current thread.

NextDomain
Returns an interface pointer to the next domain in the enumeration. Takes the EnumDomains as the parameter.

GetDefaultDomain
Returns an interface pointer of type _AppDomain, representing the default domain for the current process.


ICLRRunTimeHost is the interface developed for the CLR version 2.0. This interface is the superseded interface of ICorRuntimeHost. This interface has a new method called as SetHostControl. SetHostControl must be called before the common language runtime is initialized, that is, before a call to the Start method. It is always recommended to call SetHostControl immediately after a call to CorBindToRuntimeEx [Unmanaged API].

Creating Application Domains and Executing User code
The host can create application domains to run user code with security, isolation and unloading. It is not a better idea to run user code in the default domain. Let us list down the reasons for the same:

· A default domain cannot be unloaded until the process exists

· Security Isolation

Now that the host has created an application domain, we can execute user code in the domain. All code that is run in the CLR must be part of an assembly. An assembly is the deployment unit for types and resources and is the primary unit of execution in the CLR. The manner in which assemblies are loaded for execution depends largely on the host's specific scenario.

In general, there are two options:

· The first option is to load precompiled assemblies from a disk.

· The second option is to create assemblies on the fly using the API's in the System.Reflection.Emit namespace.

The code shown in Listing 2 is for creating an ApplicationDomain and executing an assembly into it. The code is written in C#. The Assembly that is loaded is an exe file.

Listing 2

ObjAppDomain = AppDomain.CreateDomain("My Application 1");
ObjAppDomain.ExecuteAssembly(@"C:\APPDOMAIN_Test.exe");The code shown below is for unloading the Application domain from the memory.

Listing 3

AppDomain.Unload(ObjAppDomain);
Code Access Security and Application Domains
All the managed code is subject to code access security. It is granted a set of code access permissions that determines what resource types it can access and what types of privileged operations it can perform. The Microsoft .NET Framework security system uses evidence to authenticate code to grant permissions. Evidence is used by the .NET Framework security system to identify assemblies. Code access security policy uses evidence to help grant the right permissions to the right assembly. Evidences can be classified of 2 types. Location related evidences and Author related evidences. The location related evidences can have a URL the assembly is obtained from or a directory the assembly is obtained from.

Code access security policy is configured by administrators and it determines the permissions granted to the assemblies. There are four types of policies identified for code access security.

· Enterprise - Used to apply Enterprise wide policy.

· Machine - Used to apply machine level policy.

· User - Used to apply Per-user policy.

· Application domain-level policy - ASP.NET code access security process is an example of Application domain level policy.

Execution of an Assembly by loading it into Application Domains

An assembly is said to be domain-neutral when its code can be shared by all domains in the process. The runtime host decides whether to load assemblies as domain-neutral when it loads the runtime into a process.

There are three options for loading domain-neutral assemblies:

Load no assemblies as domain-neutral, except Mscorlib, which is always loaded domain-neutral. This setting is called single domain because it is commonly used when the host is running only a single application in the process.

Load all assemblies as domain-neutral. Use this setting when there are multiple application domains in the process, all of which run the same code.

Load strong-named assemblies as domain-neutral. Use this setting when running more than one application in the same process.

In case of loading assemblies as domain-neutral, memory use and performance are at stake. The performance of a domain-neutral assembly is slower if that assembly contains static data or static methods that are accessed frequently. Access to static data or methods is slower because of the need to isolate applications. Each application domain that accesses the assembly must have a separate copy of the static data or method to prevent references to objects in static variables from crossing domain boundaries. As a result, the runtime contains additional logic to direct a caller to the appropriate copy of the static data or method. This extra logic slows down the call.

An assembly is not shared between domains when it is granted a different set of permissions in each domain. This can occur if the runtime host sets an application domain-level security policy. Assemblies should not be loaded as domain-neutral if the set of permissions granted to the assembly is to be different in each domain.

Conclusion
The CLR is the foundation on which the Microsoft .NET has been built. The CLR will be loaded into the memory by the host. A host can be an ISAPI filter, internet explorer or a Database engine. This is based on the type of the application. Hosts call the CorBindToRuntimeEx API to load the CLR into a process. There are four values a host can set when calling CorBindToRuntimeEx. These settings control which CLR gets loaded and how basic functions like garbage collection and class loading will behave in the process. The four settings are: version, server versus workstation, concurrent GC, and loader optimization. This will be he unmanaged portion of the host.

In order to begin running managed code, a host must obtain a pointer to an application domain. In many cases, this is the default domain within the process, but the host can also create additional domains as well. The GetConfiguration method on ICorRuntimeHost provides access to an interface called ICorConfiguration that can be used to configure specific aspects of the CLR that will be loaded into the process, or to register for additional events.


References