<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4374571584753215005</id><updated>2011-08-24T17:56:00.293+07:00</updated><title type='text'>Web developer program</title><subtitle type='html'>blog article web develop program asp.net ms sql 2005 ajax</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://thaieasy2web.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4374571584753215005/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://thaieasy2web.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>asp.net 2.0 and sql server</name><uri>http://www.blogger.com/profile/16372934612226923917</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>6</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4374571584753215005.post-4438793664795023910</id><published>2008-08-18T09:27:00.001+07:00</published><updated>2008-08-18T09:30:51.084+07:00</updated><title type='text'>ASP.NET - Drag and Drop on a Webpage</title><content type='html'>ASP.NET - Drag and Drop on a Webpage&lt;br /&gt;&lt;br /&gt;&lt;div class="post-body entry-content"&gt;&lt;ul class="download"&gt;&lt;li&gt;&lt;a href="http://www.codeproject.com/aspnet/drag_drop/drag_drop_demo.zip"&gt;Download demo project - 35.8 Kb&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Introduction&lt;/h2&gt;&lt;p&gt;Many web applications are required to be complex yet intuitive to the user. One way to achieve this is to create objects or areas of the web page draggable and droppable. Unfortunately, ASP.NET server controls do not have the &lt;span style="font-family:Times New Roman;"&gt;&lt;code&gt;Drag&lt;/code&gt; events and &lt;code&gt;DragEventArgs&lt;/code&gt;. Fortunately, there is a way to enable drag and drop functionalities within a web page. Now keep in mind, this is not like a Windows application where you can drag files from the user's PC to the application. The drag and drop is limited to the boundaries of the web page.&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Using the code&lt;br /&gt;&lt;/h2&gt;&lt;ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Create a web application within your solution.&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Create a web page.&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Add the provided JavaScript in the &lt;span style="font-family:Times New Roman;"&gt;&lt;code lang="html"&gt;&amp;lt;HEAD&amp;gt;&lt;/code&gt; of your &lt;code lang="html"&gt;&amp;lt;HTML&amp;gt;&lt;/code&gt;. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Add two textboxes and a button in the web form.&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Add the &lt;span style="font-family:Times New Roman;"&gt;&lt;code&gt;DrawContainers&lt;/code&gt; method to the code-behind of the web page. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Ensure that the &lt;span style="font-family:Times New Roman;"&gt;&lt;code&gt;click&lt;/code&gt; event for the button calls the &lt;code&gt;DrawContainers&lt;/code&gt; method. &lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;or&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Download the source code and run the sample application. &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;JavaScript&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This is the JavaScript that enables the drag and drop to take place:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="precollapse" id="premain0" style="WIDTH: 100%"&gt;&lt;img id="preimg0" style="CURSOR: hand" height="9" alt="" src="http://www.blogger.com/asp_net%202_0%20and%20ms%20sql%20server%202005%20ajax_files/minus.gif" width="9" preid="0" /&gt;&lt;span id="precollapse0" style="MARGIN-BOTTOM: 0px; CURSOR: hand" preid="0"&gt; Collapse&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre lang="jscript" style="MARGIN-TOP: 0px"&gt;--------- Drag and Drop JavaScript -----------&lt;/pre&gt;&lt;pre lang="jscript" style="MARGIN-TOP: 0px"&gt;&lt;span class="cpp-keyword"&gt;var&lt;/span&gt; TimerID = &lt;span class="cpp-literal"&gt;0&lt;/span&gt;;&lt;br /&gt;&lt;span class="cpp-keyword"&gt;var&lt;/span&gt; oEl     = &lt;span class="cpp-keyword"&gt;null&lt;/span&gt;;&lt;br /&gt;&lt;span class="cpp-keyword"&gt;var&lt;/span&gt; oTarget = &lt;span class="cpp-keyword"&gt;null&lt;/span&gt;;&lt;br /&gt;&lt;span class="cpp-keyword"&gt;var&lt;/span&gt; beginDrag = &lt;span class="cpp-keyword"&gt;false&lt;/span&gt;;&lt;br /&gt;&lt;span class="cpp-keyword"&gt;var&lt;/span&gt; tmpHTML = &lt;span class="cpp-string"&gt;""&lt;/span&gt;; &lt;span class="cpp-keyword"&gt;function&lt;/span&gt; killTimer()&lt;br /&gt;{ &lt;span class="cpp-keyword"&gt;if&lt;/span&gt; (TimerID != &lt;span class="cpp-literal"&gt;0&lt;/span&gt; )&lt;br /&gt;    {&lt;br /&gt;        clearTimeout(TimerID);&lt;br /&gt;        TimerID = &lt;span class="cpp-literal"&gt;0&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;} &lt;span class="cpp-keyword"&gt;function&lt;/span&gt; fnShowDragWindow()&lt;br /&gt;{ &lt;span class="cpp-keyword"&gt;var&lt;/span&gt; obj = document.all(&lt;span class="cpp-string"&gt;"DW"&lt;/span&gt;);&lt;br /&gt;  &lt;br /&gt;    killTimer(); &lt;span class="cpp-keyword"&gt;if&lt;/span&gt; (oEl == &lt;span class="cpp-keyword"&gt;null&lt;/span&gt;)&lt;br /&gt;    { &lt;span class="cpp-keyword"&gt;return&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;  &lt;br /&gt;    obj.style.top        = oEl.offsetTop;&lt;br /&gt;    obj.style.left        = oEl.offsetLeft;&lt;br /&gt;    obj.style.height    = oEl.offsetHeight - &lt;span class="cpp-literal"&gt;3&lt;/span&gt;;&lt;br /&gt;    obj.style.width        = oEl.offsetWidth - &lt;span class="cpp-literal"&gt;3&lt;/span&gt;;&lt;br /&gt;    obj.innerText        = oEl.SpecimenId;&lt;br /&gt;    obj.style.display    = &lt;span class="cpp-string"&gt;"block"&lt;/span&gt;;&lt;br /&gt;    obj.style.zIndex    = &lt;span class="cpp-literal"&gt;999&lt;/span&gt;;&lt;br /&gt;  &lt;br /&gt;    window.document.attachEvent( &lt;span class="cpp-string"&gt;"onmousemove"&lt;/span&gt; , fnMove );&lt;br /&gt;    window.document.attachEvent( &lt;span class="cpp-string"&gt;"onscroll"&lt;/span&gt; , fnMove );&lt;br /&gt;    window.document.attachEvent( &lt;span class="cpp-string"&gt;"onmousemove"&lt;/span&gt; , fnCheckState );&lt;br /&gt;    window.document.attachEvent( &lt;span class="cpp-string"&gt;"onmouseup"&lt;/span&gt; , fnRelease );&lt;br /&gt;    window.document.attachEvent( &lt;span class="cpp-string"&gt;"onselectstart"&lt;/span&gt;, fnSelect ); &lt;span class="cpp-comment"&gt;//window.document.attachEvent("onmouseover",setTarget);&lt;/span&gt; beginDrag = &lt;span class="cpp-keyword"&gt;true&lt;/span&gt;;&lt;br /&gt;} &lt;span class="cpp-keyword"&gt;function&lt;/span&gt; setTarget(id)&lt;br /&gt;{ &lt;span class="cpp-keyword"&gt;var&lt;/span&gt; src = document.getElementById(id); &lt;span class="cpp-keyword"&gt;if&lt;/span&gt; (src == &lt;span class="cpp-keyword"&gt;null&lt;/span&gt;)&lt;br /&gt;    { &lt;span class="cpp-keyword"&gt;return&lt;/span&gt;;&lt;br /&gt;    } &lt;span class="cpp-keyword"&gt;if&lt;/span&gt; (src.target == '&lt;span class="cpp-keyword"&gt;true&lt;/span&gt;')&lt;br /&gt;    {&lt;br /&gt;        oTarget = src;&lt;br /&gt;    } &lt;span class="cpp-keyword"&gt;else&lt;/span&gt; {&lt;br /&gt;        oTarget = &lt;span class="cpp-keyword"&gt;null&lt;/span&gt;;  &lt;br /&gt;    }&lt;br /&gt;} &lt;span class="cpp-keyword"&gt;function&lt;/span&gt; BeginDrag(id)&lt;br /&gt;{ &lt;span class="cpp-comment"&gt;// Get the item to be dragged.&lt;/span&gt; oEl = document.getElementById(id); &lt;span class="cpp-comment"&gt;// Is there an item?&lt;/span&gt; &lt;span class="cpp-keyword"&gt;if&lt;/span&gt;(oEl == &lt;span class="cpp-keyword"&gt;null&lt;/span&gt;)&lt;br /&gt;    { &lt;span class="cpp-keyword"&gt;return&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;  &lt;br /&gt;    tmpHTML = oEl.innerHTML; &lt;span class="cpp-comment"&gt;// Set the window timeout.&lt;/span&gt; TimerID = setTimeout(fnShowDragWindow, &lt;span class="cpp-literal"&gt;1&lt;/span&gt;);&lt;br /&gt;} &lt;span class="cpp-keyword"&gt;function&lt;/span&gt; fnCheckState()&lt;br /&gt;{ &lt;span class="cpp-keyword"&gt;if&lt;/span&gt;(event.button != &lt;span class="cpp-literal"&gt;1&lt;/span&gt;)&lt;br /&gt;    {&lt;br /&gt;        fnRelease();&lt;br /&gt;    }&lt;br /&gt;} &lt;span class="cpp-keyword"&gt;function&lt;/span&gt; fnSelect()&lt;br /&gt;{ &lt;span class="cpp-keyword"&gt;return&lt;/span&gt; &lt;span class="cpp-keyword"&gt;false&lt;/span&gt;;&lt;br /&gt;} &lt;span class="cpp-keyword"&gt;function&lt;/span&gt; fnMove()&lt;br /&gt;{ &lt;span class="cpp-keyword"&gt;if&lt;/span&gt; (event.button != &lt;span class="cpp-literal"&gt;1&lt;/span&gt;)&lt;br /&gt;    {&lt;br /&gt;        fnRelease(); &lt;span class="cpp-keyword"&gt;return&lt;/span&gt;;&lt;br /&gt;    } &lt;span class="cpp-keyword"&gt;var&lt;/span&gt; obj = document.all(&lt;span class="cpp-string"&gt;"DW"&lt;/span&gt;);&lt;br /&gt;  &lt;br /&gt;    obj.style.top =&lt;br /&gt;      event.clientY - (obj.offsetHeight/&lt;span class="cpp-literal"&gt;2&lt;/span&gt;) + window.document.body.scrollTop;&lt;br /&gt;    obj.style.left = event.clientX  + window.document.body.scrollLeft;&lt;br /&gt;    window.status = 'Top=' + obj.style.top + ' Left=' + obj.style.left; &lt;span class="cpp-keyword"&gt;if&lt;/span&gt; (event.clientY &amp;gt; window.document.body.clientHeight - &lt;span class="cpp-literal"&gt;10&lt;/span&gt; )&lt;br /&gt;    {&lt;br /&gt;        window.scrollBy(&lt;span class="cpp-literal"&gt;0&lt;/span&gt;, &lt;span class="cpp-literal"&gt;10&lt;/span&gt;);&lt;br /&gt;    } &lt;span class="cpp-keyword"&gt;else&lt;/span&gt; &lt;span class="cpp-keyword"&gt;if&lt;/span&gt; (event.clientY &amp;lt; &lt;span class="cpp-literal"&gt;10&lt;/span&gt;)&lt;br /&gt;    {&lt;br /&gt;        window.scrollBy(event.clientX, -&lt;span class="cpp-literal"&gt;10&lt;/span&gt;);&lt;br /&gt;    }&lt;br /&gt;  &lt;br /&gt;} &lt;span class="cpp-keyword"&gt;function&lt;/span&gt; fnRelease()&lt;br /&gt;{ &lt;span class="cpp-keyword"&gt;if&lt;/span&gt; (beginDrag == &lt;span class="cpp-keyword"&gt;false&lt;/span&gt;) &lt;span class="cpp-keyword"&gt;return&lt;/span&gt;;&lt;br /&gt;                         &lt;br /&gt;    window.document.detachEvent( &lt;span class="cpp-string"&gt;"onmousemove"&lt;/span&gt; , fnMove );&lt;br /&gt;    window.document.detachEvent( &lt;span class="cpp-string"&gt;"onscroll"&lt;/span&gt; , fnMove );&lt;br /&gt;    window.document.detachEvent( &lt;span class="cpp-string"&gt;"onmousemove"&lt;/span&gt; , fnCheckState );&lt;br /&gt;    window.document.detachEvent( &lt;span class="cpp-string"&gt;"onmouseup"&lt;/span&gt; , fnRelease );&lt;br /&gt;    window.document.detachEvent( &lt;span class="cpp-string"&gt;"onselectstart"&lt;/span&gt;, fnSelect ); &lt;span class="cpp-comment"&gt;//window.document.detachEvent( "onmouseover", setTarget );&lt;/span&gt; &lt;span class="cpp-keyword"&gt;var&lt;/span&gt; obj = document.all(&lt;span class="cpp-string"&gt;"DW"&lt;/span&gt;); &lt;span class="cpp-keyword"&gt;if&lt;/span&gt; (oTarget != &lt;span class="cpp-keyword"&gt;null&lt;/span&gt;)&lt;br /&gt;    { &lt;span class="cpp-keyword"&gt;var&lt;/span&gt; targetHTML = oTarget.innerHTML; &lt;span class="cpp-keyword"&gt;var&lt;/span&gt; targetSpecId = oTarget.SpecimenId; &lt;span class="cpp-keyword"&gt;var&lt;/span&gt; sourceSpecId = oEl.SpecimenId;&lt;br /&gt;      &lt;br /&gt;        oEl.innerHTML = targetHTML;&lt;br /&gt;        oEl.SpecimenId = targetSpecId;&lt;br /&gt;        oTarget.SpecimenId = sourceSpecId;&lt;br /&gt;      &lt;br /&gt;        oTarget.innerHTML = tmpHTML; &lt;span class="cpp-comment"&gt;// Is the container empty?&lt;/span&gt; &lt;span class="cpp-keyword"&gt;if&lt;/span&gt;(oTarget.innerHTML != &lt;span class="cpp-string"&gt;""&lt;/span&gt;)&lt;br /&gt;        {&lt;br /&gt;            oTarget.style.backgroundColor=&lt;span class="cpp-string"&gt;"beige"&lt;/span&gt;;&lt;br /&gt;        } &lt;span class="cpp-keyword"&gt;else&lt;/span&gt; {&lt;br /&gt;            oTarget.style.backgroundColor = &lt;span class="cpp-string"&gt;"turquoise"&lt;/span&gt;;&lt;br /&gt;        } &lt;span class="cpp-keyword"&gt;if&lt;/span&gt;(oEl.innerHTML != &lt;span class="cpp-string"&gt;""&lt;/span&gt;)&lt;br /&gt;        {&lt;br /&gt;            oEl.style.backgroundColor = &lt;span class="cpp-string"&gt;"beige"&lt;/span&gt; } &lt;span class="cpp-keyword"&gt;else&lt;/span&gt; {&lt;br /&gt;            oEl.style.backgroundColor = &lt;span class="cpp-string"&gt;"turquoise"&lt;/span&gt; }&lt;br /&gt;    }&lt;br /&gt;  &lt;br /&gt;    killTimer();&lt;br /&gt;  &lt;br /&gt;    obj.style.display    = &lt;span class="cpp-string"&gt;"none"&lt;/span&gt;;&lt;br /&gt;    oEl                    = &lt;span class="cpp-keyword"&gt;null&lt;/span&gt;;&lt;br /&gt;    oTarget                = &lt;span class="cpp-keyword"&gt;null&lt;/span&gt;;&lt;br /&gt;    beginDrag            = &lt;span class="cpp-keyword"&gt;false&lt;/span&gt;;&lt;br /&gt;    TimerID                = &lt;span class="cpp-literal"&gt;0&lt;/span&gt;;&lt;br /&gt;} &lt;span class="cpp-keyword"&gt;function&lt;/span&gt; CancelDrag()&lt;br /&gt;{ &lt;span class="cpp-keyword"&gt;if&lt;/span&gt; (beginDrag == &lt;span class="cpp-keyword"&gt;false&lt;/span&gt;)&lt;br /&gt;    {&lt;br /&gt;        killTimer();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;--------- End of Drag and Drop JavaScript -----------&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;C# code behind - DrawContainers method&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This is the code behind used to create the drag and drop objects:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="precollapse" id="premain1" style="WIDTH: 100%"&gt;&lt;img id="preimg1" style="CURSOR: hand" height="9" alt="" src="http://www.blogger.com/asp_net%202_0%20and%20ms%20sql%20server%202005%20ajax_files/minus.gif" width="9" preid="1" /&gt;&lt;span id="precollapse1" style="MARGIN-BOTTOM: 0px; CURSOR: hand" preid="1"&gt; Collapse&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre lang="cs" id="pre1" style="MARGIN-TOP: 0px"&gt;&lt;span class="cs-keyword"&gt;private&lt;/span&gt; &lt;span class="cs-keyword"&gt;void&lt;/span&gt; DrawContainers()&lt;br /&gt;{&lt;br /&gt;    TableRowCollection trCol = &lt;span class="cs-keyword"&gt;this&lt;/span&gt;.Table1.Rows;&lt;br /&gt;    TableRow tr = &lt;span class="cs-keyword"&gt;null&lt;/span&gt;; &lt;span class="cs-comment"&gt;// Should we continue?&lt;/span&gt; &lt;span class="cs-keyword"&gt;if&lt;/span&gt;(&lt;span class="cs-keyword"&gt;this&lt;/span&gt;.txtContX.Text == &lt;span class="cs-keyword"&gt;null&lt;/span&gt;  &lt;span class="cs-keyword"&gt;this&lt;/span&gt;.txtContY.Text == &lt;span class="cs-keyword"&gt;null&lt;/span&gt;) &lt;span class="cs-keyword"&gt;return&lt;/span&gt;; &lt;span class="cs-comment"&gt;// Size of the row.&lt;/span&gt; &lt;span class="cs-keyword"&gt;int&lt;/span&gt; rowSize = Int32.Parse(&lt;span class="cs-keyword"&gt;this&lt;/span&gt;.txtContX.Text); &lt;span class="cs-comment"&gt;// Number of rows.&lt;/span&gt; &lt;span class="cs-keyword"&gt;int&lt;/span&gt; rowNumber = Int32.Parse(&lt;span class="cs-keyword"&gt;this&lt;/span&gt;.txtContY.Text); &lt;span class="cs-comment"&gt;// Total number of containers.&lt;/span&gt; &lt;span class="cs-keyword"&gt;int&lt;/span&gt; numberOfContainers = rowSize * rowNumber; &lt;span class="cs-comment"&gt;// Boolean value for empty table cells.&lt;/span&gt; &lt;span class="cs-keyword"&gt;bool&lt;/span&gt; isEmpty = &lt;span class="cs-keyword"&gt;false&lt;/span&gt;; &lt;span class="cs-comment"&gt;// Loop through all of the containers.&lt;/span&gt; &lt;span class="cs-keyword"&gt;for&lt;/span&gt;(&lt;span class="cs-keyword"&gt;int&lt;/span&gt; i=&lt;span class="cs-literal"&gt;0&lt;/span&gt;; i&amp;lt; numberOfContainers; i++)&lt;br /&gt;    { &lt;span class="cs-comment"&gt;// new row mod.&lt;/span&gt; &lt;span class="cs-keyword"&gt;int&lt;/span&gt; newRow =  i % rowSize; &lt;span class="cs-comment"&gt;// Should we create a new row?&lt;/span&gt; &lt;span class="cs-keyword"&gt;if&lt;/span&gt;(tr == &lt;span class="cs-keyword"&gt;null&lt;/span&gt;  newRow == &lt;span class="cs-literal"&gt;0&lt;/span&gt;)&lt;br /&gt;        {&lt;br /&gt;            tr = &lt;span class="cs-keyword"&gt;new&lt;/span&gt; TableRow();&lt;br /&gt;            trCol.Add(tr);&lt;br /&gt;        } &lt;span class="cs-comment"&gt;// Empty cell generator.&lt;/span&gt; &lt;span class="cs-keyword"&gt;if&lt;/span&gt;((i+&lt;span class="cs-literal"&gt;1&lt;/span&gt;)%&lt;span class="cs-literal"&gt;17&lt;/span&gt;==&lt;span class="cs-literal"&gt;0&lt;/span&gt;)&lt;br /&gt;        {&lt;br /&gt;            isEmpty = &lt;span class="cs-keyword"&gt;true&lt;/span&gt;;&lt;br /&gt;        } &lt;span class="cs-keyword"&gt;else&lt;/span&gt; {&lt;br /&gt;            isEmpty = &lt;span class="cs-keyword"&gt;false&lt;/span&gt;;&lt;br /&gt;        } &lt;span class="cs-comment"&gt;// Set the cell collection.&lt;/span&gt; TableCellCollection tdc = tr.Cells; &lt;span class="cs-comment"&gt;// Create a new table cell.&lt;/span&gt; TableCell td = &lt;span class="cs-keyword"&gt;new&lt;/span&gt; TableCell();&lt;br /&gt;        td.ID = &lt;span class="cpp-string"&gt;"cell_"&lt;/span&gt; + i.ToString(); &lt;span class="cs-comment"&gt;// Set the cell backcolor.&lt;/span&gt; td.BackColor = Color.Turquoise; &lt;span class="cs-comment"&gt;// Set the cell's class.&lt;/span&gt; td.CssClass = &lt;span class="cpp-string"&gt;"SpecimenLoc"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;        td.Attributes.Add(&lt;span class="cpp-string"&gt;"SpecimenId"&lt;/span&gt;, &lt;span class="cpp-string"&gt;""&lt;/span&gt;); &lt;span class="cs-comment"&gt;// Is the cell empty?&lt;/span&gt; &lt;span class="cs-keyword"&gt;if&lt;/span&gt;(!isEmpty)&lt;br /&gt;        {&lt;br /&gt;            td.Attributes.Add(&lt;span class="cpp-string"&gt;"SpecimenId"&lt;/span&gt;, i.ToString());&lt;br /&gt;            td.BackColor = Color.Beige;&lt;br /&gt;            td.Text = i.ToString();&lt;br /&gt;        } &lt;span class="cs-comment"&gt;// Add javascript attributes to the cell.&lt;/span&gt; td.Attributes.Add(&lt;span class="cpp-string"&gt;"target"&lt;/span&gt;, &lt;span class="cpp-string"&gt;"true"&lt;/span&gt;);&lt;br /&gt;        td.Attributes.Add(&lt;span class="cpp-string"&gt;"onmousedown"&lt;/span&gt;, &lt;span class="cpp-string"&gt;"BeginDrag(this.id);"&lt;/span&gt;);&lt;br /&gt;        td.Attributes.Add(&lt;span class="cpp-string"&gt;"onmouseup"&lt;/span&gt;, &lt;span class="cpp-string"&gt;"CancelDrag();"&lt;/span&gt;);&lt;br /&gt;        td.Attributes.Add(&lt;span class="cpp-string"&gt;"onmouseover"&lt;/span&gt;, &lt;span class="cpp-string"&gt;"setTarget(this.id);this.style.cursor='hand';"&lt;/span&gt;);&lt;br /&gt;        td.Attributes.Add(&lt;span class="cpp-string"&gt;"onmouseout"&lt;/span&gt;, &lt;span class="cpp-string"&gt;"this.style.cursor='default';"&lt;/span&gt;);&lt;br /&gt;        td.Width = Unit.Pixel(&lt;span class="cs-literal"&gt;35&lt;/span&gt;);&lt;br /&gt;        td.Height = Unit.Pixel(&lt;span class="cs-literal"&gt;35&lt;/span&gt;); &lt;span class="cs-comment"&gt;// Add the cell to the cell collection.&lt;/span&gt; tdc.Add(td);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;C# code behind - button click event&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The &lt;span style="font-family:Times New Roman;"&gt;&lt;code&gt;click&lt;/code&gt; event of the button:&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre lang="cs"&gt;&lt;span class="cs-keyword"&gt;private&lt;/span&gt; &lt;span class="cs-keyword"&gt;void&lt;/span&gt; btnDrawContainers_Click(&lt;span class="cs-keyword"&gt;object&lt;/span&gt; sender, System.EventArgs e)&lt;br /&gt;{ &lt;span class="cs-comment"&gt;// Draw the containers.&lt;/span&gt; &lt;span class="cs-keyword"&gt;this&lt;/span&gt;.DrawContainers();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h2&gt;About Kenny Young&lt;/h2&gt;&lt;br /&gt;B.S. - University of South Florida.&lt;br /&gt;&lt;br /&gt;Kenny currently works as a software architect at the Data Technology Coordinating Center for the Rare Diseases Clinical Research Network http://www.rarediseasesnetwork.org.&lt;br /&gt;Click &lt;a href="http://www.codeproject.com/script/profile/whos_who.asp?vt=arts&amp;amp;id=263150"&gt;here&lt;/a&gt; to view&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4374571584753215005-4438793664795023910?l=thaieasy2web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thaieasy2web.blogspot.com/feeds/4438793664795023910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4374571584753215005&amp;postID=4438793664795023910' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4374571584753215005/posts/default/4438793664795023910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4374571584753215005/posts/default/4438793664795023910'/><link rel='alternate' type='text/html' href='http://thaieasy2web.blogspot.com/2008/08/aspnet-drag-and-drop-on-webpage.html' title='ASP.NET - Drag and Drop on a Webpage'/><author><name>asp.net 2.0 and sql server</name><uri>http://www.blogger.com/profile/16372934612226923917</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4374571584753215005.post-2820548729207429859</id><published>2008-08-15T16:11:00.004+07:00</published><updated>2008-08-18T09:06:44.657+07:00</updated><title type='text'>Implementing Active Directory Services in ASP.NET 2.0</title><content type='html'>&lt;a href="http://aspnet2ajax.blogspot.com/2007/08/active-directory-and-vbnet.html"&gt;Active Directory and VB.NET&lt;/a&gt;&lt;br /&gt;&lt;h3&gt;&lt;/h3&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;p&gt;Microsoft Active Directory is a directory service that provides the foundation for distributed networks built on Windows 2000 and later domain controllers. The Active Directory APIs provide access to the data stored in a directory.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Active Directory Architecture.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/strong&gt;The directory system agent (DSA) is the process that provides access to the store. The store is the physical store of directory information located on a hard disk. Clients access the directory using one of the following mechanisms supported by the DSA:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;LDAP clients connect to the DSA using the LDAP protocol. LDAP is an acronym for Lightweight Directory Access Protocol. Active Directory supports LDAP 3.0, defined by RFC 2251, and LDAP 2.0, defined by RFC 1777.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;MAPI clients such as Microsoft Exchange connect to the DSA using the MAPI remote procedure call interface.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Windows clients that use a previous version of Windows NT connect to the DSA using the Security Account Manager (SAM) interface.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Active Directory DSA's connect to each other to perform replication using a proprietary remote procedure call interface. &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Active Directory data model is derived from the X.500 data model. The directory holds objects that represent things of various sorts, described by attributes. The universe of objects that can be stored in the directory is defined in the schema. For each object class, the schema defines what attributes an instance of the class must have, what additional attributes it may have, and what object class can be a parent of the current object class.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Active Directory schema is implemented as a set of object class instances stored in the directory. This is very different than many directories that have a schema but store it as a text file read at startup. Storing the schema in the directory has many advantages. For example, user applications can read it to discover what objects and properties are available.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Active Directory can consist of many partitions or naming contexts. The distinguished name (DN) of an object includes enough information to locate a replica of the partition that holds the object. Many times however, the user or application does not know the DN of the target object or which partition might contain the object. The global catalog (GC) allows users and applications to find objects in an Active Directory domain tree, given one or more attributes of the target object. The global catalog contains a partial replica of every naming context in the directory. It contains the schema and configuration naming contexts as well. This means the GC holds a replica of every object in Active Directory but with only a small number of their attributes.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The global catalog is built automatically by Active Directory replication system. The replication topology for the global catalog is generated automatically. The properties replicated into the global catalog include a base set defined by Microsoft. Administrators can specify additional properties to meet the needs of their installation.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Interfaces for accessing the Active Directory.&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;LDAP&lt;/strong&gt;. The Lightweight Directory Access Protocol (LDAP) is a directory service protocol that runs on a layer above the TCP/IP stack, and provides a mechanism for connecting to, searching, and modifying Internet directories. The LDAP directory service is based on a client-server model. The function of LDAP is to allow access to an existing directory. The data model (data and namespace) of LDAP is similar to that of the X.500 OSI directory service, but with lower resource requirements due to its streamlined features. The associated LDAP API simplifies writing Internet directory service applications.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;ADSI&lt;/strong&gt;. Active Directory Service Interfaces (ADSI) is a set of COM interfaces used to access the capabilities of directory services from different network providers in a distributed computing environment, to present a single set of directory service interfaces for managing network resources. Administrators and developers can use ADSI services to enumerate and manage the resources in a directory service, regardless of the network environment that contains the resource.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;System.DirectoryServices&lt;/strong&gt;. System.DirectoryServices is a namespace in the .NET Framework that provides simple programming access to LDAP directories such as Active Directory. System.DirectoryServices is built on the Active Directory Service Interfaces (ADSI) API.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Using System.DirectoryServices namespace.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/strong&gt;This article will emphasize in the benefits of using the namespace System.DirectoryServices, such as: &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Designed completely within common language runtime parameters. System.DirectoryServices leverages common language runtime features, such as garbage collection, custom indexer, and dictionaries (hashtables). It also offers other common language runtime features such as automatic memory management, efficient deployment, an object-oriented framework, evidence-based security and exception handling.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Simple to use. Although ADSI scripting was effective for many tasks, C++ applications for ADSI are sometimes difficult to develop. System.DirectoryServices implements some basic ADSI tasks to enable more efficient and effective application development. &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;System administrators can use System.DirectoryServices to automate tasks to manage network resources in the directory, such as users and computers and also to build applications that search, create, or modify objects in a directory.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Requirements. System.DirectoryServices is supported on Windows Server 2003. System.DirectoryServices can be redistributed on Windows 98, Windows 98 SE and Windows NT 4.0, as long as the DS Client is installed on client machines. It can also be redistributed on Windows 2000 Windows XP.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I developed a lot of business objects which access the Active Directory, leveraging any application which needs the platform as its main database and for publishing objects in enterprise network.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;It's defined the interface for the business objects which serve as changing or setting up the password for a specific user in the directory. Later this interface is implemented with a class, which instances make the real interaction with the directory.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In listing 1, it's shown the contract IADPasswdManager and the class ADPasswdManager.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Imports System&lt;br /&gt;&lt;br /&gt;Imports System.DirectoryServices&lt;br /&gt;&lt;br /&gt;Namespace OLAActiveDirectory.Management&lt;br /&gt;&lt;br /&gt;Public Interface IADPasswdManager&lt;br /&gt;&lt;br /&gt;Sub ChangePassword(ByVal objUser As IADUser, ByVal strOldPasswd As String, ByVal strNewPasswd As String)&lt;br /&gt;&lt;br /&gt;Sub SetPassword(ByVal objUser As IADUser, ByVal strPasswd As String)&lt;br /&gt;&lt;br /&gt;End Interface&lt;br /&gt;&lt;br /&gt;Public Class ADPasswdManager : Implements IADPasswdManager&lt;br /&gt;&lt;br /&gt;Public Sub New()&lt;br /&gt;&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;Public Sub SetPassword(ByVal objUser As IADUser, ByVal strPasswd As String) Implements IADPasswdManager.SetPassword&lt;br /&gt;&lt;br /&gt;Dim objLoginEntry As DirectoryEntry=objUser.DirectoryEntry&lt;br /&gt;&lt;br /&gt;If Not objLoginEntry Is Nothing Then&lt;br /&gt;&lt;br /&gt;objLoginEntry.Invoke("SetPassword", New Object(){strPasswd})&lt;br /&gt;&lt;br /&gt;objLoginEntry.CommitChanges()&lt;br /&gt;&lt;br /&gt;End If&lt;br /&gt;&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;Public Sub ChangePassword(ByVal objUser As IADUser, ByVal strOldPasswd As String, ByVal strNewPasswd As String) Implements IADPasswdManager.ChangePassword&lt;br /&gt;&lt;br /&gt;Dim objLoginEntry As DirectoryEntry=objUser.DirectoryEntry&lt;br /&gt;&lt;br /&gt;If Not objLoginEntry Is Nothing Then&lt;br /&gt;&lt;br /&gt;objLoginEntry.Invoke("ChangePassword",New Object(){strOldPasswd,strNewPasswd})&lt;br /&gt;&lt;br /&gt;objLoginEntry.CommitChanges()&lt;br /&gt;&lt;br /&gt;End If&lt;br /&gt;&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;End Class&lt;br /&gt;&lt;br /&gt;End Namespace&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Listing 1.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;A business entity must be defined for the users of the directory. It has all the information of a particular user in the directory knowing its Distinguished Name (DN).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;It's defined an interface IADUser and the implementation is realized in the class ADUser as shown in the Listing 2.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Imports System&lt;br /&gt;&lt;br /&gt;Imports System.DirectoryServices&lt;br /&gt;&lt;br /&gt;Imports System.Collections&lt;br /&gt;&lt;br /&gt;Namespace OLAActiveDirectory.Management&lt;br /&gt;&lt;br /&gt;Public Interface IADUser&lt;br /&gt;&lt;br /&gt;ReadOnly Property DirectoryEntry() As DirectoryEntry&lt;br /&gt;&lt;br /&gt;ReadOnly Property IsUser() As Boolean&lt;br /&gt;&lt;br /&gt;ReadOnly Default Property Item(ByVal strKey As String) As PropertyValueCollection&lt;br /&gt;&lt;br /&gt;End Interface&lt;br /&gt;&lt;br /&gt;Public Class ADUser : Implements IADUser&lt;br /&gt;&lt;br /&gt;Private ReadOnly m_objUserEntry As DirectoryEntry&lt;br /&gt;&lt;br /&gt;Public Sub New(ByVal strLogin As String, ByVal strRootPath As String)&lt;br /&gt;&lt;br /&gt;Dim objRootEntry As DirectoryEntry = New DirectoryEntry(strRootPath)&lt;br /&gt;&lt;br /&gt;Dim objADSearcher As DirectorySearcher = New DirectorySearcher(objRootEntry)&lt;br /&gt;&lt;br /&gt;objADSearcher.Filter="(&amp;amp;(objectClass=user)(anr=" &amp;amp; strLogin &amp;amp; "))"&lt;br /&gt;&lt;br /&gt;Dim objResult As SearchResult=objADSearcher.FindOne()&lt;br /&gt;&lt;br /&gt;If (Not objResult Is Nothing) Then&lt;br /&gt;&lt;br /&gt;Me.m_objUserEntry=objResult.GetDirectoryEntry()&lt;br /&gt;&lt;br /&gt;Else&lt;br /&gt;&lt;br /&gt;Me.m_objUserEntry=Nothing&lt;br /&gt;&lt;br /&gt;End If&lt;br /&gt;&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;Public ReadOnly Property DirectoryEntry() As DirectoryEntry Implements IADUser.DirectoryEntry&lt;br /&gt;&lt;br /&gt;Get&lt;br /&gt;&lt;br /&gt;Return Me.m_objUserEntry&lt;br /&gt;&lt;br /&gt;End Get&lt;br /&gt;&lt;br /&gt;End Property&lt;br /&gt;&lt;br /&gt;Public ReadOnly Default Property Item(ByVal strKey As String) As PropertyValueCollection&lt;br /&gt;&lt;br /&gt;Get&lt;br /&gt;&lt;br /&gt;Return Me.m_objUserEntry.Properties(strKey)&lt;br /&gt;&lt;br /&gt;End Get&lt;br /&gt;&lt;br /&gt;End Property&lt;br /&gt;&lt;br /&gt;Public ReadOnly Property IsUser() As Boolean Implements IADUser.IsUser&lt;br /&gt;&lt;br /&gt;Get&lt;br /&gt;&lt;br /&gt;Return Not Me.m_objUserEntry Is Nothing&lt;br /&gt;&lt;br /&gt;End Get&lt;br /&gt;&lt;br /&gt;End Property&lt;br /&gt;&lt;br /&gt;End Class&lt;br /&gt;&lt;br /&gt;End Namespace&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Listing 2.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In the Presentation Layer resides an instance of the class ADUserInfoShower whose role is to create an information string for a specific user. This object is independent of the technology used for showing the user information. That is, this string can be rendered in a Web Browser, a Windows Client and a Mobile Device. In the listing 3, it's shown the code for this business object.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Imports System&lt;br /&gt;&lt;br /&gt;Namespace OLAActiveDirectory.Management&lt;br /&gt;&lt;br /&gt;Public Interface IADUserInfoShower&lt;br /&gt;&lt;br /&gt;Function GetInformation(ByVal objUser As IADUser, ByVal strSep As String) As String&lt;br /&gt;&lt;br /&gt;End Interface&lt;br /&gt;&lt;br /&gt;Public Class ADUserInfoShower : Implements IADUserInfoShower&lt;br /&gt;&lt;br /&gt;Private Function prvInfoBuilder(ByVal objUser As IADUser, ByVal strSep As String) As String&lt;br /&gt;&lt;br /&gt;Dim strResult As String&lt;br /&gt;&lt;br /&gt;strResult="Fullname:" &amp;amp; objUser("givenName").Value &amp;amp; " " &amp;amp; objUser("sn").Value&lt;br /&gt;&lt;br /&gt;strResult &amp;amp;= strSep &amp;amp; "Mail:" &amp;amp; objUser("mail").Value&lt;br /&gt;&lt;br /&gt;strResult &amp;amp;= strSep &amp;amp; "Telephone(s):" &amp;amp; objUser("telephoneNumber").Value&lt;br /&gt;&lt;br /&gt;For Each strPhone As String In objUser("otherTelephone")&lt;br /&gt;&lt;br /&gt;strResult &amp;amp;= strSep &amp;amp; strPhone&lt;br /&gt;&lt;br /&gt;Next strPhone&lt;br /&gt;&lt;br /&gt;Return strResult&lt;br /&gt;&lt;br /&gt;End Function&lt;br /&gt;&lt;br /&gt;Public Sub New()&lt;br /&gt;&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;Public Function GetInformation(ByVal objUser As IADUser, ByVal strSep As String) As String Implements IADUserInfoShower.GetInformation&lt;br /&gt;&lt;br /&gt;Return Me.prvInfoBuilder(objUser,strSep)&lt;br /&gt;&lt;br /&gt;End Function&lt;br /&gt;&lt;br /&gt;End Class&lt;br /&gt;&lt;br /&gt;End Namespace&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;====================================================================&lt;br /&gt;จากตัวอย่างในเรื่องการ สร้าง Authen กับ Active Directory นั้น ทำการ authen นั้นผ่าน protocal LDAP ได้ ซึ่ง ผมได้ทำตัวอย่างไว้ ทั้งแบบ VB6 และแบบของ .Net เอง สร้างเป็น Class DLL แล้วนำไปใช้ใน Project นะครับ ทีนี้ เราก็จะสามารถ ตัดปัญหายุ่งยากเรื่อง username และ password อันหลากหลายในระบบงานที่พัฒนาขึ้นมาได้แล้วนะครับ ก็จะเป็นการทำ ในเรื่อง single singon นั่นเอง&lt;/p&gt;&lt;br /&gt;&lt;p&gt;============ เริ่มจาก ของ VB6 ก่อนเลยนะครับ ============&lt;br /&gt;สำหรับในตัว VB6 นั้นข้อดีของการสร้าง Active X control จาก vb6 ทำให้เราสามารถ นำ Dll นั้นไปใช้งานกับ Project ที่พัฒนาด้วย เทคโนโลยีตัวเก่า ได้นะครับ เช่นใช้งานกับ vba ของ access หรือ excel หรือใช้งานร่วมกับ ภาษาโปรแกรมตัวอื่นๆ ก็ได้ครับ หรือ จะเอาไปใช้กับเทคโนโลยีของ .net ด้วยก็ยังได้ เพราะ dll ของเทคโนโลยีตัวเก่า สามารถ ใช้งานกับตัวใหม่ได้ แต่ถ้าพัฒนาจาก .net จะไม่สามารถนำไปใช้กับ ระบบงานเก่าๆ ได้ครับ&lt;/p&gt;&lt;br /&gt;&lt;p&gt;ของเริ่มเรื่อง เลยนะครับ&lt;/p&gt;&lt;br /&gt;&lt;p&gt;เริ่มจาก เปิด visual studio 6 ขึ้นมา สร้าง Project Active X Dll นะครับ&lt;br /&gt;จากนั้นให้ เปลี่ยนชื่อ class เป็นชื่ออะไรก็ได้ ในที่นี้ผม ใช้ชื่อ cssLoginAD&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Option Explicit&lt;br /&gt;Const ADS_SECURE_AUTHENTICATION = 1&lt;br /&gt;' method สำหรับการตรวจสอบ Login AD&lt;br /&gt;Public Function ValidateAuthenAD(ByVal UserName As String, _&lt;br /&gt;ByVal Domain As String, _&lt;br /&gt;ByVal Password As String) As Integer&lt;br /&gt;Dim MyNamespace As IADsOpenDSObject&lt;br /&gt;Dim X As IADsContainer&lt;br /&gt;Dim oUserName  As String&lt;br /&gt;Dim oPassword  As String&lt;br /&gt;oUserName = UserName&lt;br /&gt;oPassword = Password&lt;br /&gt;' ตรวจสอบ login AD&lt;br /&gt;On Error GoTo CleanUp&lt;br /&gt;If InStr(1, UserName, ".", vbTextCompare) &amp;lt;&amp;gt; 0 And InStr(1, UserName, "@", vbTextCompare) = 0 Then&lt;br /&gt;oUserName = UserName&lt;br /&gt;End If&lt;br /&gt;' กำหนด Potocal LDAP สำหรับการเข้าไปค้นหา&lt;br /&gt;Set MyNamespace = GetObject("LDAP:")&lt;br /&gt;Set X = MyNamespace.OpenDSObject("LDAP://" + Domain, oUserName, oPassword, ADS_SECURE_AUTHENTICATION)&lt;br /&gt;ValidateAuthenAD = 0&lt;br /&gt;GoTo FinFonction&lt;br /&gt;CleanUp:&lt;br /&gt;Select Case Err.Number&lt;br /&gt;Case -2147023570 ' Return Error หาก password ไม่ถูกต้อง&lt;br /&gt;ValidateAuthenAD = 1&lt;br /&gt;Case -2147016646 ' return Error หาก Domain ไม่ถูกต้อง&lt;br /&gt;ValidateAuthenAD = 2&lt;br /&gt;Case Else ' return Error อื่นๆ&lt;br /&gt;ValidateAuthenAD = 99&lt;br /&gt;End Select&lt;br /&gt;FinFonction:&lt;br /&gt;Set MyNamespace = Nothing&lt;br /&gt;Set X = Nothing&lt;br /&gt;End Function&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt; &lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;strong&gt;หลักการของโปรแกรม&lt;/strong&gt; &lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Class ActiveX cssLoginAD ในเวอร์ชั่นนี้จะประกอบไปด้วย Method ให้เรียกใช้งานได้ดังต่อไปนี้&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;ValidateAuthenAD Method&lt;/strong&gt; เป็นชนิด Integer การทำงานของ method จะเปิด Directory Service ขึ้นมา เพื่อเข้าไปตรวจสอบ user และ pass และ Domain controller โดยผ่าน โปรโตคอล LDap เพื่อ Search หา user และ pass ใน DC ว่ามีอยู่หรือไม่ โดยจะ คืนค่ากลับมา เป็น 0 คือ ตรวจหาพบ หรือ error อื่นๆ ดังนี้&lt;br /&gt;0 = login ถูกต้อง&lt;br /&gt;1 = password ไม่ถูก&lt;br /&gt;2 = ไม่พบ Domain&lt;br /&gt;99 = error อื่นๆ&lt;br /&gt;parameter ที่จะส่งเข้าไปใน method นี้&lt;br /&gt;1. UserName&lt;br /&gt;2. Domain&lt;br /&gt;3. Password&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt; &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;//จากนั้นให้ทำการ Complier dll ออกมาเท่านี้ก็จะสามารถใช้งาน Authen AD ได้แล้วครับ&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;//เมื่อนำ Dll นั้นไปใช้กับ Project &lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;// สร้าง ฟังชั่นขึ้นมาเพื่อตรวจสอบ กับ Class cssLoginAD&lt;br /&gt;Private Function chkLogin(ByVal user As String, ByVal pass As String, ByVal dc As String) As Boolean&lt;br /&gt;Dim result As Boolean&lt;br /&gt;Dim AuthenAD As New cssLoginAD&lt;br /&gt;Dim valReturn As Integer&lt;br /&gt;result = False ' กำหนด ให้ ค่าเริ่มต้นเป็น False&lt;br /&gt;If user &amp;lt;&amp;gt; "" And pass &amp;lt;&amp;gt; "" And dc &amp;lt;&amp;gt; "" Then&lt;br /&gt;valReturn = AuthenAD.ValidateAuthenAD(user, dc, pass)&lt;br /&gt;Select Case valReturn&lt;br /&gt;Case 0 ' กรณี Login ถูกต้อง&lt;br /&gt;result = True&lt;br /&gt;Case 1  ' กรณี password ผิด&lt;br /&gt;MsgBox "กรุณาระบุ password ให้ถูกต้องด้วย !!", vbOKOnly + vbCritical, "Login ผิด !!"&lt;br /&gt;Case 2 ' กรณี ชื่อ Domain ผิด&lt;br /&gt;MsgBox "กรุณาระบุ Domain ให้ถูกต้องด้วย !!", vbOKOnly + vbCritical, "Login ผิด !!"&lt;br /&gt;Case Else ' error อื่นๆ&lt;br /&gt;MsgBox "Error !!"&lt;br /&gt;End Select&lt;br /&gt;Else&lt;br /&gt;' หากกรอกข้อมูลไม่ครับ&lt;br /&gt;MsgBox "กรุณากรอกข้อมูลให้ครบถ้วนด้วย !!", vbOKOnly + vbCritical, "Validate Form!!"&lt;br /&gt;End If&lt;br /&gt;Set AuthenAD = Nothing&lt;br /&gt;chkLogin = result&lt;br /&gt;End Function&lt;br /&gt;‘ ส่วนของ ปุ่ม Submit&lt;br /&gt;Private Sub Command1_Click()&lt;br /&gt;If chkLogin(txtuser.Text, txtpassword.Text, Combo1.Text) Then&lt;br /&gt;MsgBox "Login ถูกต้อง ยินดีต้อนรับคุณ " &amp;amp; txtuser.Text&lt;br /&gt;Call clearText&lt;br /&gt;End If&lt;br /&gt;End Sub&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;จากตัวอย่างด้านบนเป็นการใช้ Active X Dll ที่พัฒนาจาก vb6 สำหรับระบบงาน เก่าๆ หรือใช้งาน กับ vba กับ Access นะครับ&lt;br /&gt;ทีนี้ เรามาดูพระเอกของบทความนี้กันดีกว่า สร้าง Authen Active Directory ด้วย .Net&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;สำหรับใน .Net นั้นนะครับ ได้เตรียม namespace ไว้ให้เราเรียบร้อย จะใช้  System.DirectoryServices&lt;br /&gt;ทีนี้เรามาสร้าง Class สำหรับ authen กับ Acitve directory กันนะครับ&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;อันดับแรก ก็เปิด vs.net แล้ว สร้าง class ขึ้นมานะครับ ดังโคดด้านล่างนี้&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt; Imports System.DirectoryServices  ' impoart namespace สำหรับจัดการ directoryservice&lt;br /&gt;&lt;br /&gt;Namespace LoginAD  ' สร้าง namespace ชื่อ LoginAD เอาไว้จัดกลุ่ม class นะครับ&lt;br /&gt;    Public Class css_AuthenAD&lt;br /&gt;        ' สร้าง private property&lt;br /&gt;        Private strUser As String&lt;br /&gt;        Private strPass As String&lt;br /&gt;        Private strDomain As String&lt;br /&gt;        Private authenType As AuthenticationTypes&lt;br /&gt;&lt;br /&gt;        ' ===============================&lt;br /&gt;' สร้าง Public method&lt;br /&gt;' method สำหรับ Set Domain&lt;br /&gt;Public Function SetDomain(ByVal strValue As String) As Boolean&lt;br /&gt;If strValue.Length &amp;lt;= 0 Then Return False&lt;br /&gt;Me.strDomain = "LDAP://" &amp;amp; strValue&lt;br /&gt;Return True&lt;br /&gt;End Function&lt;br /&gt;&lt;br /&gt;' method สำหรับ Set User&lt;br /&gt;Public Function SetUser(ByVal strValue As String) As Boolean&lt;br /&gt;If strValue.Length &amp;lt;= 0 Then Return False&lt;br /&gt;Me.strUser = strValue&lt;br /&gt;Return True&lt;br /&gt;End Function&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;' method สำหรับ Set password&lt;br /&gt;Public Function SetPass(ByVal strValue As String) As Boolean&lt;br /&gt;If strValue.Length &amp;lt;= 0 Then Return False&lt;br /&gt;Me.strPass = strValue&lt;br /&gt;Return True&lt;br /&gt;End Function&lt;br /&gt;&lt;br /&gt;Public Sub SetAuthenType(Optional ByVal bValue As Boolean = False)&lt;br /&gt;If bValue Then&lt;br /&gt;' type สำหรับ edirectory&lt;br /&gt;authenType = AuthenticationTypes.SecureSocketsLayer&lt;br /&gt;Else&lt;br /&gt;' type สำหรับ Active Directory&lt;br /&gt;authenType = AuthenticationTypes.Secure&lt;br /&gt;End If&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;' และ method login สำหรับเอาไว้ authen นะครับ&lt;br /&gt;Public Function Login() As Boolean&lt;br /&gt;Dim result As Boolean = False&lt;br /&gt;Dim DirEntry As New DirectoryEntry(Me.strDomain, _&lt;br /&gt;Me.strUser, _&lt;br /&gt;Me.strPass, _&lt;br /&gt;Me.authenType)&lt;br /&gt;Try&lt;br /&gt;Dim native As Object = DirEntry.NativeObject()&lt;br /&gt;result = True&lt;br /&gt;Catch ex As Exception&lt;br /&gt;result = False&lt;br /&gt;End Try&lt;br /&gt;Return result&lt;br /&gt;End Function&lt;br /&gt;' ===============================&lt;br /&gt;End Class&lt;br /&gt;End Namespace&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4374571584753215005-2820548729207429859?l=thaieasy2web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thaieasy2web.blogspot.com/feeds/2820548729207429859/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4374571584753215005&amp;postID=2820548729207429859' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4374571584753215005/posts/default/2820548729207429859'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4374571584753215005/posts/default/2820548729207429859'/><link rel='alternate' type='text/html' href='http://thaieasy2web.blogspot.com/2008/08/implementing-active-directory-services.html' title='Implementing Active Directory Services in ASP.NET 2.0'/><author><name>asp.net 2.0 and sql server</name><uri>http://www.blogger.com/profile/16372934612226923917</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4374571584753215005.post-3399719153951314129</id><published>2008-08-15T16:08:00.000+07:00</published><updated>2008-08-15T16:11:36.044+07:00</updated><title type='text'>Using Active Directory In ASP.NET - Dump Schema Information</title><content type='html'>&lt;strong&gt;Using Active Directory In ASP.NET - Dump Schema InformationBy &lt;/strong&gt;&lt;a href="http://www.codeproject.com/script/Articles/list_articles.asp?userid=26062"&gt;&lt;strong&gt;Softomatix&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;.&lt;br /&gt;An article on using System.DirectoryServices classes in ASP.NET&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.codeproject.com/aspnet/ADSI1/ADSI1_src.zip"&gt;Download source files - 4 Kb&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.codeproject.com/aspnet/ADSI1/ADSI1_demo.zip"&gt;Download demo project - 37 Kb&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;This article is first in the series demonstrating the use of Active Directory in ASP.NET. Of course all the demo code is written in language of choice - C#. This series will not go into discussion of Active Directory or LDAP servers. We are assuming that the readers of these articles have basic understanding of these technologies.&lt;br /&gt;&lt;/p&gt;&lt;h2&gt;.NET namespace and classes utilized&lt;br /&gt;&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;System.DirectoryServices&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;System.DirectoryServices.DirectoryEntry&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;System.DirectoryServices.DirectorySearcher&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;System.DirectoryServices.SearchResultCollection&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;System.DirectoryServices.SearchResult&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;System.DirectoryServices.ResultPropertyCollection&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;System.DirectoryServices.PropertyValueCollection&lt;/em&gt; &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;What is this article about?&lt;br /&gt;&lt;/h2&gt;&lt;p&gt;Searching an Active Directory is one of the major tasks in manipulation of various resources. When I started with ADSI programming, I used to look for right kind of filter values to use. Some time I had to go back forth and look at the Active Directory schema to find value I should be using to get the information I was looking for. For example If you want to get the information when the user account was last changed, you need to create a filter looking for &lt;em&gt;whenchanged&lt;/em&gt; property in schema. So we decided to write a small dump utility that will display all the properties that are used to describe a user's account in Active Directory. &lt;/p&gt;&lt;br /&gt;&lt;h2&gt;How To Do It&lt;br /&gt;&lt;/h2&gt;&lt;p&gt;The first step in using Directory Services interfaces is to make connection with the node that you want to search for. .NET framework provides &lt;code&gt;DirectoryEntry &lt;/code&gt;class to specify the search node. For example if you want to search for a resource in whole domain, then you need to connect to the top node of domain in Active Directory. It is very important that you specify the search location as close as possible to the nearest location where the resource could be found. Otherwise the search will take longer time. For example if You want to search for a user information, you need to specify the location as User node and not the whole domain resource tree. &lt;/p&gt;&lt;br /&gt;&lt;pre lang="cs"&gt;string strLDAP = "LDAP://pardesiservices.com"&lt;br /&gt;m_obDirEntry = new DirectoryEntry(strLDAP);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;After initializing the search node, you need to specify the query string in &lt;code&gt;DirectorySearcher&lt;/code&gt; class object. You can set various parameter values of this object to fine tune your search and how the results will be returned. For this article we will only mention &lt;code&gt;Filter&lt;/code&gt; property. This is the property that you will use to set your query string. The query string shall be specified in LDAP format. For example if you want to search for a user &lt;em&gt;"foo"&lt;/em&gt;, you can specify the query string as &lt;code&gt;(cn=foo)&lt;/code&gt;. It is very important that you specify the filter/query in parentheses. For more information on this property, look in the .NET documentation for &lt;code&gt;Filter&lt;/code&gt; property of &lt;code&gt;DirectorySearcher&lt;/code&gt; class. &lt;/p&gt;&lt;br /&gt;&lt;pre lang="cs"&gt;DirectorySearcher srch = new DirectorySearcher(m_obDirEntry);&lt;br /&gt;srch.Filter = "(cn=foo)";&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The next step is to start the search. You will call &lt;code&gt;FindAll&lt;/code&gt; or &lt;code&gt;FindOne&lt;/code&gt; method on &lt;code&gt;DirectorySearcher&lt;/code&gt; class object. If you are only interested in the first entry of the returned results, then call &lt;code&gt;FindOne&lt;/code&gt;. Otherwise if you want to get all the search results, call &lt;code&gt;FindAll&lt;/code&gt; method. This method returns the results as &lt;code&gt;SearchResultCollection&lt;/code&gt; class subject. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;The other property that is worth mentioning is &lt;code&gt;PropertiesToLoad&lt;/code&gt;. This property lets you specify the values you want the search to return. If you don't specify any properties, then search returns all the properties by default. Therefore if you are only interested in some of the values, then make sure that you specify those properties in the &lt;code&gt;PropertiesToLoad&lt;/code&gt;. This way you can avoid unnecessary loading of all the values in memory. &lt;/p&gt;&lt;br /&gt;&lt;pre lang="cs"&gt;SearchResultCollection results;&lt;br /&gt;results = srch.FindAll();&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;After getting all the search results, you can iterate over each &lt;code&gt;SearchResult&lt;/code&gt; entry in the &lt;code&gt;SearchResultCollection&lt;/code&gt;. The &lt;code&gt;SearchResult&lt;/code&gt; class object has &lt;code&gt;Properties&lt;/code&gt; property that returns &lt;code&gt;ResultPropertyCollection&lt;/code&gt; object. This contains all the properties were found by search you specified. &lt;/p&gt;&lt;br /&gt;&lt;pre lang="cs"&gt;foreach (SearchResult result in results)&lt;br /&gt;{&lt;br /&gt;   ResultPropertyCollection propColl = result.Properties;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&lt;code&gt;ResultPropertyCollection&lt;/code&gt; exposes &lt;code&gt;ProperyNames&lt;/code&gt; property that returns the collection containing names of all the properties returned by search. You can iterate over this collection to get the names. We used this technique to get the names of all properties exposed by User objects. &lt;/p&gt;&lt;br /&gt;&lt;pre lang="cs"&gt;foreach (string strKey in propColl.PropertyNames)&lt;br /&gt;{&lt;br /&gt;  foreach (object obProp in propColl[strKey])&lt;br /&gt;  {&lt;br /&gt;    this.AppendPropertyNode(obTopNode, strKey, obProp);&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;And then you can use this property names to extract particular values from &lt;code&gt;ResultPropertyCollection&lt;/code&gt; dictionary. &lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Demo Code&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;We have included the demo code with this article. All the Active Directory implementation has been encapsulated in &lt;code&gt;ADSIUtil&lt;/code&gt; class. We have also created an utility class, &lt;code&gt;ADSIUser&lt;/code&gt;. This class parses the search results and saves as a &lt;code&gt;XMLDocument&lt;/code&gt;. And it also exposes some properties to get specific information like First Name, Last Name, etc. This class is not complete. But we will expand this as the series progress. &lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Platforms Tested&lt;/h2&gt;&lt;br /&gt;We have tested the included project on following platforms&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Windows 2000 Adv. Server&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Windows .NET Enterprise Server (Beta 3)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Contact Us&lt;br /&gt;&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;For any suggections ot comment you can visit us as at &lt;a href="http://www.pardesiservices.com/softomatix.asp"&gt;Softomatix&lt;/a&gt; or write to us, &lt;a href="mailto:softomatix@pardesiservices.com"&gt;softomatix@pardesiservices.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;About Softomatix&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;To learn more about us, Please visit us at http://www.netomatix.com&lt;br /&gt;Click &lt;/span&gt;&lt;a href="http://www.codeproject.com/script/profile/whos_who.asp?vt=arts&amp;amp;id=26062"&gt;&lt;span style="font-size:100%;"&gt;here&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:100%;"&gt; to view Softomatix's online profile.&lt;/span&gt;&lt;/h2&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4374571584753215005-3399719153951314129?l=thaieasy2web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thaieasy2web.blogspot.com/feeds/3399719153951314129/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4374571584753215005&amp;postID=3399719153951314129' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4374571584753215005/posts/default/3399719153951314129'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4374571584753215005/posts/default/3399719153951314129'/><link rel='alternate' type='text/html' href='http://thaieasy2web.blogspot.com/2008/08/using-active-directory-in-aspnet-dump.html' title='Using Active Directory In ASP.NET - Dump Schema Information'/><author><name>asp.net 2.0 and sql server</name><uri>http://www.blogger.com/profile/16372934612226923917</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4374571584753215005.post-6454416677570422369</id><published>2008-08-15T16:07:00.001+07:00</published><updated>2008-08-15T16:07:48.903+07:00</updated><title type='text'>HOW TO: ASP.NET Generate PDF Output</title><content type='html'>สวัสดีครับ สำหรับในบทความนี้นะครับ จะเป็นบทความต่อจาก คราวที่แล้ว คือ วิธีการเขียน asp.net ให้ gen ข้อมูลออกมาเป็น PDF file ครับ&lt;br /&gt;&lt;br /&gt;กล่าวนำนิดนึง หลายคนที่พัฒนา web application ด้วย asp.net คงจะ เจอปัญหา เวลาสั่ง print report ซึ่ง เมื่อ เราสั่ง print แล้วโดยปกติ จะได้ url อันไม่พึงประสงค์ติด มาพร้อมกับ รายงานด้วยนะครับ&lt;br /&gt;วิธีการที่จะทำให้ เวลาที่เราสั่ง print แล้ว ได้ออกมาเป็นรูปแบบรายงานที่สวยงาม ไม่มี url ติดมา นั้น เราจำเป็นต้องทำ ออกมาเป็น PDF ไฟล์ก่อน จากนั้นถึงจะสั่ง print นะครับ&lt;br /&gt;&lt;br /&gt;ซึ่งการทำ ให้ asp.net export ออกมาเป็น pdf มีอยู่มากมายหลายวิธี หรือใช้ component ช่วย ก็มีหลายตัว ทั้งเสียเงิน และไม่เสียเงิน&lt;br /&gt;&lt;br /&gt;สำหรับวิธีการนี้ ผมจะใช้ component ฟรี ที่ช่วยในการ เขียน PDF นะครับ โดยผมขอแนะนำตัวช่วย ที่ได้กล่าวไปเมื่อกี้นะครับ คือ Itextsharp&lt;br /&gt;หลายๆ คนคงจะรู้จัก กันพอสมควรแล้วนะครับ ว่า itextsharp คือ open source ที่พัฒนาขึ้นมาเพื่อ ทำงานกับ เอกสารได้เป็นอย่างดี โดยจะสามารถดาวน์โหลด component ได้ที่ &lt;a href="http://itextsharp.sourceforge.net/" target="_blank"&gt;&lt;span style="color:#de7008;"&gt;http://itextsharp.sourceforge.net/&lt;/span&gt;&lt;/a&gt; เมื่อดาวน์โหลดมาแล้ว เราจะได้ไฟล์ itextsharp.dll มา ตัวนี้แหละครับที่เราจะเอามา add reference เข้ามาใน Project ของเรา เพื่อเขียน gen pdf ไฟล์ครับ&lt;br /&gt;&lt;br /&gt;ขั้นตอนในการใช้งาน Itextsharp เพื่อ เขียน PDF&lt;br /&gt;1. เปิด vs.net ขึ้นมา สร้าง project ขึ้นจากนั้น ก็ทำการ add reference ไฟล์ itextsharp.dll ที่ดาวน์โหลด มา เข้าไปไว้ในโปรเจค เพื่อจะสามารถใช้งาน library ต่างๆได้&lt;br /&gt;2. ที่ส่วนหัวของหน้า code ให้ทำการ import namespace เข้ามา&lt;br /&gt;&lt;br /&gt;using iTextSharp.text;&lt;br /&gt;using iTextSharp.text.pdf;&lt;br /&gt;&lt;br /&gt;3. ส่วนโคดที่จะใช้ในการเขียน เพื่อสร้างเอกสาร pdf นั้น จะให้อยู่ใน event page_load นะครับ แล้วเขียนดังนี้&lt;br /&gt;// ขั้นแรก จะต้องทำการ create object document ขึ้นมา&lt;br /&gt;Document document = new Document(); // การ create document แบบแนว ตั้งปกติ ซึ่งเราอาจจะ จัดเอกสารให้เป็นขนาดอื่นๆ หรือ เป็นแนวตั้งได้ดังนี้&lt;br /&gt;// Document document = new Document(&lt;span style="color:#3333ff;"&gt;&lt;strong&gt;&lt;span style="color:#000000;"&gt;PageSize.A4.Rotate()&lt;/span&gt;&lt;/strong&gt;,&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;span style="color:#ff0000;"&gt;&lt;strong&gt;20,20,20,20&lt;/strong&gt;&lt;/span&gt;);&lt;br /&gt;// ส่วนที่เป็น สีน้ำเงิน คือ ส่วนที่จะระบุเข้าไปในเอกสาร คือ ให้มีขนาด เป็น A4 และ สีแดงคือ margin ของเอกสาร&lt;br /&gt;&lt;br /&gt;string filename = Server.MapPath("&lt;/span&gt;&lt;strong&gt;../report_pdf/ชื่อไฟล์.pdf&lt;/strong&gt;"); // กำหนด path และชื่อไฟล์&lt;br /&gt;PdfWriter.GetInstance(document, new FileStream(filename, FileMode.Create));&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// เริ่มทำการ Add meta information ของเอกสาร&lt;br /&gt;document.AddAuthor("Test asp.net gen Report PDF");&lt;br /&gt;document.AddSubject("This is the result of Report.");&lt;br /&gt;document.Open(); // เปิด object เอกสารเพื่อทำการเขียนข้อมูล&lt;br /&gt;&lt;br /&gt;// กำหนด font ภาษาไทย เราสามารถกำหนด ชนิดของ font ได้ว่าจะให้เป็น font ตัวไหน หรือจะ upload font ขึ้นไปไว้บน server แล้วทำการ อ้าง path ก็ได้นะครับ หากไม่กำหนด font เราจะสามารถใช้ ภาษาไทย ได้นะครับ&lt;br /&gt;BaseFont EnCodefont = BaseFont.CreateFont(Server.MapPath("../font/&lt;span style="color:#ff0000;"&gt;ANGSA.TTF&lt;/span&gt;"), &lt;span style="color:#ff0000;"&gt;BaseFont.IDENTITY_H, BaseFont.EMBEDDED&lt;/span&gt;);&lt;br /&gt;Font Nfont= new Font(EnCodefont, 18, Font.NORMAL, new Color(0, 0, 255));&lt;br /&gt;// ===================&lt;br /&gt;&lt;br /&gt;// การเขียน ข้อมูลลงใน PDF นั้นทำได้ ด้วยการใช้ method add และ ข้อมูลที่จะใส่ไว้ใน method add นั้น เราสามารถ สร้าง object ข้อมูลได้ หลายอย่างมากครับ ผมจะขอ นำเสอน ทีละอย่างนะครับ&lt;br /&gt;// อย่างแรก การสร้างข้อมูลด้วย object paragraph แล้วกำหนด รูปแบบ font ด้วยตัวแปร Nfont ที่ได้สร้างไว้&lt;br /&gt;document.Add(new Paragraph("รายงานข้อมูลประจำวันที่ " + DateTime.ToString("dd/MM/yyyy"), Nfont));&lt;br /&gt;document.Close();&lt;br /&gt;&lt;br /&gt;// อย่างที่สองการสร้าง เป็น table ด้วย object table&lt;br /&gt;Table DT = new Table(4); // สร้าง table columns 4 columns&lt;br /&gt;DT.Padding = 2; // กำหนด ระยะของ ขอบ ตารางและตัวอักษร&lt;br /&gt;DT.Spacing = 0; //กำหนดระยะของขอบตาราง&lt;br /&gt;DT.DefaultHorizontalAlignment = Element.ALIGN_CENTER; // จัดเรียก alignment&lt;br /&gt;DT.DefaultVerticalAlignment = Element.ALIGN_TOP;&lt;br /&gt;float[] headerwidths = { 12, 18, 10, 10 }; // กำหนด ความกว้างของ columns&lt;br /&gt;DT.Widths = headerwidths;&lt;br /&gt;DT.WidthPercentage = 100;&lt;br /&gt;DT.AddCell(new Phrase("ลำดับ", Sfont)); // columns 1&lt;br /&gt;DT.AddCell(new Phrase("ชื่อ - นามสกุล", Sfont)); // columns 2&lt;br /&gt;DT.AddCell(new Phrase("เพศ", Sfont)); // columns 3&lt;br /&gt;DT.AddCell(new Phrase("อายุ", Sfont)); // columns 4&lt;br /&gt;&lt;br /&gt;// เมื่อได้ object tableของข้อมูลมาแล้ว ก็จะทำการ Add ใน method add ของ object document&lt;br /&gt;document.Add(DT);&lt;br /&gt;document.Close();&lt;br /&gt;&lt;br /&gt;// เพียงเท่านี้ เราก็จะสามารถ create PDF ไฟล์ได้แล้วครับ&lt;br /&gt;// ที่เหลือ ก็จะเป็นการ นำเอาไปปรับเปลี่ยนวิธีการเพื่อแสดง ผล แล้วก็ advance ต่อไป ซึ่ง จะมีทั้งตัวอย่าง การทำในแบบต่างๆ อยู่ในไฟล์ ที่ itextsharp ได้ทำไว้ให้เป็น sample ด้วยมากมาย ผมขอ ยกมากล่าว เพียงเท่านี้นะครับ&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4374571584753215005-6454416677570422369?l=thaieasy2web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thaieasy2web.blogspot.com/feeds/6454416677570422369/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4374571584753215005&amp;postID=6454416677570422369' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4374571584753215005/posts/default/6454416677570422369'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4374571584753215005/posts/default/6454416677570422369'/><link rel='alternate' type='text/html' href='http://thaieasy2web.blogspot.com/2008/08/how-to-aspnet-generate-pdf-output.html' title='HOW TO: ASP.NET Generate PDF Output'/><author><name>asp.net 2.0 and sql server</name><uri>http://www.blogger.com/profile/16372934612226923917</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4374571584753215005.post-8836639653931109154</id><published>2008-08-15T16:03:00.000+07:00</published><updated>2008-08-15T16:07:01.229+07:00</updated><title type='text'>asp.net connect upload FTP</title><content type='html'>ในเรื่องการ upload ไฟล์ หลายคน อาจจะเจอปัญหา การ upload ไฟล์ ขนาดใหญ่มากๆ ซึ่ง หากเราใช้ asp.net ปกติ upload ไฟล์ขนาดใหญ่ จะต้องทำการ เซ็ทค่า ให้สามารถ upload ไฟล์ขนาดใหญ่ได้เสียก่อน ไม่อย่างนั้น จะเกิดการ timeout ขึ้น การ เซ็ทค่า เราอาจจะทำจาก web.config ได้ดังนี้&lt;br /&gt;ซึ่งค่าปกติ ที่กำหนดไว้ โดยประมาณคือ 4M หรือ ขนาด maxRequestLength = 4096 ซึ่งเรา&lt;br /&gt;จากการ upload แบบธรรมดาที่ได้กล่าวไปนั้นจะเป็นการ upload โดยผ่าน HTTP เต็มที่ของไฟล์ ก็คงไม่สามารถ upload ไฟล์ ขนาดเป็นร้อยM ได้&lt;br /&gt;ดังนั้นวิธีที่ดีที่สุดสำหรับการ upload ไฟล์ ขนาดใหญ่มากๆ ด้วย asp.net จึงจำเป็นต้องใช้ protocal FTP สำหรับ รับส่งข้อมูลโดยตรง&lt;br /&gt;สำหรับการใช้ asp.net ติดต่อไปยัง FTP เพื่อ ทำการ Transfer Data ผ่าน Protocal FTP นั้น เราสามารถมารถทำได้ สำหรับในตัวอย่างบทความนี้ จะเป็นการใช้ asp.net by C# ในการเขียน Class เพื่อติดต่อ FTP ไปยัง host แล้วทำการ upload ไฟล์ ขึ้นไปนะครับ&lt;br /&gt;ขั้นแรก ที่ project ให้ add new ITEM Class ขึ้นมา จากนั้นก็ทำการสร้าง class namespace FTP&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.msit.mut.ac.th/member/filemanager/share_file/hikari/webFTPclient.zip" target="_blank"&gt;สามารถดาวน์โหลด class FTPclient ได้จากที่นี่&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;เมื่อได้ Class Namespace สำหรับ Ftpclient เรียบร้อยแล้ว ต่อไปจะเป็นการ สร้างโคดสำหรับเรียกใช้งาน class namespace ftpต่อมา Addnew item สร้างไฟล์ aspx ปกติ แล้วสร้างฟอร์ม upload ไฟล์&lt;br /&gt;&lt;br /&gt;โคดทั้งหมด สามารถดาวน์โหลดได้ ที่ link ด้านบนครับ&lt;br /&gt;&lt;br /&gt;เมื่อดาวน์โหลดไฟล์ทั้งหมดไปแล้ว ในหน้า CS จะมีตัวแปร FTPhost,FTPuser,FTPpass อย่าลืมระบุค่าของ ftp server ลงไปด้วยนะครับ&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4374571584753215005-8836639653931109154?l=thaieasy2web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thaieasy2web.blogspot.com/feeds/8836639653931109154/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4374571584753215005&amp;postID=8836639653931109154' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4374571584753215005/posts/default/8836639653931109154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4374571584753215005/posts/default/8836639653931109154'/><link rel='alternate' type='text/html' href='http://thaieasy2web.blogspot.com/2008/08/aspnet-connect-upload-ftp.html' title='asp.net connect upload FTP'/><author><name>asp.net 2.0 and sql server</name><uri>http://www.blogger.com/profile/16372934612226923917</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4374571584753215005.post-5966292237730037990</id><published>2008-08-15T15:53:00.002+07:00</published><updated>2008-08-15T16:02:57.094+07:00</updated><title type='text'>Active Directory and VB.NET</title><content type='html'>&lt;p&gt;&lt;span style="color:#ff6600;"&gt;&lt;span style="font-family:Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="color:#000000;"&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Microsoft Active Directory is a directory service that provides the foundation for distributed networks built on Windows 2000 and later domain controllers. The Active Directory APIs provide access to the data stored in a directory.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;span style="font-family:Verdana, Arial, Helvetica, sans-serif;color:#990000;"&gt;&lt;strong&gt;Active Directory Architecture.&lt;br /&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style="color:#ff6600;"&gt;&lt;span style="font-family:Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="color:#000000;"&gt;The directory system agent (DSA) is the process that provides access to the store. The store is the physical store of directory information located on a hard disk. Clients access the directory using one of the following mechanisms supported by the DSA:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#ff6600;"&gt;&lt;span style="font-family:Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="color:#ff6600;"&gt;&lt;span style="font-family:Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="color:#000000;"&gt;LDAP clients connect to the DSA using the LDAP protocol. LDAP is an acronym for Lightweight Directory Access Protocol. Active Directory supports LDAP 3.0, defined by RFC 2251, and LDAP 2.0, defined by RFC 1777.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="color:#ff6600;"&gt;&lt;span style="font-family:Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="color:#000000;"&gt;MAPI clients such as Microsoft Exchange connect to the DSA using the MAPI remote procedure call interface.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="color:#ff6600;"&gt;&lt;span style="font-family:Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="color:#000000;"&gt;Windows clients that use a previous version of Windows NT connect to the DSA using the Security Account Manager (SAM) interface.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="color:#ff6600;"&gt;&lt;span style="font-family:Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="color:#000000;"&gt;Active Directory DSA's connect to each other to perform replication using a proprietary remote procedure call interface. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="color:#ff6600;"&gt;&lt;span style="font-family:Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="color:#000000;"&gt;Active Directory data model is derived from the X.500 data model. The directory holds objects that represent things of various sorts, described by attributes. The universe of objects that can be stored in the directory is defined in the schema. For each object class, the schema defines what attributes an instance of the class must have, what additional attributes it may have, and what object class can be a parent of the current object class.&lt;br /&gt;&lt;br /&gt;Active Directory schema is implemented as a set of object class instances stored in the directory. This is very different than many directories that have a schema but store it as a text file read at startup. Storing the schema in the directory has many advantages. For example, user applications can read it to discover what objects and properties are available.&lt;br /&gt;&lt;br /&gt;Active Directory can consist of many partitions or naming contexts. The distinguished name (DN) of an object includes enough information to locate a replica of the partition that holds the object. Many times however, the user or application does not know the DN of the target object or which partition might contain the object. The global catalog (GC) allows users and applications to find objects in an Active Directory domain tree, given one or more attributes of the target object. The global catalog contains a partial replica of every naming context in the directory. It contains the schema and configuration naming contexts as well. This means the GC holds a replica of every object in Active Directory but with only a small number of their attributes.&lt;br /&gt;&lt;br /&gt;The global catalog is built automatically by Active Directory replication system. The replication topology for the global catalog is generated automatically. The properties replicated into the global catalog include a base set defined by Microsoft. Administrators can specify additional properties to meet the needs of their installation.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="color:#990000;"&gt;Interfaces for accessing the Active Directory.&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="color:#ff6600;"&gt;&lt;span style="font-family:Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="color:#000000;"&gt;&lt;strong&gt;&lt;span style="color:#990000;"&gt;LDAP&lt;/span&gt;&lt;/strong&gt;. The Lightweight Directory Access Protocol (LDAP) is a directory service protocol that runs on a layer above the TCP/IP stack, and provides a mechanism for connecting to, searching, and modifying Internet directories. The LDAP directory service is based on a client-server model. The function of LDAP is to allow access to an existing directory. The data model (data and namespace) of LDAP is similar to that of the X.500 OSI directory service, but with lower resource requirements due to its streamlined features. The associated LDAP API simplifies writing Internet directory service applications.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="color:#ff6600;"&gt;&lt;span style="font-family:Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="color:#000000;"&gt;&lt;strong&gt;&lt;span style="color:#990000;"&gt;ADSI&lt;/span&gt;&lt;/strong&gt;. Active Directory Service Interfaces (ADSI) is a set of COM interfaces used to access the capabilities of directory services from different network providers in a distributed computing environment, to present a single set of directory service interfaces for managing network resources. Administrators and developers can use ADSI services to enumerate and manage the resources in a directory service, regardless of the network environment that contains the resource.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="color:#ff6600;"&gt;&lt;span style="font-family:Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="color:#000000;"&gt;&lt;strong&gt;&lt;span style="color:#990000;"&gt;System.DirectoryServices&lt;/span&gt;&lt;/strong&gt;. System.DirectoryServices is a namespace in the .NET Framework that provides simple programming access to LDAP directories such as Active Directory. System.DirectoryServices is built on the Active Directory Service Interfaces (ADSI) API.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="color:#990000;"&gt;Using System.DirectoryServices namespace.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/strong&gt;This article will emphasize in the benefits of using the namespace System.DirectoryServices, such as: &lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Designed completely within common language runtime parameters. System.DirectoryServices leverages common language runtime features, such as garbage collection, custom indexer, and dictionaries (hashtables). It also offers other common language runtime features such as automatic memory management, efficient deployment, an object-oriented framework, evidence-based security and exception handling.&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Simple to use. Although ADSI scripting was effective for many tasks, C++ applications for ADSI are sometimes difficult to develop. System.DirectoryServices implements some basic ADSI tasks to enable more efficient and effective application development. &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;System administrators can use System.DirectoryServices to automate tasks to manage network resources in the directory, such as users and computers and also to build applications that search, create, or modify objects in a directory.&lt;br /&gt;&lt;br /&gt;Requirements. System.DirectoryServices is supported on Windows Server 2003. System.DirectoryServices can be redistributed on Windows 98, Windows 98 SE and Windows NT 4.0, as long as the DS Client is installed on client machines. It can also be redistributed on Windows 2000 Windows XP.&lt;br /&gt;&lt;br /&gt;I developed a lot of business objects which access the Active Directory, leveraging any application which needs the platform as its main database and for publishing objects in enterprise network.&lt;br /&gt;&lt;br /&gt;It's defined the interface for the business objects which serve as changing or setting up the password for a specific user in the directory. Later this interface is implemented with a class, which instances make the real interaction with the directory.&lt;br /&gt;&lt;br /&gt;In listing 1, it's shown the contract IADPasswdManager and the class ADPasswdManager.&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Imports&lt;/span&gt; System&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Imports&lt;/span&gt; System.DirectoryServices&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Namespace&lt;/span&gt; OLAActiveDirectory.Management&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Interface&lt;/span&gt; IADPasswdManager&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Sub&lt;/span&gt; ChangePassword(&lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; objUser &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; IADUser, &lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; strOldPasswd &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;String&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; strNewPasswd &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;String&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Sub&lt;/span&gt; SetPassword(&lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; objUser &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; IADUser, &lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; strPasswd &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;String&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Interface&lt;br /&gt;&lt;br /&gt;Public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Class&lt;/span&gt; ADPasswdManager : &lt;span style="color:#0000ff;"&gt;Implements&lt;/span&gt; IADPasswdManager&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Sub&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;New&lt;/span&gt;()&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Sub&lt;br /&gt;&lt;br /&gt;Public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Sub&lt;/span&gt; SetPassword(&lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; objUser &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; IADUser, &lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; strPasswd &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;String&lt;/span&gt;) &lt;span style="color:#0000ff;"&gt;Implements&lt;/span&gt; IADPasswdManager.SetPassword&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Dim&lt;/span&gt; objLoginEntry &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; DirectoryEntry=objUser.DirectoryEntry&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;If&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Not&lt;/span&gt; objLoginEntry &lt;span style="color:#0000ff;"&gt;Is&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Nothing&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Then&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;objLoginEntry.Invoke("SetPassword", &lt;span style="color:#0000ff;"&gt;New&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Object&lt;/span&gt;(){strPasswd})&lt;br /&gt;&lt;br /&gt;objLoginEntry.CommitChanges()&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;If&lt;br /&gt;&lt;br /&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Sub&lt;br /&gt;&lt;br /&gt;Public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Sub&lt;/span&gt; ChangePassword(&lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; objUser &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; IADUser, &lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; strOldPasswd &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;String&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; strNewPasswd &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;String&lt;/span&gt;) &lt;span style="color:#0000ff;"&gt;Implements&lt;/span&gt; IADPasswdManager.ChangePassword&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Dim&lt;/span&gt; objLoginEntry &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; DirectoryEntry=objUser.DirectoryEntry&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;If&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Not&lt;/span&gt; objLoginEntry &lt;span style="color:#0000ff;"&gt;Is&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Nothing&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Then&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;objLoginEntry.Invoke("ChangePassword",&lt;span style="color:#0000ff;"&gt;New&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Object&lt;/span&gt;(){strOldPasswd,strNewPasswd})&lt;br /&gt;&lt;br /&gt;objLoginEntry.CommitChanges()&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;If&lt;br /&gt;&lt;br /&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Sub&lt;br /&gt;&lt;br /&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Class&lt;br /&gt;&lt;br /&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Namespace&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Listing 1.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;A business entity must be defined for the users of the directory. It has all the information of a particular user in the directory knowing its Distinguished Name (DN).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;It's defined an interface IADUser and the implementation is realized in the class ADUser as shown in the Listing 2.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Imports&lt;/span&gt; System&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Imports&lt;/span&gt; System.DirectoryServices&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Imports&lt;/span&gt; System.Collections&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Namespace&lt;/span&gt; OLAActiveDirectory.Management&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Interface&lt;/span&gt; IADUser&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;ReadOnly&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt; DirectoryEntry() &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; DirectoryEntry&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;ReadOnly&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt; IsUser() &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Boolean&lt;br /&gt;&lt;br /&gt;ReadOnly&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Default&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt; Item(&lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; strKey &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;String&lt;/span&gt;) &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; PropertyValueCollection&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Interface&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Class&lt;/span&gt; ADUser : &lt;span style="color:#0000ff;"&gt;Implements&lt;/span&gt; IADUser&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;ReadOnly&lt;/span&gt; m_objUserEntry &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; DirectoryEntry&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Sub&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;New&lt;/span&gt;(&lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; strLogin &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;String&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; strRootPath &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;String&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Dim&lt;/span&gt; objRootEntry &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; DirectoryEntry = &lt;span style="color:#0000ff;"&gt;New&lt;/span&gt; DirectoryEntry(strRootPath)&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Dim&lt;/span&gt; objADSearcher &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; DirectorySearcher = &lt;span style="color:#0000ff;"&gt;New&lt;/span&gt; DirectorySearcher(objRootEntry)&lt;br /&gt;&lt;br /&gt;objADSearcher.Filter="(&amp;amp;(objectClass=user)(anr=" &amp;amp; strLogin &amp;amp; "))"&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Dim&lt;/span&gt; objResult &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; SearchResult=objADSearcher.FindOne()&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;If&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;Not&lt;/span&gt; objResult &lt;span style="color:#0000ff;"&gt;Is&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Nothing&lt;/span&gt;) &lt;span style="color:#0000ff;"&gt;Then&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;Me&lt;/span&gt;.m_objUserEntry=objResult.GetDirectoryEntry()&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Else&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;Me&lt;/span&gt;.m_objUserEntry=&lt;span style="color:#0000ff;"&gt;Nothing&lt;br /&gt;&lt;br /&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;If&lt;br /&gt;&lt;br /&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Sub&lt;br /&gt;&lt;br /&gt;Public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;ReadOnly&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt; DirectoryEntry() &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; DirectoryEntry &lt;span style="color:#0000ff;"&gt;Implements&lt;/span&gt; IADUser.DirectoryEntry&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Get&lt;br /&gt;&lt;br /&gt;Return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Me&lt;/span&gt;.m_objUserEntry&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Get&lt;br /&gt;&lt;br /&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Property&lt;br /&gt;&lt;br /&gt;Public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;ReadOnly&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Default&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt; Item(&lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; strKey &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;String&lt;/span&gt;) &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; PropertyValueCollection&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Get&lt;br /&gt;&lt;br /&gt;Return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Me&lt;/span&gt;.m_objUserEntry.Properties(strKey)&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Get&lt;br /&gt;&lt;br /&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Property&lt;br /&gt;&lt;br /&gt;Public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;ReadOnly&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt; IsUser() &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Boolean&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Implements&lt;/span&gt; IADUser.IsUser&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Get&lt;br /&gt;&lt;br /&gt;Return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Not&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Me&lt;/span&gt;.m_objUserEntry &lt;span style="color:#0000ff;"&gt;Is&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Nothing&lt;br /&gt;&lt;br /&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Get&lt;br /&gt;&lt;br /&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Property&lt;br /&gt;&lt;br /&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Class&lt;br /&gt;&lt;br /&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Namespace&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Listing 2.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In the Presentation Layer resides an instance of the class ADUserInfoShower whose role is to create an information string for a specific user. This object is independent of the technology used for showing the user information. That is, this string can be rendered in a Web Browser, a Windows Client and a Mobile Device. In the listing 3, it's shown the code for this business object.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Imports&lt;/span&gt; System&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Namespace&lt;/span&gt; OLAActiveDirectory.Management&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Interface&lt;/span&gt; IADUserInfoShower&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Function&lt;/span&gt; GetInformation(&lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; objUser &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; IADUser, &lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; strSep &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;String&lt;/span&gt;) &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;String&lt;br /&gt;&lt;br /&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Interface&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Class&lt;/span&gt; ADUserInfoShower : &lt;span style="color:#0000ff;"&gt;Implements&lt;/span&gt; IADUserInfoShower&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Function&lt;/span&gt; prvInfoBuilder(&lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; objUser &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; IADUser, &lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; strSep &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;String&lt;/span&gt;) &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;String&lt;br /&gt;&lt;br /&gt;Dim&lt;/span&gt; strResult &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;String&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;strResult="Fullname:" &amp;amp; objUser("givenName").Value &amp;amp; " " &amp;amp; objUser("sn").Value&lt;br /&gt;&lt;br /&gt;strResult &amp;amp;= strSep &amp;amp; "Mail:" &amp;amp; objUser("mail").Value&lt;br /&gt;&lt;br /&gt;strResult &amp;amp;= strSep &amp;amp; "Telephone(s):" &amp;amp; objUser("telephoneNumber").Value&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;For&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Each&lt;/span&gt; strPhone &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;String&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;In&lt;/span&gt; objUser("otherTelephone")&lt;br /&gt;&lt;br /&gt;strResult &amp;amp;= strSep &amp;amp; strPhone&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Next&lt;/span&gt; strPhone&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Return&lt;/span&gt; strResult&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Function&lt;br /&gt;&lt;br /&gt;Public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Sub&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;New&lt;/span&gt;()&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Sub&lt;br /&gt;&lt;br /&gt;Public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Function&lt;/span&gt; GetInformation(&lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; objUser &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; IADUser, &lt;span style="color:#0000ff;"&gt;ByVal&lt;/span&gt; strSep &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;String&lt;/span&gt;) &lt;span style="color:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;String&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Implements&lt;/span&gt; IADUserInfoShower.GetInformation&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Me&lt;/span&gt;.prvInfoBuilder(objUser,strSep)&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Function&lt;br /&gt;&lt;br /&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Class&lt;br /&gt;&lt;br /&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Namespace&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#ff6600;"&gt;&lt;span style="font-family:Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="color:#0000ff;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;====================================================================&lt;br /&gt;จากตัวอย่างในเรื่องการ สร้าง Authen กับ Active Directory นั้น ทำการ authen นั้นผ่าน protocal LDAP ได้ ซึ่ง ผมได้ทำตัวอย่างไว้ ทั้งแบบ VB6 และแบบของ .Net เอง สร้างเป็น Class DLL แล้วนำไปใช้ใน Project นะครับ ทีนี้ เราก็จะสามารถ ตัดปัญหายุ่งยากเรื่อง username และ password อันหลากหลายในระบบงานที่พัฒนาขึ้นมาได้แล้วนะครับ ก็จะเป็นการทำ ในเรื่อง single singon นั่นเอง&lt;/p&gt;&lt;br /&gt;&lt;p&gt;============ เริ่มจาก ของ VB6 ก่อนเลยนะครับ ============&lt;br /&gt;สำหรับในตัว VB6 นั้นข้อดีของการสร้าง Active X control จาก vb6 ทำให้เราสามารถ นำ Dll นั้นไปใช้งานกับ Project ที่พัฒนาด้วย เทคโนโลยีตัวเก่า ได้นะครับ เช่นใช้งานกับ vba ของ access หรือ excel หรือใช้งานร่วมกับ ภาษาโปรแกรมตัวอื่นๆ ก็ได้ครับ หรือ จะเอาไปใช้กับเทคโนโลยีของ .net ด้วยก็ยังได้ เพราะ dll ของเทคโนโลยีตัวเก่า สามารถ ใช้งานกับตัวใหม่ได้ แต่ถ้าพัฒนาจาก .net จะไม่สามารถนำไปใช้กับ ระบบงานเก่าๆ ได้ครับ&lt;/p&gt;&lt;br /&gt;&lt;p&gt;ของเริ่มเรื่อง เลยนะครับ&lt;/p&gt;&lt;br /&gt;&lt;p&gt;เริ่มจาก เปิด visual studio 6 ขึ้นมา สร้าง Project Active X Dll นะครับ&lt;br /&gt;จากนั้นให้ เปลี่ยนชื่อ class เป็นชื่ออะไรก็ได้ ในที่นี้ผม ใช้ชื่อ cssLoginAD&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Option Explicit&lt;br /&gt;Const ADS_SECURE_AUTHENTICATION = 1&lt;br /&gt;' method สำหรับการตรวจสอบ Login AD&lt;br /&gt;Public Function ValidateAuthenAD(ByVal UserName As String, _&lt;br /&gt;ByVal Domain As String, _&lt;br /&gt;ByVal Password As String) As Integer&lt;br /&gt;Dim MyNamespace As IADsOpenDSObject&lt;br /&gt;Dim X As IADsContainer&lt;br /&gt;Dim oUserName  As String&lt;br /&gt;Dim oPassword  As String&lt;br /&gt;oUserName = UserName&lt;br /&gt;oPassword = Password&lt;br /&gt;' ตรวจสอบ login AD&lt;br /&gt;On Error GoTo CleanUp&lt;br /&gt;If InStr(1, UserName, ".", vbTextCompare) &amp;lt;&amp;gt; 0 And InStr(1, UserName, "@", vbTextCompare) = 0 Then&lt;br /&gt;oUserName = UserName&lt;br /&gt;End If&lt;br /&gt;' กำหนด Potocal LDAP สำหรับการเข้าไปค้นหา&lt;br /&gt;Set MyNamespace = GetObject("LDAP:")&lt;br /&gt;Set X = MyNamespace.OpenDSObject("LDAP://" + Domain, oUserName, oPassword, ADS_SECURE_AUTHENTICATION)&lt;br /&gt;ValidateAuthenAD = 0&lt;br /&gt;GoTo FinFonction&lt;br /&gt;CleanUp:&lt;br /&gt;Select Case Err.Number&lt;br /&gt;Case -2147023570 ' Return Error หาก password ไม่ถูกต้อง&lt;br /&gt;ValidateAuthenAD = 1&lt;br /&gt;Case -2147016646 ' return Error หาก Domain ไม่ถูกต้อง&lt;br /&gt;ValidateAuthenAD = 2&lt;br /&gt;Case Else ' return Error อื่นๆ&lt;br /&gt;ValidateAuthenAD = 99&lt;br /&gt;End Select&lt;br /&gt;FinFonction:&lt;br /&gt;Set MyNamespace = Nothing&lt;br /&gt;Set X = Nothing&lt;br /&gt;End Function&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt; &lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;strong&gt;หลักการของโปรแกรม&lt;/strong&gt; &lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Class ActiveX cssLoginAD ในเวอร์ชั่นนี้จะประกอบไปด้วย Method ให้เรียกใช้งานได้ดังต่อไปนี้&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;ValidateAuthenAD Method&lt;/strong&gt; เป็นชนิด Integer การทำงานของ method จะเปิด Directory Service ขึ้นมา เพื่อเข้าไปตรวจสอบ user และ pass และ Domain controller โดยผ่าน โปรโตคอล LDap เพื่อ Search หา user และ pass ใน DC ว่ามีอยู่หรือไม่ โดยจะ คืนค่ากลับมา เป็น 0 คือ ตรวจหาพบ หรือ error อื่นๆ ดังนี้&lt;br /&gt;0 = login ถูกต้อง&lt;br /&gt;1 = password ไม่ถูก&lt;br /&gt;2 = ไม่พบ Domain&lt;br /&gt;99 = error อื่นๆ&lt;br /&gt;parameter ที่จะส่งเข้าไปใน method นี้&lt;br /&gt;1. UserName&lt;br /&gt;2. Domain&lt;br /&gt;3. Password&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt; &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;//จากนั้นให้ทำการ Complier dll ออกมาเท่านี้ก็จะสามารถใช้งาน Authen AD ได้แล้วครับ&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;//เมื่อนำ Dll นั้นไปใช้กับ Project &lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;// สร้าง ฟังชั่นขึ้นมาเพื่อตรวจสอบ กับ Class cssLoginAD&lt;br /&gt;Private Function chkLogin(ByVal user As String, ByVal pass As String, ByVal dc As String) As Boolean&lt;br /&gt;Dim result As Boolean&lt;br /&gt;Dim AuthenAD As New cssLoginAD&lt;br /&gt;Dim valReturn As Integer&lt;br /&gt;result = False ' กำหนด ให้ ค่าเริ่มต้นเป็น False&lt;br /&gt;If user &amp;lt;&amp;gt; "" And pass &amp;lt;&amp;gt; "" And dc &amp;lt;&amp;gt; "" Then&lt;br /&gt;valReturn = AuthenAD.ValidateAuthenAD(user, dc, pass)&lt;br /&gt;Select Case valReturn&lt;br /&gt;Case 0 ' กรณี Login ถูกต้อง&lt;br /&gt;result = True&lt;br /&gt;Case 1  ' กรณี password ผิด&lt;br /&gt;MsgBox "กรุณาระบุ password ให้ถูกต้องด้วย !!", vbOKOnly + vbCritical, "Login ผิด !!"&lt;br /&gt;Case 2 ' กรณี ชื่อ Domain ผิด&lt;br /&gt;MsgBox "กรุณาระบุ Domain ให้ถูกต้องด้วย !!", vbOKOnly + vbCritical, "Login ผิด !!"&lt;br /&gt;Case Else ' error อื่นๆ&lt;br /&gt;MsgBox "Error !!"&lt;br /&gt;End Select&lt;br /&gt;Else&lt;br /&gt;' หากกรอกข้อมูลไม่ครับ&lt;br /&gt;MsgBox "กรุณากรอกข้อมูลให้ครบถ้วนด้วย !!", vbOKOnly + vbCritical, "Validate Form!!"&lt;br /&gt;End If&lt;br /&gt;Set AuthenAD = Nothing&lt;br /&gt;chkLogin = result&lt;br /&gt;End Function&lt;br /&gt;‘ ส่วนของ ปุ่ม Submit&lt;br /&gt;Private Sub Command1_Click()&lt;br /&gt;If chkLogin(txtuser.Text, txtpassword.Text, Combo1.Text) Then&lt;br /&gt;MsgBox "Login ถูกต้อง ยินดีต้อนรับคุณ " &amp;amp; txtuser.Text&lt;br /&gt;Call clearText&lt;br /&gt;End If&lt;br /&gt;End Sub&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;จากตัวอย่างด้านบนเป็นการใช้ Active X Dll ที่พัฒนาจาก vb6 สำหรับระบบงาน เก่าๆ หรือใช้งาน กับ vba กับ Access นะครับ&lt;br /&gt;ทีนี้ เรามาดูพระเอกของบทความนี้กันดีกว่า สร้าง Authen Active Directory ด้วย .Net&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;สำหรับใน .Net นั้นนะครับ ได้เตรียม namespace ไว้ให้เราเรียบร้อย จะใช้  System.DirectoryServices&lt;br /&gt;ทีนี้เรามาสร้าง Class สำหรับ authen กับ Acitve directory กันนะครับ&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;อันดับแรก ก็เปิด vs.net แล้ว สร้าง class ขึ้นมานะครับ ดังโคดด้านล่างนี้&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt; Imports System.DirectoryServices  ' impoart namespace สำหรับจัดการ directoryservice&lt;br /&gt;&lt;br /&gt;Namespace LoginAD  ' สร้าง namespace ชื่อ LoginAD เอาไว้จัดกลุ่ม class นะครับ&lt;br /&gt;    Public Class css_AuthenAD&lt;br /&gt;        ' สร้าง private property&lt;br /&gt;        Private strUser As String&lt;br /&gt;        Private strPass As String&lt;br /&gt;        Private strDomain As String&lt;br /&gt;        Private authenType As AuthenticationTypes&lt;br /&gt;&lt;br /&gt;        ' ===============================&lt;br /&gt;' สร้าง Public method&lt;br /&gt;' method สำหรับ Set Domain&lt;br /&gt;Public Function SetDomain(ByVal strValue As String) As Boolean&lt;br /&gt;If strValue.Length &amp;lt;= 0 Then Return False&lt;br /&gt;Me.strDomain = "LDAP://" &amp;amp; strValue&lt;br /&gt;Return True&lt;br /&gt;End Function&lt;br /&gt;&lt;br /&gt;' method สำหรับ Set User&lt;br /&gt;Public Function SetUser(ByVal strValue As String) As Boolean&lt;br /&gt;If strValue.Length &amp;lt;= 0 Then Return False&lt;br /&gt;Me.strUser = strValue&lt;br /&gt;Return True&lt;br /&gt;End Function&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;' method สำหรับ Set password&lt;br /&gt;Public Function SetPass(ByVal strValue As String) As Boolean&lt;br /&gt;If strValue.Length &amp;lt;= 0 Then Return False&lt;br /&gt;Me.strPass = strValue&lt;br /&gt;Return True&lt;br /&gt;End Function&lt;br /&gt;&lt;br /&gt;Public Sub SetAuthenType(Optional ByVal bValue As Boolean = False)&lt;br /&gt;If bValue Then&lt;br /&gt;' type สำหรับ edirectory&lt;br /&gt;authenType = AuthenticationTypes.SecureSocketsLayer&lt;br /&gt;Else&lt;br /&gt;' type สำหรับ Active Directory&lt;br /&gt;authenType = AuthenticationTypes.Secure&lt;br /&gt;End If&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;' และ method login สำหรับเอาไว้ authen นะครับ&lt;br /&gt;Public Function Login() As Boolean&lt;br /&gt;Dim result As Boolean = False&lt;br /&gt;Dim DirEntry As New DirectoryEntry(Me.strDomain, _&lt;br /&gt;Me.strUser, _&lt;br /&gt;Me.strPass, _&lt;br /&gt;Me.authenType)&lt;br /&gt;Try&lt;br /&gt;Dim native As Object = DirEntry.NativeObject()&lt;br /&gt;result = True&lt;br /&gt;Catch ex As Exception&lt;br /&gt;result = False&lt;br /&gt;End Try&lt;br /&gt;Return result&lt;br /&gt;End Function&lt;br /&gt;' ===============================&lt;br /&gt;End Class&lt;br /&gt;End Namespace&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4374571584753215005-5966292237730037990?l=thaieasy2web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thaieasy2web.blogspot.com/feeds/5966292237730037990/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4374571584753215005&amp;postID=5966292237730037990' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4374571584753215005/posts/default/5966292237730037990'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4374571584753215005/posts/default/5966292237730037990'/><link rel='alternate' type='text/html' href='http://thaieasy2web.blogspot.com/2008/08/active-directory-and-vbnet.html' title='Active Directory and VB.NET'/><author><name>asp.net 2.0 and sql server</name><uri>http://www.blogger.com/profile/16372934612226923917</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>
