Solucionar bloqueo de tablas en SQL SERVER

El sistema ERP de la empresa no podia ingresar a una opcion de la aplicacion. Esta devolvía un error por timeout de SQL.

Se solucionó bajando el proceso que hacia que se bloquee la tabla

Con el siguiente script se visualizó el bloqueo (no aparecia el bloqueo en otros metodos consultados en internet)

SELECT request_session_id sessionid,
 resource_type type,
 resource_database_id dbid,
 OBJECT_NAME(resource_associated_entity_id, resource_database_id) objectname,
 request_mode rmode,
 request_status rstatus
FROM sys.dm_tran_locks
WHERE resource_type IN ('DATABASE', 'OBJECT')

Tambien con esta consulta

EXECUTE sp_lock

Finalmente con el comando kill (ssid) se bajó el proceso conflictivo.

Se revisaron ademas las siguientes opciones

 

http://microsoftsqlsecret.fullblog.com.ar/detectar-bloqueos-sql-server-v2005-y-superiores.html

http://www.eklectopia.com/consultar-tablas-bloqueadas-en-sql-server-el-misterioso-caso-del-select/

http://www.sql-server-performance.com/2007/performance-monitor-general/

http://programacion-x.blogspot.pe/2012/07/como-identificar-bloqueos-en-sql-server.html

Response End en Update Panel

Se tenia un boton que generaba un archivo txt segun items seleccionados en una grilla. La grilla estaba dentro de un update panel.

Para generar el archivo, se generaba en memoria y luego se volcaba a un txt finalizando en response.end()

El response.end(), es incompatible con las llamadas asincronas por lo que el <asp:AsyncPostBackTrigger ControlID=»ImgBtnDescargar» EventName=»Click» /> no funciona.

Para que se realice la accion de generar el archivo se tuvo que cambiar  <asp:PostBackTrigger ControlID=»ImgBtnDescargar» />, sin embargo se generaba y descargaba el archivo pero no se actualizaba la grilla.

 

Al final se ha optado por generar el archivo en una ruta del servidor y redirigir la aplicacion a una nueva pagina que descarga el archivo.

 

private string GenerarArchivo()
{
string NombreArchivo = System.IO.Path.GetRandomFileName();
string NombreGenerado = "CargaSUNAT_" + DateTime.Now.ToString("yyyyMMdd");

System.IO.MemoryStream stream=new System.IO.MemoryStream();
//System.IO.StreamWriter SW = new System.IO.StreamWriter(stream);
System.IO.StreamWriter SW = new System.IO.StreamWriter(Server.MapPath("txtGenerados/" + NombreGenerado + ".txt"));

BLLDocument _BllDocument = new BLLDocument();

foreach (GridViewRow fila in this.gvDocumentosBaja.Rows)
{
DataKey dkey = gvDocumentosBaja.DataKeys[fila.RowIndex];
int IdCorrelativo = int.Parse(dkey[0].ToString());
CheckBox chkSeleccionado = (CheckBox)fila.Cells[0].FindControl("chkselbaja");
if (chkSeleccionado.Checked)
{
BEDocument _documento = _BllDocument.DocumentoTXT(IdCorrelativo);
string [] numeroDoc=_documento.NumberDocument.Split('-');
SW.WriteLine(_documento.ClientRUC + "|" + _documento.DateDocument.ToString("yyyyMMdd") + "|" + _documento.TipoDocumentoDescripcion +
"|" + numeroDoc[0] + "|" + numeroDoc[1] + "|" + _documento.DateDocument.ToString("yyyyMMdd") + "|" + _documento.MensajeBaja);

BEMethExResultInfo resultado = _BllDocument.RegistraTXTGenerado(IdCorrelativo, _SessionVariable.BEUser.Name);

}
}

SW.Close();

return NombreGenerado;
}

 

 protected void ImgBtnDescargar_Click(object sender, ImageClickEventArgs e)
        {
            string NombreGenerado=GenerarArchivo();
            //Response.Redirect("GenerarTXT.aspx");

            if (chkverTodos.Checked)
                CargarGrilla("1");
            else
                CargarGrilla("0");
            
            ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "AbrirDescarga", string.Format("window.open('Descargas.aspx?Fileid={0}');",NombreGenerado), true); 
        }

 

    public partial class Descargas : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                if (Request.QueryString["Fileid"] != null)
                {
                    string nombrearchivo = Request.QueryString["Fileid"].ToString();

                    System.IO.FileStream fs = null;
                    fs = System.IO.File.Open(Server.MapPath("txtGenerados/" + nombrearchivo + ".txt"), System.IO.FileMode.Open);
                    byte[] txtbyte = new byte[fs.Length];
                    fs.Read(txtbyte, 0, Convert.ToInt32(fs.Length));
                    fs.Close();
                    Response.AddHeader("Content-disposition", "attachment; filename=" + nombrearchivo + ".txt");
                    Response.ContentType = "application/octet-stream";
                    Response.BinaryWrite(txtbyte);
                    Response.End();
                }

            }
        }
    }

Autenticacion Windows en ASP NET

The default authentication mechanism built into ASP.NET Web Pages site templates is Forms Authentication via the SimpleMembershipProvider, which is designed to enable authentication of users against a database. This requires the user to know their user name and password, and to enter those whenever they want to log in to access restricted areas within a site. If you are using the ASP.NET Web Pages framework to build an Intranet site that will be hosted within your own corporate network (i.e. client machines and web server are in the same domain), you can use Integrated Windows Authentication instead which simplifies authentication dramatically.

Integrated Windows Authentication is the preferred approach to authentication whenever users are part of the same Windows domain as the server. Users are authenticated against an existing identity store such as Active Directory, and their credentials are not transmistted across the Internet. In addition, users are provided with a seamless experience, as they only need to log in to Windows, and their browser and IIS take care of managing authentication from then on. There are a number of alternatives to Integrated Windows Authentication: Basic, Digest and Client Certificate, but only Integrated Windows Authentication provides strong authentication without the hassle of managing client certificates. It is therefore the recommended option.

Configuring Integrated Windows Authentication is quite straightforward, but there are a number of steps that need to be followed. The first step is to change the web.config file to specify that Windows Authentication is to be used for the site:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add key="EnableSimpleMembership" value="false" />
    </appSettings>

    <system.web>
        <compilation debug="true" targetFramework="4.0" />
        <authentication mode="Windows" />

    </system.web>
</configuration>

There are three items to note: first, an appSettings entry is added to turn off SimpleMembership, which relies on Forms Authentication. Then, within the system.web node, the authentication mode is set to Windows.

The next step is to ensure that your web server is set up to manage Windows Authentication for the site. To do this, you need to explicitly disable anonymous access (which allows anyone to access the site withoiut havng to authenticate) and enable Windows Authentication. WebMatrix doesn’t offer any GUI management tools for IIS Express, so you need to locate the applicationhost.config file (typically located in C:\Users\<your_username>\Documents\IISExpress\config). Having done that, navigate all the way to the bottom where you should find the closing </configuration> tag. Add the following, where «Windows Auth» is the name of your site:

	<location path="Windows Auth">
        <system.webServer>
            <security>
                <authentication>
                    <anonymousAuthentication enabled="false" />
                    <windowsAuthentication enabled="true" />
                </authentication>
            </security>
        </system.webServer>
    </location>
</configuration> <-- left in to help with positioning -->

Visual Studio Express for Web does provide a visual means to manage these settings: you can configure them with two clicks in the site properties:

Windows Authentication

There is an alternative way to disable anonymous access to the site, and that is to add the following to your web.config file within the system.web node:

<authorization>
    <deny users="?"/>
</authorization>

When you deploy the site to the full version of IIS, you can use the standard IIS administrative tools to manage configuration. First, you need to ensure that Windows Authentication is enabled for the web server. You can do this by going to Control Panel » Programs and Features, and then clicking Turn Windows features on or off (left hand side). Locate Internet Information Services and then drill down to Security and ensure that Windows Authentication is checked.

Windows Auth in IIS

Once you have created the site in IIS, go to Feature View and click Authentication:

Windows Authentication in IIS

Make sure that the options are the same as you set in IIS Express: Anonymous Authentication should be disabled, and Windows Authentication enabled.

Windwos Authentication IIS

Working with users and roles

Users are logged in automatically and their identity is stored in the Identity property of the User object. The User object is an instance of the IPrincipal interface. The underlying type is the WindowsPrinciple class. You can get the name of the user from User.Identity.Name. The value returned from this is in the form DomainName\UserName or MachineName\UserName. For example, if I have a Windows login for a domain called CONTOSO01, the value returned by User.Identity.Name might be CONTOSO01\mikebrind.

Some parts of the Intranet might only be accessible to members of certain Windows groups (roles) such as Administrator or Sales. In order to determine whether the current user belongs to a specific group, you use the User.IsInRole method:

@if(User.IsInRole(@"BUILTIN\Administrators") || User.IsInRole(@"DOMAIN\Sales")){
    <div>Is an administrator or sales person</div>
}

You can also use an override of the IsInRole method that takes a WindowsBuiltInRole enumeration, although you have to cast the User object to a WindowsPrincipal to use this option:

@using System.Security.Principal;
@{
    var user = (WindowsPrincipal)User;
    if(user.IsInRole(WindowsBuiltInRole.Administrator)){
        //user is an administrator
    }
}

Note that you also need to add a using directive to reference the System.Security.Principal namespace. Enumerations are good, in that Intellisense offers code completion and compile time checking, but you can’t use this approach to test for membership of custom groups that you have created such as the Sales one illustrated earlier.

You can’t do very much with groups or roles when using Windows Authentication. However, you can activate theWindowsTokenRoleProvider if you do need to make use of its limited features. To do this, add the following to your web.config within the system.web node:

<roleManager enabled="true" defaultProvider="WindowsProvider">
    <providers>
        <clear />
        <add name="WindowsProvider" type="System.Web.Security.WindowsTokenRoleProvider" />
    </providers>
</roleManager>

The first thing to point out is that if you enable this feature, you can no longer use the WindowsBuiltInRole enumeration option with the User.IsInRole method because the underlying type for User has now become a RolePrincipal type, which cannot be converted to WindowsPrincipal. You can continue to use the User.IsInRole method that accepts a string, or you can use the Roles.IsUserInRole(string, string) method, that takes the user name and the role to check against. The only other meaningful method exposed by the WindowsTokenRoleProvider is the GetRolesForUser method which returns an array of roles:

@foreach(var role in Roles.GetRolesForUser()){
    <div>User belongs to @role</div>
}

Unless you actually need to use this method, there seems little point in activating the RoleManager for your intranet site.

Active Directory con C#

Table of Contents

Introduction

When it comes to programmatically accessing Microsoft’s Active Directory a lot of people seem to have quite a difficult time tying all the pieces together to accomplish exactly what they want to. There are so many technologies available for communicating with LDAP that many programmers end up with a mix between COM+ ADSI calls and .NET class calls mixed into their code. ADSI code is so difficult to understand and follow that the creator of that code usually owns it for the entirety of it’s lifecycle since no one else wants to support it.

This article attempts to tie together the most commonly used elements involved in Active Directory Management in the simplest, most clean manner possible. I interact with Active Directory in nearly all of my applications (web & forms) and I have had to solve a lot of integration issues for many customers. When I was starting out with this technology I had a lot of growing pains so this is an attempt to help those programmers who may have a need to interact with the Directory but do not want to have to become experts in the issue. However, certain rudimentary knowledge and concepts are required in order to utilize the code. You must be familiar with such terms as: distinguishedName, ldap paths, fully qualified domain names, object attributes (single string & multi-string), and general knowledge of ldap schemas.

Background

There is a great collection of sample code available on MSDN’s website for the v1.1System.DirectoryServices assembly but there seems to be a void when it comes to the new functionality available in the v2.0 System.DirectoryServices.ActiveDirectory assembly. Since this article’s original publishing, Generics have gained widespread acceptance and I encourage anyone borrowing from this resource to replace the archaic ArrayList collections with List<T> or appropriate generic collections.

Points of Concern

In order to communicate with Active Directory one must take into account network security, business rules, and technological constraints. If you’re using Active Directory code from an ASP.NET page you must ensure that the code has the appropriate level of permission to access and interact with the directory. For development purposes or proof of concept you can enable impersonation at the ASP.NET level (in web.config) and the IIS level and if the IIS server and the directory domain controller reside on the same machine this will work. However, if these entities are not co-located on the same server (as they never are in production) you can wrap the code around an impersonation class (such as the Zeta Impersonator which will execute the Directory calls under the token of the impersonated user. It’s strongly recommended that you do not do this for security reasons unless absolutely necessary.. The authorized method for granting the ASP.NET application permission to the directory is by way of either a privileged IIS Application Pool running under the identity of a service account or by way of a COM+ entity running under the identity of a service account.

If you plan on running this code from a desktop assembly then you’re going to want to ensure that your machine is attached to a domain and can communicate with that domain. The impersonation is not necessary if the user running the code has sufficient privileges on the domain.

Running Code in Batch Processes

It is also important to note that if you plan on running this code from an ASP.NET page in batch, ASP.NET will time out on you if you try to run batch processes from it’s primary thread. There are several things to consider in this scenario but be aware that for example, if you’re creating x number of accounts through an ASP.NET application (or performing any batch operation in general) that you must plan to use queues, a back-end scheduler, or some other mechanism outside the scope of the page itself to prevent timing out during your processes. As with any ASPNET design, it’s never a good idea to use ASPNET itself for anything but the «View» part of the solution. The best architecture would queue tasks into a SQL database or something to that effect and then a back-end windows service or similar application would pick up the tasking and perform the actual Directory operations.

This is typically how I engineer Active Directory management solutions for customers.

A Note on Method Parameters

You will notice that most of the methods require the same parameters. Rather than identify each time I will outline them now:

  • friendlyDomainName: the non qualified domain name (contoso – NOT contoso.com)
  • ldapDomain: the fully qualified domain such as contoso.com or dc=contoso,dc=com
  • objectPath: the fully qualified path to the object: CN=user, OU=USERS, DC=contoso, DC=com (same asobjectDn)
  • objectDn: the distinguishedName of the object: CN=group, OU=GROUPS, DC=contoso, DC=com
  • userDn: the distinguishedName of the user: CN=user, OU=USERS, DC=contoso, DC=com
  • groupDn: the distinguishedName of the group: CN=group,OU=GROUPS,DC=contoso,DC=com

A Note on System.DirectoryServices.DirectoryEntry

You’ll notice in all the samples that we’re binding directly to the directoryEntry and not specifying a server or credentials. If you do not want to use an impersonation class you can send credentials directly into theDirectoryEntry constructor. The impersonation class is helpful for those times when you want to use astatic method and don’t want to go through the trouble of creating a DirectoryContext object to hold these details. Likewise you may want to target a specific domain controller.

Target Specific Domain Controllers or Credentials

Everywhere in the code that you see: LDAP:// you can replace withLDAP://MyDomainControllerNameOrIpAddress as well as everywhere you see a DirectoryEntry class being constructed you can send in specific credentials as well. This is especially helpful if you need to work on an Active Directory for which your machine is not a member of it’s forest or domain or you want to target a DC to make the changes to.

//Rename an object and specify the domain controller and credentials directly


public static void Rename(string server,
    string userName, string password, string objectDn, string newName)
{
    DirectoryEntry child = new DirectoryEntry("LDAP://" + server + "/" + 
        objectDn, userName, password);
    child.Rename("CN=" + newName);
}

Managing local accounts with DirectoryEntry

It is important to note that you can execute some of these methods against a local machine as opposed to an Active Directory if needed by simply replacing the LDAP:// string with WinNT:// as demonstrated below

//create new local account

DirectoryEntry localMachine = new DirectoryEntry("WinNT://" + 
    Environment.MachineName);
DirectoryEntry newUser = localMachine.Children.Add("localuser", "user");
newUser.Invoke("SetPassword", new object[] { "3l!teP@$$w0RDz" });
newUser.CommitChanges();
Console.WriteLine(newUser.Guid.ToString());
localMachine.Close();
newUser.Close();

Managing local groups with DirectoryEntry

A few configuration changes need to be made to the code but it’s pretty straightforward. Below you can see an example of using DirectoryEntry to enumerate the members of the local «administrator» group.

DirectoryEntry localMachine = new DirectoryEntry
    ("WinNT://" + Environment.MachineName + ",Computer");
DirectoryEntry admGroup = localMachine.Children.Find
    ("administrators", "group");
object members = admGroup.Invoke("members", null);

foreach (object groupMember in (IEnumerable)members)
{
    DirectoryEntry member = new DirectoryEntry(groupMember);
    Console.WriteLine(member.Name);
}

Managing IIS with DirectoryEntry

In addition to managing local & directory services accounts, the versatile DirectoryEntry object can manage other network providers as well, such as IIS. Below is an example of how you can use DirectoryEntry to provision a new virtual directory in IIS.

//Create New Virtual Directory in IIS with DirectoryEntry()


string wwwroot = "c:\\Inetpub\\wwwroot";
string virtualDirectoryName = "myNewApp";
string sitepath = "IIS://localhost/W3SVC/1/ROOT";

DirectoryEntry vRoot = new DirectoryEntry(sitepath);
DirectoryWntry vDir = vRoot.Children.Add(virtualDirectoryName, 
                            "IIsWebVirtualDir");
vDir.CommitChanges();

vDir.Properties["Path"].Value = wwwroot + "\\" + virtualDirectoryName;
vDir.Properties["DefaultDoc"].Value = "Default.aspx";
vDir.Properties["DirBrowseFlags"].Value = 2147483648;
vDir.Commitchanges();
vRoot.CommitChanges();

Active Directory Code

The code below is broken apart logically into usage categories. Again, this is not intended to be a complete library, just the code that I use on a daily basis.

Active Directory Management

//These methods require these imports

//You must add a references in your project as well

using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;

Translate the Friendly Domain Name to Fully Qualified Domain

public static string FriendlyDomainToLdapDomain(string friendlyDomainName)
{
    string ldapPath = null;
    try
    {
        DirectoryContext objContext = new DirectoryContext(
            DirectoryContextType.Domain, friendlyDomainName);
        Domain objDomain = Domain.GetDomain(objContext);
        ldapPath = objDomain.Name;
    }
    catch (DirectoryServicesCOMException e)
    {
        ldapPath = e.Message.ToString();
    }
    return ldapPath;
}

Enumerate Domains in the Current Forest

public static ArrayList EnumerateDomains()
{
    ArrayList alDomains = new ArrayList();
    Forest currentForest = Forest.GetCurrentForest();
    DomainCollection myDomains = currentForest.Domains;

    foreach (Domain objDomain in myDomains)
    {
        alDomains.Add(objDomain.Name);
    }
    return alDomains;
}

Enumerate Global Catalogs in the Current Forest

public static ArrayList EnumerateDomains()
{
    ArrayList alGCs = new ArrayList();
    Forest currentForest = Forest.GetCurrentForest();
    foreach (GlobalCatalog gc in currentForest.GlobalCatalogs)
    {
        alGCs.Add(gc.Name);
    }
    return alGCs;
}

Enumerate Domain Controllers in a Domain

public static ArrayList EnumerateDomainControllers()
{
    ArrayList alDcs = new ArrayList();
    Domain domain = Domain.GetCurrentDomain();
    foreach (DomainController dc in domain.DomainControllers)
    {
        alDcs.Add(dc.Name);
    }
    return alDcs;
}

Create a Trust Relationship

public void CreateTrust(string sourceForestName, string targetForestName)
{
    Forest sourceForest = Forest.GetForest(new DirectoryContext(
        DirectoryContextType.Forest, sourceForestName));

    Forest targetForest = Forest.GetForest(new DirectoryContext(
        DirectoryContextType.Forest, targetForestName));

    // create an inbound forest trust

    sourceForest.CreateTrustRelationship(targetForest,
        TrustDirection.Outbound);
}

Delete a Trust Relationship

public void DeleteTrust(string sourceForestName, string targetForestName)
{
    Forest sourceForest = Forest.GetForest(new DirectoryContext(
        DirectoryContextType.Forest, sourceForestName));

    Forest targetForest = Forest.GetForest(new DirectoryContext(
        DirectoryContextType.Forest, targetForestName));

    // delete forest trust

    sourceForest.DeleteTrustRelationship(targetForest);
}

Enumerate Objects in an OU

The parameter OuDn is the Organizational Unit distinguishedName such asOU=Users,dc=myDomain,dc=com

public ArrayList EnumerateOU(string OuDn)
{
    ArrayList alObjects = new ArrayList();
    try
    {
        DirectoryEntry directoryObject = new DirectoryEntry("LDAP://" + OuDn);
        foreach (DirectoryEntry child in directoryObject.Children)
        {
            string childPath = child.Path.ToString();
            alObjects.Add(childPath.Remove(0,7)); 
                //remove the LDAP prefix from the path

            child.Close();
            child.Dispose();
        }
        directoryObject.Close();
        directoryObject.Dispose();
    }
    catch (DirectoryServicesCOMException e)
    {
        Console.WriteLine("An Error Occurred: " + e.Message.ToString());
    }
    return alObjects;
}

Enumerate Directory Entry Settings

One of the nice things about the 2.0 classes is the ability to get and set a configuration object for yourdirectoryEntry objects.

static void DirectoryEntryConfigurationSettings(string domainADsPath)
{
    // Bind to current domain

    DirectoryEntry entry = new DirectoryEntry(domainADsPath);
    DirectoryEntryConfiguration entryConfiguration = entry.Options;

    Console.WriteLine("Server: " + entryConfiguration.GetCurrentServerName());
    Console.WriteLine("Page Size: " + entryConfiguration.PageSize.ToString());
    Console.WriteLine("Password Encoding: " + 
        entryConfiguration.PasswordEncoding.ToString());
    Console.WriteLine("Password Port: " + 
        entryConfiguration.PasswordPort.ToString());
    Console.WriteLine("Referral: " + entryConfiguration.Referral.ToString());
    Console.WriteLine("Security Masks: " + 
        entryConfiguration.SecurityMasks.ToString());
    Console.WriteLine("Is Mutually Authenticated: " + 
        entryConfiguration.IsMutuallyAuthenticated().ToString());
    Console.WriteLine();
    Console.ReadLine();
}

Active Directory Objects

//These methods require these imports

//You must add a references in your project as well

using System.DirectoryServices;

Check for the Existence of an Object

This method does not need you to know the distinguishedName, you can concat strings or even guess a location and it will still run (and return false if not found).

public static bool Exists(string objectPath)
{
    bool found = false;
    if (DirectoryEntry.Exists("LDAP://" + objectPath))
    {
        found = true;
    }
    return found;
}

Move an Object from one Location to Another

It should be noted that the string newLocation should NOT include the CN= value of the object. The method will pull that from the objectLocation string for you. So object CN=group,OU=GROUPS,DC=contoso,DC=comis sent in as the objectLocation but the newLocation is something like:OU=NewOUParent,DC=contoso,DC=com. The method will take care of the CN=group.

public void Move(string objectLocation, string newLocation)
{
    //For brevity, removed existence checks

    DirectoryEntry eLocation = new DirectoryEntry("LDAP://" + objectLocation);
    DirectoryEntry nLocation = new DirectoryEntry("LDAP://" + newLocation);
    string newName = eLocation.Name;
    eLocation.MoveTo(nLocation, newName);
    nLocation.Close();
    eLocation.Close();
}

Enumerate Multi-String Attribute Values of an Object

This method includes a recursive flag in case you want to recursively dig up properties of properties such as enumerating all the member values of a group and then getting each member group’s groups all the way up the tree.

public ArrayList AttributeValuesMultiString(string attributeName,
     string objectDn, ArrayList valuesCollection, bool recursive)
{
    DirectoryEntry ent = new DirectoryEntry(objectDn);
    PropertyValueCollection ValueCollection = ent.Properties[attributeName];
    IEnumerator en = ValueCollection.GetEnumerator();

    while (en.MoveNext())
    {
        if (en.Current != null)
        {
            if (!valuesCollection.Contains(en.Current.ToString()))
            {
                valuesCollection.Add(en.Current.ToString());
                if (recursive)
                {
                    AttributeValuesMultiString(attributeName, "LDAP://" +
                    en.Current.ToString(), valuesCollection, true);
                }
            }
        }
    }
    ent.Close();
    ent.Dispose();
    return valuesCollection;
}

Enumerate Single String Attribute Values of an Object

public string AttributeValuesSingleString
    (string attributeName, string objectDn)
{
    string strValue;
    DirectoryEntry ent = new DirectoryEntry(objectDn);
    strValue = ent.Properties[attributeName].Value.ToString();
    ent.Close();
    ent.Dispose();
    return strValue;
}

Enumerate an Object’s Properties: The Ones with Values

public static ArrayList GetUsedAttributes(string objectDn)
{
    DirectoryEntry objRootDSE = new DirectoryEntry("LDAP://" + objectDn);
    ArrayList props = new ArrayList();

    foreach (string strAttrName in objRootDSE.Properties.PropertyNames)
    {
        props.Add(strAttrName);
    }
    return props;
}

Get an Object DistinguishedName: ADO.NET search (ADVANCED)

This method is the glue that ties all the methods together since most all the methods require the consumer to provide a distinguishedName. Wherever you put this code, you must ensure that you add these enumerations as well. This allows the consumers to specify the type of object to search for and whether they want thedistinguishedName returned or the objectGUID.

public enum objectClass
{
    user, group, computer
}
public enum returnType
{
 distinguishedName, ObjectGUID
}

A call to this class might look like:

myObjectReference.GetObjectDistinguishedName(objectClass.user, returnType.ObjectGUID,"john.q.public", "contoso.com")

public string GetObjectDistinguishedName(objectClass objectCls,
    returnType returnValue, string objectName, string LdapDomain)
{
    string distinguishedName = string.Empty;
    string connectionPrefix = "LDAP://" + LdapDomain;
    DirectoryEntry entry = new DirectoryEntry(connectionPrefix);
    DirectorySearcher mySearcher = new DirectorySearcher(entry);

    switch (objectCls)
    {
        case objectClass.user:
            mySearcher.Filter = "(&(objectClass=user)
        (|(cn=" + objectName + ")(sAMAccountName=" + objectName + ")))";
            break;
        case objectClass.group:
            mySearcher.Filter = "(&(objectClass=group)
        (|(cn=" + objectName + ")(dn=" + objectName + ")))";
            break;
        case objectClass.computer:
            mySearcher.Filter = "(&(objectClass=computer)
            (|(cn=" + objectName + ")(dn=" + objectName + ")))";
            break;
    }
    SearchResult result = mySearcher.FindOne();

    if (result == null)
    {
        throw new NullReferenceException
        ("unable to locate the distinguishedName for the object " +
        objectName + " in the " + LdapDomain + " domain");
    }
    DirectoryEntry directoryObject = result.GetDirectoryEntry();
    if (returnValue.Equals(returnType.distinguishedName))
    {
        distinguishedName = "LDAP://" + directoryObject.Properties
            ["distinguishedName"].Value;
    }
    if (returnValue.Equals(returnType.ObjectGUID))
    {
        distinguishedName = directoryObject.Guid.ToString();
    }
    entry.Close();
    entry.Dispose();
    mySearcher.Dispose();
    return distinguishedName;
}

Convert distinguishedName to ObjectGUID

public string ConvertDNtoGUID(string objectDN)
{
    //Removed logic to check existence first

    DirectoryEntry directoryObject = new DirectoryEntry(objectDN);
    return directoryObject.Guid.ToString();
}

Convert an ObjectGUID to OctectString: The Native ObjectGUID

public static string ConvertGuidToOctectString(string objectGuid)
{
    System.Guid guid = new Guid(objectGuid);
    byte[] byteGuid = guid.ToByteArray();
    string queryGuid = "";
    foreach (byte b in byteGuid)
    {
        queryGuid += @"\" + b.ToString("x2");
    }
    return queryGuid;
}

Search by ObjectGUID or convert ObjectGUID to distinguishedName

public static string ConvertGuidToDn(string GUID)
{
      DirectoryEntry ent = new DirectoryEntry();
      String ADGuid = ent.NativeGuid;
      DirectoryEntry x = new DirectoryEntry("LDAP://{GUID=" + ADGuid + ">"); 
          //change the { to <>

      return x.Path.Remove(0,7); //remove the LDAP prefix from the path

}

Publish Network Shares in Active Directory

 //Example

 private void init()
{
    CreateShareEntry("OU=HOME,dc=baileysoft,dc=com",
        "Music", @"\\192.168.2.1\Music", "mp3 Server Share");
    Console.ReadLine();
}

//Actual Method

public void CreateShareEntry(string ldapPath,
    string shareName, string shareUncPath, string shareDescription)
{
    string oGUID = string.Empty;
    string connectionPrefix = "LDAP://" + ldapPath;
    DirectoryEntry directoryObject = new DirectoryEntry(connectionPrefix);
    DirectoryEntry networkShare = directoryObject.Children.Add("CN=" + 
        shareName, "volume");
    networkShare.Properties["uNCName"].Value = shareUncPath;
    networkShare.Properties["Description"].Value = shareDescription;
    networkShare.CommitChanges();

    directoryObject.Close();
    networkShare.Close();
}

Create a New Security Group

Note: by default if no GroupType property is set, the group is created as a domain security group.

public void Create(string ouPath, string name)
{
    if (!DirectoryEntry.Exists("LDAP://CN=" + name + "," + ouPath))
    {
        try
        {
            DirectoryEntry entry = new DirectoryEntry("LDAP://" + ouPath);
            DirectoryEntry group = entry.Children.Add("CN=" + name, "group");
            group.Properties["sAmAccountName"].Value = name;
            group.CommitChanges();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message.ToString());
        }
    }
    else { Console.WriteLine(path + " already exists"); }
}

Delete a group

public void Delete(string ouPath, string groupPath)
{
    if (DirectoryEntry.Exists("LDAP://" + groupPath))
    {
        try
        {
            DirectoryEntry entry = new DirectoryEntry("LDAP://" + ouPath);
            DirectoryEntry group = new DirectoryEntry("LDAP://" + groupPath);
            entry.Children.Remove(group);
            group.CommitChanges();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message.ToString());
        }
    }
    else
    { 
        Console.WriteLine(path + " doesn't exist"); 
    }
}

Active Directory Users Tasks

//These methods require these imports

//You must add a references in your project as well

using System.DirectoryServices;

Authenticate a User Against the Directory

Per John Storer, thanks for sharing.

private bool Authenticate(string userName,
    string password, string domain)
{
    bool authentic = false;
    try
    {
        DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain,
            userName, password);
        object nativeObject = entry.NativeObject;
        authentic = true;
    }
    catch (DirectoryServicesCOMException) { }
    return authentic;
}

Add User to Group

public void AddToGroup(string userDn, string groupDn)
{
    try
    {
        DirectoryEntry dirEntry = new DirectoryEntry("LDAP://" + groupDn);
        dirEntry.Properties["member"].Add(userDn);
        dirEntry.CommitChanges();
        dirEntry.Close();
    }
    catch (System.DirectoryServices.DirectoryServicesCOMException E)
    {
        //doSomething with E.Message.ToString();

    }
}

Remove User from Group

public void RemoveUserFromGroup(string userDn, string groupDn)
{
    try
    {
        DirectoryEntry dirEntry = new DirectoryEntry("LDAP://" + groupDn);
        dirEntry.Properties["member"].Remove(userDn);
        dirEntry.CommitChanges();
        dirEntry.Close();
    }
    catch (System.DirectoryServices.DirectoryServicesCOMException E)
    {
        //doSomething with E.Message.ToString();

    }
}

Get User Group Memberships of the Logged in User from ASP.NET

public ArrayList Groups()
{
    ArrayList groups = new ArrayList();
    foreach (System.Security.Principal.IdentityReference group in
        System.Web.HttpContext.Current.Request.LogonUserIdentity.Groups)
    {
        groups.Add(group.Translate(typeof
            (System.Security.Principal.NTAccount)).ToString());
    }
    return groups;
}

Get User Group Memberships

This method requires that you have the AttributeValuesMultiString method earlier in the article included in your class.

public ArrayList Groups(string userDn, bool recursive)
{
    ArrayList groupMemberships = new ArrayList();
    return AttributeValuesMultiString("memberOf", userDn,
        groupMemberships, recursive);
}

Create User Account

public string CreateUserAccount(string ldapPath, string userName, 
    string userPassword)
{
    try
    {
        string oGUID = string.Empty;
        string connectionPrefix = "LDAP://" + ldapPath;
        DirectoryEntry dirEntry = new DirectoryEntry(connectionPrefix);
        DirectoryEntry newUser = dirEntry.Children.Add
            ("CN=" + userName, "user");
        newUser.Properties["samAccountName"].Value = userName;
        newUser.CommitChanges();
        oGUID = newUser.Guid.ToString();

        newUser.Invoke("SetPassword", new object[] { userPassword });
        newUser.CommitChanges();
        dirEntry.Close();
        newUser.Close();
    }
    catch (System.DirectoryServices.DirectoryServicesCOMException E)
    {
        //DoSomethingwith --> E.Message.ToString();

    }
    return oGUID;
}

Dealing with User Passwords

There are some specifics to understand when dealing with user passwords and boundaries around passwords such as forcing a user to change their password on the next logon, denying the user the right to change their own passwords, setting passwords to never expire, to when to expire, and these tasks can be accomplished usingUserAccountControl flags that are demonstrated in the proceeding sections. Please refer to this great MSDN article: Managing User Passwords for examples and documentation regarding these features. (thanks to Daniel Ocean for identifying this resource)

//Add this to the create account method

int val = (int)newUser.Properties["userAccountControl"].Value; 
     //newUser is DirectoryEntry object

newUser.Properties["userAccountControl"].Value = val | 0x80000; 
    //ADS_UF_TRUSTED_FOR_DELEGATION

All UserAccountControl flags

CONST   HEX
-------------------------------
        SCRIPT 0x0001
        ACCOUNTDISABLE 0x0002
        HOMEDIR_REQUIRED 0x0008
        LOCKOUT 0x0010
        PASSWD_NOTREQD 0x0020
        PASSWD_CANT_CHANGE 0x0040
        ENCRYPTED_TEXT_PWD_ALLOWED 0x0080
        TEMP_DUPLICATE_ACCOUNT 0x0100
        NORMAL_ACCOUNT 0x0200
        INTERDOMAIN_TRUST_ACCOUNT 0x0800
        WORKSTATION_TRUST_ACCOUNT 0x1000
        SERVER_TRUST_ACCOUNT 0x2000
        DONT_EXPIRE_PASSWORD 0x10000
        MNS_LOGON_ACCOUNT 0x20000
        SMARTCARD_REQUIRED 0x40000
        TRUSTED_FOR_DELEGATION 0x80000
        NOT_DELEGATED 0x100000
        USE_DES_KEY_ONLY 0x200000
        DONT_REQ_PREAUTH 0x400000
        PASSWORD_EXPIRED 0x800000
        TRUSTED_TO_AUTH_FOR_DELEGATION 0x1000000

Enable a User Account

public void Enable(string userDn)
{
    try
    {
        DirectoryEntry user = new DirectoryEntry(userDn);
        int val = (int)user.Properties["userAccountControl"].Value;
        user.Properties["userAccountControl"].Value = val & ~0x2; 
            //ADS_UF_NORMAL_ACCOUNT;

        user.CommitChanges();
        user.Close();
    }
    catch (System.DirectoryServices.DirectoryServicesCOMException E)
    {
        //DoSomethingWith --> E.Message.ToString();

    }
}

Disable a User Account

public void Disable(string userDn)
{
    try
    {
        DirectoryEntry user = new DirectoryEntry(userDn);
        int val = (int)user.Properties["userAccountControl"].Value;
        user.Properties["userAccountControl"].Value = val | 0x2; 
             //ADS_UF_ACCOUNTDISABLE;

        user.CommitChanges();
        user.Close();
    }
    catch (System.DirectoryServices.DirectoryServicesCOMException E)
    {
        //DoSomethingWith --> E.Message.ToString();

    }
}

Unlock a User Account

public void Unlock(string userDn)
{
    try
    {
        DirectoryEntry uEntry = new DirectoryEntry(userDn);
        uEntry.Properties["LockOutTime"].Value = 0; //unlock account

        uEntry.CommitChanges(); //may not be needed but adding it anyways

        uEntry.Close();
    }
    catch (System.DirectoryServices.DirectoryServicesCOMException E)
    {
        //DoSomethingWith --> E.Message.ToString();

    }
}

Alternate Lock/Unlock Account

It’s hard to find code to lock an account. Here is my code to lock or unlock an account. dEntry is class variable already set to a user account. Shared by dextrous1.

/// <span class="code-SummaryComment"><summary></span>
/// Gets or sets a value indicating if the user account is locked out
/// <span class="code-SummaryComment"></summary></span>
public bool IsLocked
{
    get { return Convert.ToBoolean(dEntry.InvokeGet("IsAccountLocked")); }
    set { dEntry.InvokeSet("IsAccountLocked", value); }
}

Reset a User Password

public void ResetPassword(string userDn, string password)
{
    DirectoryEntry uEntry = new DirectoryEntry(userDn);
    uEntry.Invoke("SetPassword", new object[] { password });
    uEntry.Properties["LockOutTime"].Value = 0; //unlock account

    uEntry.Close();
}

Rename an Object

public static void Rename(string objectDn, string newName)
{
    DirectoryEntry child = new DirectoryEntry("LDAP://" + objectDn);
   child.Rename("CN=" + newName);
}

Conclusion

I would have liked to include a sample project but my professional code is so tightly integrated with customer proprietary code that it was not feasible at this time.

UPDATE

If you would like to see an extremely simple implementation of some of this code check out theDirectoryServicesBrowserDialog I posted some time ago. This should demonstrate to those of you who are having trouble adding the proper references or having other difficulties.

I hope this helps out all those programmers that were like me and had to get up to speed really quickly and lost countless hours studying the System.DirectoryServices assembly trying to dig up answers on how to do AD tasks.

If you have some additional segments of code that are small but efficient that you’d like to include send them to me and I’ll add them to this document.

History

  • Originally submitted – 22 March 2007
  • Added GetUsedAttributes() method – 24 March 2007
  • Added EnumerateOU() method – 25 March 2007
  • Added CreateShareEntry() – 27 March 2007
  • Added CommitChanged() call in UnlockUserAccount()
  • Cleaned up article, added a few new methods – 03 Apr 2007
  • Added note on DirectoryEntry – 04 Apr 2007
  • Added note on working with local accounts – 12 Apr 2007
  • Added code for creating/deleting groups – 20 Apr 2007
  • Added John Storer’s code for authenticating users against the directory
  • Added UserAccountControl flags section – 06 Jun 2007
  • Added Managing IIS with DirectoryEntry() section – 12 Jun 2007
  • Created table of contents – 09 Jul 2007
  • Added Dealing with User Passwords Section – 21 May 2008
  • Added Alternate Lock/Unlock Account by dextrous1 – 21 May 2008

Usar autenticacion windows en aplicaciones .NET II

Windows Authentication With ASP.NET Web Pages

4.88 (26 votes)

The default authentication mechanism built into ASP.NET Web Pages site templates is Forms Authentication via the SimpleMembershipProvider, which is designed to enable authentication of users against a database. This requires the user to know their user name and password, and to enter those whenever they want to log in to access restricted areas within a site. If you are using the ASP.NET Web Pages framework to build an Intranet site that will be hosted within your own corporate network (i.e. client machines and web server are in the same domain), you can use Integrated Windows Authentication instead which simplifies authentication dramatically.

Integrated Windows Authentication is the preferred approach to authentication whenever users are part of the same Windows domain as the server. Users are authenticated against an existing identity store such as Active Directory, and their credentials are not transmistted across the Internet. In addition, users are provided with a seamless experience, as they only need to log in to Windows, and their browser and IIS take care of managing authentication from then on. There are a number of alternatives to Integrated Windows Authentication: Basic, Digest and Client Certificate, but only Integrated Windows Authentication provides strong authentication without the hassle of managing client certificates. It is therefore the recommended option.

Configuring Integrated Windows Authentication is quite straightforward, but there are a number of steps that need to be followed. The first step is to change the web.config file to specify that Windows Authentication is to be used for the site:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add key="EnableSimpleMembership" value="false" />
    </appSettings>

    <system.web>
        <compilation debug="true" targetFramework="4.0" />
        <authentication mode="Windows" />

    </system.web>
</configuration>

There are three items to note: first, an appSettings entry is added to turn off SimpleMembership, which relies on Forms Authentication. Then, within the system.web node, the authentication mode is set to Windows.

The next step is to ensure that your web server is set up to manage Windows Authentication for the site. To do this, you need to explicitly disable anonymous access (which allows anyone to access the site withoiut havng to authenticate) and enable Windows Authentication. WebMatrix doesn’t offer any GUI management tools for IIS Express, so you need to locate the applicationhost.config file (typically located in C:\Users\<your_username>\Documents\IISExpress\config). Having done that, navigate all the way to the bottom where you should find the closing </configuration> tag. Add the following, where «Windows Auth» is the name of your site:

	<location path="Windows Auth">
        <system.webServer>
            <security>
                <authentication>
                    <anonymousAuthentication enabled="false" />
                    <windowsAuthentication enabled="true" />
                </authentication>
            </security>
        </system.webServer>
    </location>
</configuration> <-- left in to help with positioning -->

Visual Studio Express for Web does provide a visual means to manage these settings: you can configure them with two clicks in the site properties:

Windows Authentication

There is an alternative way to disable anonymous access to the site, and that is to add the following to your web.config file within the system.web node:

<authorization>
    <deny users="?"/>
</authorization>

When you deploy the site to the full version of IIS, you can use the standard IIS administrative tools to manage configuration. First, you need to ensure that Windows Authentication is enabled for the web server. You can do this by going to Control Panel » Programs and Features, and then clicking Turn Windows features on or off (left hand side). Locate Internet Information Services and then drill down to Security and ensure that Windows Authentication is checked.

Windows Auth in IIS

Once you have created the site in IIS, go to Feature View and click Authentication:

Windows Authentication in IIS

Make sure that the options are the same as you set in IIS Express: Anonymous Authentication should be disabled, and Windows Authentication enabled.

Windwos Authentication IIS

Working with users and roles

Users are logged in automatically and their identity is stored in the Identity property of the User object. The User object is an instance of the IPrincipal interface. The underlying type is the WindowsPrinciple class. You can get the name of the user from User.Identity.Name. The value returned from this is in the form DomainName\UserName or MachineName\UserName. For example, if I have a Windows login for a domain called CONTOSO01, the value returned by User.Identity.Name might be CONTOSO01\mikebrind.

Some parts of the Intranet might only be accessible to members of certain Windows groups (roles) such as Administrator or Sales. In order to determine whether the current user belongs to a specific group, you use the User.IsInRole method:

@if(User.IsInRole(@"BUILTIN\Administrators") || User.IsInRole(@"DOMAIN\Sales")){
    <div>Is an administrator or sales person</div>
}

You can also use an override of the IsInRole method that takes a WindowsBuiltInRole enumeration, although you have to cast the User object to a WindowsPrincipal to use this option:

@using System.Security.Principal;
@{
    var user = (WindowsPrincipal)User;
    if(user.IsInRole(WindowsBuiltInRole.Administrator)){
        //user is an administrator
    }
}

Note that you also need to add a using directive to reference the System.Security.Principal namespace. Enumerations are good, in that Intellisense offers code completion and compile time checking, but you can’t use this approach to test for membership of custom groups that you have created such as the Sales one illustrated earlier.

You can’t do very much with groups or roles when using Windows Authentication. However, you can activate theWindowsTokenRoleProvider if you do need to make use of its limited features. To do this, add the following to your web.config within the system.web node:

<roleManager enabled="true" defaultProvider="WindowsProvider">
    <providers>
        <clear />
        <add name="WindowsProvider" type="System.Web.Security.WindowsTokenRoleProvider" />
    </providers>
</roleManager>

The first thing to point out is that if you enable this feature, you can no longer use the WindowsBuiltInRole enumeration option with the User.IsInRole method because the underlying type for User has now become a RolePrincipal type, which cannot be converted to WindowsPrincipal. You can continue to use the User.IsInRole method that accepts a string, or you can use the Roles.IsUserInRole(string, string) method, that takes the user name and the role to check against. The only other meaningful method exposed by the WindowsTokenRoleProvider is the GetRolesForUser method which returns an array of roles:

@foreach(var role in Roles.GetRolesForUser()){
    <div>User belongs to @role</div>
}

Unless you actually need to use this method, there seems little point in activating the RoleManager for your intranet site.

Usar autenticacion windows en aplicaciones .NET

Para usar autenticacion Windows se deben de realizar minimo dos pasos

1.- Configurar el modo de la aplicacion web como windows

<system.web>
<compilation debug="true" targetFramework="4.0" />
<authentication mode="Windows"></authentication>
<authorization>
<allow users="megarep\vorellana"/>
<deny users="*"/>
</authorization>
</system.web>

2.- Configurar servidor IIS

Windows Auth in IIS

Windows Authentication in IIS

Windwos Authentication IIS

Resolver conflictos entre jquery y ASP NET (Update Panels)

Conflicts between ASP.NET AJAX UpdatePanels & jQuery functions

In one of my previous posts dealing with the jQuery DatePicker , a user commented reporting an issue where he uses the jQuery DatePicker and ASP.NET AJAX UpdatePanels.

He says: On the same control that I have the date picker, I also have an ajax update panel, with sync as well as asych triggers. The date pick works before I trigger any ajax, and doesn’t work after. Any clue of a workaround here?

Only two hours after his comment, I’ve replied with solution that I’ve used previously in one of my testing projects since I already experienced the same issue with some JavaScript functions previously.

So, once you see the issue, you will think that ASP.NET AJAX UpdatePanels does not like the other jQuery functions within the page. Hmm… it seems true, because after partial post-back has been made by the ASP.NET AJAX UpdatePanel, the JavaScript event handlers are lost.

First of all, we should avoid mixing different JavaScript libraries or frameworks because we may always have some issues when they override some of the default functions they use or some other conflicts that even we cannot think of. Also, both jQuery and ASP.NET Ajax use the dollar ($) sign in different context, which might be an issue when mixing both of the technologies on a single page.

Well, in order to reproduce the problem, lets pass trough the following steps:

1. Add reference to the jQuery library. If you don’t have the library on your local machine, you can reference it from the Microsoft Content Delivery Network (CDN)

<script src=»http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.min.js» type=»text/javascript»></script>
2. The ASPX code – ScriptManager, UpdatePanel, Label and Button

<div>
<asp:ScriptManager ID=»ScriptManager1″ runat=»server»>
</asp:ScriptManager>
<asp:UpdatePanel ID=»UpdatePanel1″ runat=»server»>
<ContentTemplate>
<asp:Label runat=»server» ID=»lblText» />
<br />
<asp:Button ID=»btnClick» runat=»server» Text=»Click Me» OnClick=»btnClick_Click» />
</ContentTemplate>
</asp:UpdatePanel>
<br /><br />
<%= DateTime.Now %>
<!– the Date time won’t change on button click since its outside of the update panel –>
</div>

3. The jQuery function that will show an Alert when clicking on the Button

<script language=»javascript» type=»text/javascript»>
$(function () {
$(«#btnClick»).click(function () {
//will run on btnClick, which is inside the UpdatePanel
alert(«Alert: Hello from jQuery!»);
});
});
</script>

4. The server-side C# code that will run when the partial post back occurs, on button click event

protected void btnClick_Click(object s, EventArgs e)
{
lblText.Text = «Hello from the Server! Current Date&Time: » + DateTime.Now;
}

 

As you can see, I have mixed both technologies, the ASP.NET AJAX UpdatePanels and the jQuery that has event bound to the button inside the UpdatePanel.

Once we run the website, here is what happens:

–  The website runs and the following screen will show up

– Click on the “Click Me” button and the following alert message will pop up (the jQuery function is called)

– Right after the client-side code is executed, the UpdatePanel will trigger partial postback event to the server and the result will be

– Now, we click the “Click Me” button again, but there is no Alert message anymore, even though we were expecting the alert. Partial postback has been done again and the server returns new message (see the date time difference)

The problem is reproduced, now lets explain what has happened.

After the page was loaded for first time, everything seems ok. The jQuery function waits till the DOM is fully loaded and then binds its event to the button click. However, the button is inside ASP.NET Ajax UpdatePanel which’s content will get reloaded once the partial post-back is triggered, which actually causes the event handlers to get lost.

 

I’ve seen few blogs where developers have posted some workarounds. I will post three different methods to resolve this so that you can use the one which seems more suitable for your application.

Method 1

The first method is by using the PageRequestManager. With the request manager, we can add an End Request event handler once the page has loaded after the partial post back is finished.

Here is how:

We need to write additional two JavaScript functions

load() – which will add the End Request event using the Page Request Manager and will register the jsFunctions function

jsFunctions() function which will reload the jQuery functions

<script language=»javascript» type=»text/javascript»>
function load() {
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(jsFunctions);
}
function jsFunctions() {
$(«#btnClick»).click(function () {
alert(«Alert: Hello from jQuery!»);
});
}
</script>

and we need to add

<body onload=»load()»>

which will call the load() function once the onload event occurs.

 

 

Method 2

ASP.NET Ajax has one pageLoad() method which invokes the Sys.Application.load load event. Think of the pageLoad() event similar to the Page_Load server-side event that runs on code-behind in server. Only the pageLoad() event runs on client-side, everytime the page is reloaded (no matter if the reload is full or partial). If we put the script inside this event, it will avoid all the conflicts that happen between ASP.NET Ajax and the jQuery because it will rebind the scripts every time the page will do post-back.

<body>
<script language=»javascript» type=»text/javascript»>
function pageLoad()
{
$(function () {
$(«#btnClick»).click(function () {
alert(«Alert: Hello from jQuery!»);
});
});
}
</script>

This seems definitely better than the first method since its more clear, you don’t need to create additional functions that will run on end request and you don’t need to add onload event to the body element.

 

Method 3

I won’t show anything new in this third method, but, I will show a way how to register the script from method 2 on server-side.

protected void Page_Load(object sender, EventArgs e)
{
//I’ve formatted the JS function to be more readable 😉
string javaScriptFunction =
«function pageLoad() {» +
«$(function () {» +
«$(‘#btnClick’).click(function () {» +
«alert(‘Alert: Hello from jQuery!’);» +
«});» +
«});» +
«}»;
ClientScript.RegisterStartupScript(this.GetType(), «myScript», javaScriptFunction, true);
}

I have added the script in the javaScriptFunction string, but you can add your scripts in an external JavaScript (.js) file and reference it using ClientScript.RegisterClientScriptInclude() function, so in such case we will have:

protected void Page_Load(object sender, EventArgs e)
{
ClientScript.RegisterClientScriptInclude(this.GetType(), «myScript», «Scripts/javaScriptFile.js»);
}

where the Scripts/javaScriptFile.js is the script file.

Note: There are some other methods too, such as using the jQuery live() function.

 

COMPLETE CODE

Here is the complete code implemented as in Method 2 with commented code lines for the last method with the server-side code.

<%@ Page Language=»C#» %>

<!DOCTYPE html PUBLIC «-//W3C//DTD XHTML 1.0 Transitional//EN» «http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd»>

<html xmlns=»http://www.w3.org/1999/xhtml»>
<head id=»Head1″ runat=»server»>
<title>Conflicts between ASP.NET AJAX Update Panels & JavaScript/jQuery functions</title>
<script src=»http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.min.js» type=»text/javascript»></script>
</head>
<body>
<script language=»javascript» type=»text/javascript»>
function pageLoad() {
$(function () {
$(«#btnClick»).click(function () {
alert(«Alert: Hello from jQuery!»);
});
});
}
</script>
<form id=»form1″ runat=»server»>
<div>
<asp:ScriptManager ID=»ScriptManager1″ runat=»server»>
</asp:ScriptManager>
<asp:UpdatePanel ID=»UpdatePanel1″ runat=»server»>
<ContentTemplate>
<asp:Label runat=»server» ID=»lblText» />
<br />
<asp:Button ID=»btnClick» runat=»server» Text=»Click Me» OnClick=»btnClick_Click» />
</ContentTemplate>
</asp:UpdatePanel>
<br /><br />
<%= DateTime.Now %>
<!– the Date time won’t change on button click since its outside of the update panel –>
</div>
<script runat=»server»>
protected void Page_Load(object sender, EventArgs e)
{
#region if you want to use your script in server side, uncomment the code inside this region
/*
string javaScriptFunction =
«function pageLoad() {» +
«$(function () {» +
«$(‘#btnClick’).click(function () {» +
«alert(‘Alert: Hello from jQuery!’);» +
«});» +
«});» +
«}»;

ClientScript.RegisterStartupScript(this.GetType(), «myScript», javaScriptFunction, true);
*/
#endregion

#region if you have your JS script in an external file and want to reference it, uncomment the following line
//ClientScript.RegisterClientScriptInclude(this.GetType(), «myScript», «Scripts/javaScriptFile.js»);
#endregion
}

protected void btnClick_Click(object s, EventArgs e)
{
lblText.Text = «Hello from the Server! Current Date&Time: » + DateTime.Now;
}
</script>
</form>
</body>
</html>

So, that’s it.

Even though the implementation is pretty simple, I made this blog post quite long in order to explain the details with trying not to get out of the problem boundaries.

I would like to note that I’m a big fun and I work a lot with both, the Microsoft ASP.NET Ajax and the jQuery library.

I hope this was helpful.

Kind Regards,
Hajan

Utilizar jquery ui con ASP .NET

Colocando esta linea de codigo funcionó los componentes de jquery ui con .NET

html aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="AsistenteVentas.aspx.cs" Inherits="Mantenimientos.AsistenteVentas" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 <title></title>
 <link href="css/custom.css" rel="stylesheet" />
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
 <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css" />
 <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
</head>
 <script type="text/javascript">
 function InIEvent()
 {
 $(function () {
 var xdialog;
xdialog = $('#BuscaPersonal').dialog({
 modal: true,
 autoOpen: false,
 height: 300,
 width: 650
 });
$('#xbtn_buscar').on('click', function () {
 xdialog.dialog('open');
 $('#hddorigen').val('ASISTVTA');
 });
xdialog.parent().appendTo($('form:first'));
 });
 }
$(document).ready(InIEvent);
 
 </script>
<body>
 <form id="form1" runat="server">
 <asp:ScriptManager runat="server"></asp:ScriptManager>
 <script type="text/javascript">
 Sys.WebForms.PageRequestManager.getInstance().add_endRequest(InIEvent);
 </script>
 <div class="contenido">
 <h2>Asistentes de Ventas</h2>
 <div>
 <div>
 <table>
 <tr>
 <td> 
 <asp:ImageButton ID="btnNuevoAsisVta" runat="server" ImageUrl="~/img/nuevo.png" Width="16px" OnClick="btnNuevoAsisVta_Click" />
 </td>
 </tr>
 </table>
 </div>
 <%-- Panel de mantenimiento de asistentes de ventas --%>
 <asp:UpdatePanel ID="updpnlMtoAsistVta" runat="server" UpdateMode="Conditional">
 <ContentTemplate>
 <asp:Panel ID="pnlmtoAsistVta" runat="server">
 <table class="form-tabla">
 <tr>
 <td>Codigo</td>
 <td>:</td>
 <td><asp:TextBox ID="txtcodigoAsistvta" runat="server" ReadOnly="true" Width="50px"></asp:TextBox></td>
 <td><img src="img/search.png" width="32" alt="" id="xbtn_buscar" class="img-boton" /></td>
 </tr>
 <tr>
 <td>Nombres y Apellidos</td>
 <td>:</td>
 <td colspan="2"><asp:TextBox ID="txtnomyape" runat="server" ReadOnly="true" Width="200px"></asp:TextBox></td>
 </tr>
 <tr>
 <td>Correo Electrónico</td>
 <td>:</td>
 <td colspan="2"><asp:TextBox ID="txtcorreo" runat="server" ReadOnly="true" Width="200px"></asp:TextBox></td>
 </tr>
 <tr>
 <td>L&iacute;nea</td>
 <td>:</td>
 <td colspan="2"><asp:DropDownList ID="ddl_linea" runat="server" Width="150px"></asp:DropDownList></td>
 </tr>
 <tr class="form-fila-botones">
 <td colspan="2"><asp:ImageButton ID="btnguardarAsisVta" runat="server" ImageUrl="~/img/save.png" Width="32" /></td>
 <td colspan="2"><asp:ImageButton ID="btnregresarAsisVta" runat="server" ImageUrl="~/img/back.png" Width="32" OnClick="btnregresarAsisVta_Click" /></td>
 </tr>
 </table>
 <asp:Label ID="lblmensaje1" runat="server"></asp:Label>
 </asp:Panel>
 </ContentTemplate>
 <Triggers>
 <asp:AsyncPostBackTrigger ControlID="btnguardarAsisVta" EventName="Click" />
 <asp:AsyncPostBackTrigger ControlID="btnregresarAsisVta" EventName="Click" />
 <asp:AsyncPostBackTrigger ControlID="btnNuevoAsisVta" EventName="Click" />
 </Triggers>
 </asp:UpdatePanel>
<div> 
 <%-- Grilla de asistentes de ventas --%>
<asp:GridView ID="gvAsistentes" runat="server" AutoGenerateColumns="False">
 <Columns>
 <asp:TemplateField HeaderText="ID"> 
 <ItemTemplate>
 <asp:LinkButton ID="lnkID" runat="server" Text='<%# Eval("codigo").ToString() %>'></asp:LinkButton>
 </ItemTemplate>
 </asp:TemplateField>
 <asp:BoundField DataField="linea" HeaderText="Linea" />
 <asp:BoundField DataField="nombres" HeaderText="Nombres y Apellidos" />
 <asp:BoundField DataField="correo" HeaderText="Correo electronico" />
 <asp:TemplateField>
 <ItemTemplate>
 <asp:ImageButton ID="btneliminar" runat="server" ImageUrl="~/img/eliminar.png" Width="16" /> 
 </ItemTemplate>
 </asp:TemplateField>
 </Columns>
 </asp:GridView>
 </div>
 <div id="BuscaPersonal" class="widget" title="Busqueda de personal">
 <div>
 <%-- LA BUSQUEDA DE PERSONAL --%>
 <asp:Panel ID="pnl_buscar" runat="server" DefaultButton="btn_buscar">
 <table class="form-tabla">
 <tr>
 <td>Ingrese nombres o correo electrónico</td>
 <td>:</td>
 <td><asp:TextBox ID="txtbuscar" runat="server" Width="300px"></asp:TextBox></td>
 <td><asp:ImageButton ID="btn_buscar" runat="server" ImageUrl="~/img/search.png" Width="32" OnClick="btn_buscar_Click" /></td>
 </tr>
 </table> 
 </asp:Panel>
 </div>
 <asp:UpdatePanel ID="upd1" runat="server" UpdateMode="Conditional">
 <ContentTemplate>
 <asp:GridView ID="gvpersonal" runat="server" AutoGenerateColumns="False" CssClass="grid-net" >
 <Columns>
 <asp:TemplateField HeaderText="Codigo"> 
 <ItemTemplate>
 <asp:LinkButton ID="lnkpersonal" runat="server" Text='<%# Eval("CodigoPersona").ToString() %>'></asp:LinkButton>
 </ItemTemplate>
 </asp:TemplateField>
 <asp:BoundField DataField="NombresApellidos" HeaderText="Nombres y Apellidos" />
 <asp:BoundField DataField="CorreoElectronico" HeaderText="Correo electronico" />
 </Columns>
 </asp:GridView> 
 <asp:HiddenField ID="hddorigen" runat="server" /> 
 </ContentTemplate>
 <Triggers>
 <asp:AsyncPostBackTrigger ControlID="btn_buscar" EventName="Click" />
 </Triggers>
 </asp:UpdatePanel> 
 <div>
</div>
 </div>
<div>
 <%-- LA BUSQUEDA DE PERSONAL --%>
 <h3>Personal de Ventas</h3>
 <div>
 <table>
 <tr>
 <td><asp:ImageButton ID="img_nuevo_vta" runat="server" ImageUrl="~/img/nuevo.png" Width="16px" /></td>
 </tr>
 </table>
 </div>
 <div>
 <asp:GridView ID="gv_ventas" runat="server" AutoGenerateColumns="False">
 <Columns>
 <asp:BoundField DataField="codigo" HeaderText="Codigo" />
 <asp:BoundField DataField="nombres" HeaderText="Nombres y Apellidos" />
 <asp:BoundField DataField="correo" HeaderText="Correo electrónico" />
 <asp:TemplateField>
 <ItemTemplate>
 <asp:ImageButton ID="img_eliminar_vta" runat="server" ImageUrl="~/img/eliminar.png" Width="16px" />
 </ItemTemplate>
 </asp:TemplateField>
 </Columns>
 </asp:GridView>
 </div>
 </div>
 <div>
 <table>
 <tr>
 <td>
</td>
 </tr>
 </table>
 </div>
 </div>
 </div>
 </form>
</body>
</html>

Codigo C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using DTO;
using ENT;

namespace Mantenimientos
{
 public partial class AsistenteVentas : System.Web.UI.Page
 {
 protected void Page_Load(object sender, EventArgs e)
 {
 if (!(Page.IsPostBack))
 {
 DTOAsistVta obj = new DTOAsistVta();
 List<ENTLinea> lstLinea = obj.ListarLineas();

 if (lstLinea.Count == 1 && lstLinea[0].Mensaje != null)
 {
 ScriptManager.RegisterStartupScript(this, typeof(Page), "alerta", string.Format("alert('Ha ocurrido un error: {0}", lstLinea[0].Mensaje), true);
 return;
 }

 this.ddl_linea.DataSource = lstLinea;
 this.ddl_linea.DataTextField = "NombreLinea";
 this.ddl_linea.DataValueField="CodigoLinea";
 this.DataBind();

 this.ddl_linea.Items.Insert(0, new ListItem("...Seleccione", "0"));
 //this.pnlmtoAsistVta.Style.Add(HtmlTextWriterStyle.Display, "none");
 this.pnlmtoAsistVta.Visible = false;
 }
 }

 protected void btn_buscar_Click(object sender, ImageClickEventArgs e)
 {
 DTOAsistVta obj = new DTOAsistVta();

 List<ENTPersona> lstpersona = obj.ListarColaboradores(this.txtbuscar.Text.Trim());
 
 //Verificando que no haya error

 if (lstpersona.Count == 1 && lstpersona[0].Mensaje != null)
 {
 ScriptManager.RegisterStartupScript(this, typeof(Page), "alerta", string.Format("alert('Ha ocurrido un error: {0}", lstpersona[0].Mensaje), true);
 return;
 }

 this.gvpersonal.DataSource = lstpersona;
 this.gvpersonal.DataBind();
 }

 protected void btnNuevoAsisVta_Click(object sender, ImageClickEventArgs e)
 {
 //this.pnlmtoAsistVta.Style.Add(HtmlTextWriterStyle.Display, "inline");
 this.pnlmtoAsistVta.Visible = true;
 }

 protected void btnregresarAsisVta_Click(object sender, ImageClickEventArgs e)
 {
 this.pnlmtoAsistVta.Visible = false;
 }


 }
}

No ejecutan controles de servidor ASP.NET con Jquery UI

Hay que agregar la ultima linea luego de configurar el dialog jqueryui

jQuery(function() {
    var dlg = jQuery("#dialog").dialog({
                         draggable: true,
                         resizable: true,
                         show: 'Transfer',
                         hide: 'Transfer',
                         width: 320,
                         autoOpen: false,
                         minHeight: 10,
                         minwidth: 10
                     });
    dlg.parent().appendTo(jQuery("form:first"));
})

Solucion error WCF IIS: Memoria disponible menor al 5%

El detalle del error mostrado por IIS es:

Memory gates checking failed because the free memory (373817344 bytes) is less than 5% of total memory.  As a result, the service will not be available for incoming requests.  To resolve this, either reduce the load on the machine or adjust the value of minFreeMemoryPercentageToActivateService on the serviceHostingEnvironment config element.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.InsufficientMemoryException: Memory gates checking failed because the free memory (373817344 bytes) is less than 5% of total memory.  As a result, the service will not be available for incoming requests.  To resolve this, either reduce the load on the machine or adjust the value of minFreeMemoryPercentageToActivateService on the serviceHostingEnvironment config element

Se ha solucionado añadiendo las siguientes lineas en el web config de la aplicación

<system.serviceModel> 
    <serviceHostingEnvironment minFreeMemoryPercentageToActivateService="0" />
</system.serviceModel>