Wednesday, April 18, 2007

Session Management in ASP.NET

ASP.NET Session State: Architectural and Performance Considerations

I recently came across a great post on one of the internal forums describing the strengths and weaknesses of different ASP.NET session state strategies. Its author, J.D. Meier, has graciously given me permission to use it as the basis of a blog entry.

As you're probably aware, state management is an important consideration for web developers. The HTTP protocol is connectionless, so any web application that persists data across multiple web page requests needs some mechanism to ensure this session-based data is maintained. Examples of session-based data include shopping carts (on an ecommerce site), the currently logged-on user credentials, and other application-specific data that would normally be held on a client. Various strategies have been utilised over the last few years, including hidden forms, cookies and server-based state engines. Of these choices, the latter is perhaps architecturally most attractive since it reduces the dependence on a client; unfortunately, maintaining session state on the server can be expensive on resources and makes it hard to scale out using web farms or secure pages with HTTPS.

Enter the ASP.NET session state engine, which attempts to make server-side session state a much more viable option. ASP.NET offers three separate choices for session state storage when it's switched on: locally on the server (InProc), remotely in a SQL Server database (SqlServer), or remotely using a session state service (StateServer). I'll go through each of those options and compare the benefits of each.

InProc

The local option is not dissimilar to that provided by ASP, in that it requires all requests to come to the same physical server rather than being randomly split across multiple IIS machines. The upside is that it's very fast (it runs in-process), and it's simple to implement. If you've just got one web server, this is the best choice in most scenarios. The only time when you might want to consider something else in this scenario is when the session data is expensive to rebuild, since any InProc session data is flushed when the ASP.NET worker process or IIS restarts. If, for example, you're maintaining a shopping cart as local session data that gets cleared out, you risk annoying customers sufficiently that they take their business elsewhere.

For multiple servers, InProc is unsuitable unless you can implement some form of server affinity, so that every time a particular client requests a web page they are directed back to that same server. Services such as Network Load Balancing (part of Windows Server 2003 Enterprise Edition) can provide this, although they inevitably add their own overhead.

StateServer

I've come across a few developers who haven't come across this choice. The state server relies on a Windows service which is disabled by default, which perhaps explains why people haven't noticed it - go to Administrative Tools / Services and enable the ASP.NET State Service to get it working. You can run the state service on a dedicated machine or shared with a web server host; the main requirement to make this service work efficiently is plenty of RAM. Because the service is isolated from IIS, you can restart IIS without losing the session data contained within it, and you can point multiple distributed ASP.NET boxes at the same service, thereby removing server affinity issues. However, the session data isn't persisted onto disk, so it can't be backed up and a server reboot will lose the data. On the plus side, you don't need SQL Server or anything beyond a Windows licence to run it, making this option easy to set up and maintain. This option is however signficantly slower than using InProc, due to network latency and roundtrip costs. Keeping the state server on a dedicated private LAN with the other web server boxes will help.

Finally, don't forget that you can run the ASP.NET State Service in a single web server environment - this provides durability against IIS restarts, but at a performance cost due to it running out of process.

SqlServer

This is the high-end option in terms of flexibility and reliability, but is also the most expensive to build and maintain. Rather than storing session data in memory, it is persisted to a SQL Server instance. It's more reliable than any of the other approaches, since the data is persisted in a more durable form (e.g. it will survive a server restart and can be backed up). You can even use SQL Server clustering support to increase session state reliability still further. From a performance point of view, it's generally comparable to the StateServer service when you've got multiple web servers using it for session state. The session state itself is stored as a BLOB in a persisted or temporary table, which can reduce the serialization cost but makes it harder to view the session data itself.

In most cases, integrated Windows authentication is the best choice, preferably utilising Kerberos (NTLM requires an extra roundtrip for authentication). Connection pooling can be used to minimise the initial performance hit.

Happy Programming !!

Difference between user defined function and stored procedure

Advantages of User Defined Functions

Before SQL 2000, User Defined Functions (UDFs), were not available. Stored Procedures were often used in their place. When advantages or disadvantages of User Defined Functions are discussed, the comparison is usually to Stored Procedures.

One of the advantages of User Defined Functions over Stored Procedures, is the fact that a UDF can be used in a Select, Where, or Case statement. They also can be used to create joins. In addition, User Defined Functions are simpler to invoke than Stored Procedures from inside another SQL statement.

Disadvantages of User Defined Functions

User Defined Functions cannot be used to modify base table information. The DML statements INSERT, UPDATE, and DELETE cannot be used on base tables. Another disadvantage is that SQL functions that return non-deterministic values are not allowed to be called from inside User Defined Functions. GETDATE is an example of a non-deterministic function. Every time the function is called, a different value is returned. Therefore, GETDATE cannot be called from inside a UDF you create.

Types of User Defined Functions

There are three different types of User Defined Functions. Each type refers to the data being returned by the function. Scalar functions return a single value. In Line Table functions return a single table variable that was created by a select statement. The final UDF is a Multi-statement Table Function. This function returns a table variable whose structure was created by hand, similar to a Create Table statement. It is useful when complex data manipulation inside the function is required.

Scalar UDFs

Our first User Defined Function will accept a date time, and return only the date portion. Scalar functions return a value. From inside Query Analyzer, enter:

 

CREATE FUNCTION dbo.DateOnly(@InDateTime datetime)
RETURNS varchar(10)
AS
BEGIN
        DECLARE @MyOutput varchar(10)
        SET @MyOutput = CONVERT(varchar(10),@InDateTime,101)
        RETURN @MyOutput
END

To call our function, execute: SELECT dbo.DateOnly(GETDATE())

Notice the User Defined Function must be prefaced with the owner name, DBO in this case. In addition, GETDATE can be used as the input parameter, but could not be used inside the function itself. Other built in SQL functions that cannot be used inside a User Defined Function include: RAND, NEWID, @@CONNCECTIONS, @@TIMETICKS, and @@PACK_SENT. Any built in function that is non-deterministic.

The statement begins by supplying a function name and input parameter list. In this case, a date time value will be passed in. The next line defines the type of data the UDF will return. Between the BEGIN and END block is the statement code. Declaring the output variable was for clarity only. This function should be shortened to:

 

CREATE FUNCTION testDateOnly(@InDateTime datetime)
RETURNS varchar(10)
AS
BEGIN
        RETURN CONVERT(varchar(10),@InDateTime,101)   
END

Inline Table UDFs

These User Defined Functions return a table variable that was created by a single select statement. Almost like a simply constructed non-updatable view, but having the benefit of accepting input parameters.

This next function looks all the employees in the pubs database that start with a letter that is passed in as a parameter. In Query Analyzer, enter and run:

 

USE pubs
GO
 
CREATE FUNCTION dbo.LookByFName(@FirstLetter char(1))
RETURNS TABLE
AS
RETURN SELECT *
FROM employee
WHERE LEFT(fname, 1) =  @FirstLetter

To use the new function, enter:

SELECT * FROM dbo.LookByFName('A')

All the rows having a first name starting with A were returned. The return is a Table Variable, not to be confused with a temporary table. Table variables are new in SQL 2000. They are a special data type whose scope is limited to the process that declared it. Table variables are stated to have performance benefits over temporary tables. None of my personal testing has found this result though.

Multi Statement UDFs

Multi Statement User Defined Functions are very similar to Stored Procedures. They both allow complex logic to take place inside the function. There are a number of restrictions unique to functions though. The Multi Statement UDF will always return a table variable--and only one table variable. There is no way to return multiple result sets. In addition, a User Defined Function cannot call a Stored Procedure from inside itself. They also cannot execute dynamic SQL. Remember also, that UDFs cannot use non-deterministic built in functions. So GETDATE and RAND cannot be used. Error handling is restricted. RAISERROR and @@ERROR are invalid from inside User Defined Functions. Like other programming languages, the purpose of a User Defined Function is to create a stand-alone code module to be reused over and over by the global application.

For a Multi Statement test, we will create a modified version of the LookByFName function. This new function will accept the same input parameter. But rather than return a table from a simple select, a specific table will be created, and data in it will be manipulated prior to the return:

CREATE FUNCTION dbo.multi_test(@FirstLetter char(1))
RETURNS @Result TABLE
        (
        fname varchar(20),
        hire_date datetime,
        on_probation char(1)
        )
AS
BEGIN
        INSERT INTO @Result
               (fname, hire_date)
               SELECT fname, hire_date
               FROM employee
               WHERE LEFT(fname, 1) =  @FirstLetter
        
        UPDATE @Result
        SET on_probation = 'N'
        
        UPDATE @Result
        SET on_probation = 'Y'
        WHERE hire_date < '01/01/1991'
        
        RETURN
END

To use the new function, execute:

SELECT * FROM dbo.multi_test('A')

With the new Multi Statement Function, we can manipulate data like a Stored Procedure, but use it in statement areas like a View.

For example, only specific columns can be returned.

SELECT fname FROM dbo.multi_test('A')

The function can also be joined like a view:

SELECT e.lname, f.fname
FROM employee e INNER JOIN dbo.multi_test('A') f ON e.fname = f.fname
 

Conclusion

User Defined Functions offer an excellent way to work with code snippets. The main requirement is that the function be self-contained. Not being able to use non-deterministic built in functions is a problem, but if it can be worked around, UDFs will provide you with a programming plus.

 

Happy Programming !!

 

Tuesday, April 17, 2007

Javascript function to check valid decimal value with specified digits after decimal point

    Below is the function that validates only positive decimal numbers in text box. You can specify number of digits that can be allow after decimal point.

 

var DigitsAfterDecimal = 8;
function
CheckUnit()
{

if(document.getElementById
("TextBoxName").value == '' )
{
alert("Please enter valid decimal
value");

return false;
}
else
{

if(isNaN(document.getElementById
("TextBoxName").value))
{
alert("Please enter valid decimal
value")
;


return false;
}
else
{
var val = document.getElementById
("TextBoxName").value;
if(val.indexOf(".") > -1)
{

if(val.length - (val.indexOf
(".")+1) >
DigitsAfterDecimal)
{
alert("Please enter valid
decimal value. Only " +
DigitsAfterDecimal + "
digits are allowed after
decimal.")
;



return false;
}
else
{
return true;
}
}
else
{
if(parseInt(val) > 0)
{
return true;
}
else
{
alert("Value must be
greater than 0"
);

return false;
}
}
}
}
}
Happy Programming !!

Sunday, April 08, 2007

Transferring sessions from asp to aspx

          In my starting days with dotnet before 2 years, all vendors were converting from ASP to ASP.NET. They still wanted some of the pages in ASP. The real problem is to transfer session from asp page to aspx page.  The easiest way I found was shown below.

         Lest say that you have a page Old.asp and a page New.aspx . You need to transfer the session from Old to New. The idea is create an intermediate forms(pages)  that can help you in transferring the sessions.  First Create Step1.asp page and redirect to this page from "Old.asp" page . This page will creates a form with hidden fields which stores the value of all session variables as shown below,

<html>
<
head>
<
meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<
title>Step 1</title>
</
head>
<
body>
<%
Response.Write("<form name=t id=t action=Step2.aspx method=post >")
For each Item in Session.Contents
Response.Write("<input type=hidden name=" & Item)
Response.Write( " value=" & Session.Contents(item) & " >")
next
Response.Write("</FORM>")
Response.Write("<script>t.submit();</script>")
%>
</
body>
</
html>

Fig - (1) First Step to transfer the session from asp to aspx.


       The page shown in Fig - (1) creates the form will create new form which has action attribute set to "Step2.aspx" page. This page will loop through all the session variables and generates hidden field for each. After that, java script submit the page to aspx page. Now look at the "Step2.aspx" page.

public class WebForm1 : System.Web.UI.Page
{
private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here
for(int i=0;i<Request.Form.Count;i++)
{
Session[Request.Form.GetKey(i)]=Request.Form[i].ToString();
}
// Destination aspx page to which you need to transfer sessions
Server.Transfer(Session["DestPage"].ToString(),true);

}
}

Fig - (2)  Step2 to transfer session from asp to aspx.


        This page will loop through all the fields of posted form using "Request.Form" and add the values in session. The last line transfer this aspx page to destination aspx page which is "New.aspx".


Happy Programming !

Friday, April 06, 2007

Validation of viewstate MAC failed.

            I was trying to post my aspx page to new page using JavaScript. The common methods "document.form1.submit()". I have specified action and method attribute also. Still I was getting error on form submit as shown below,

"Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that <machineKey> configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster."

         Below is the code I was using for form submission.

document.form1.action="New.aspx"
document.form1.submit();

Fig - (1) Javascript to submit the form.

      I had written above script on submit button. After searching I found the reason for that. In ASP.NET, there is a specific method "__dopostback()" which allows user to submit the form to server(postback). Each time form is submitted with "post" method, CLR checks for valid viewstate so that there can not be any type of injection.

        To solve this problem you have set "name" attribute of viewstate before submitting. The code is shown below.

ocument.form1.action="New.aspx";
document.form1.__VIEWSTATE.name="name";
document.form1.submit();

Fig - (2) Javascript to submit the form without error.

Happy Programming !

Tuesday, April 03, 2007

Single Sign on between Form Authentication Applications

    In my recent interview, I faced an interesting question. "Can we use single sign on for diffrent Form Authentication Sites?". Obviously my answer was "No Idea". After that I search on net for this and found that, yes !! we can do that. Below is the way to achieve this.

 

SSO for parent and child application in the virtual sub-directory
Lets assume that we have two .NET applications - Foo and Bar, and Bar is running in a virtual sub-directory of Foo (http://foo.com/bar). Both applications implement Forms authentication. Implementation of Forms authentication requires you to override the Application_AuthenticateRequest, where you perform the authentication and upon successful authentication, call FormsAuthentication.RedirectFromLoginPage, passing in the logged-in user name (or any other piece of information that identifies the user in the system) as a parameter. In ASP.NET the logged-in user status is persisted by storing the cookie on the client computer. When you call RedirectFromLoginPage, a cookie is created which contains an encrypted FormsAuthenticationTicket with the name of the logged-in user . There is a section in web.config that defines how the cookie is created:

<authentication mode="Forms">
   <forms name=".FooAuth" protection="All" timeout="60" loginUrl="login.aspx" />
</authentication>

 <authentication mode="Forms">
   <forms name=".BarAuth" protection="All" timeout="60" loginUrl="login.aspx" />
</authentication>

The important attributes here are name and protection. If you make them match for both Foo and Bar applications, they will both write and read the same cookie using the same protection level, effectively providing SSO:

<authentication mode="Forms">
   <forms name=".SSOAuth" protection="All" timeout="60" loginUrl="login.aspx" />
</authentication>

When protection attribute is set to "All", both encryption and validation (via hash) is applied to the cookie. The default validation and encryption keys are stored in the machine.config file and can be overridden in the application’s web.config file. The default value is this:

<machineKey validationKey="AutoGenerate,IsolateApps" decryptionKey=" AutoGenerate,IsolateApps" validation="SHA1" />

IsolateApps means that a different key will be generated for every application. We can’t have that. In order for the cookie to be encrypted and decrypted with the same key in all applications either remove the IsolateApps option or better yet, add the same concrete key to the web.config of all applications using SSO:

<machineKey validationKey="F9D1A2D3E1D3E2F7B3D9F90FF3965ABDAC304902" decryptionKey="F9D1A2D3E1D3E2F7B3D9F90FF3965ABDAC304902F8D923AC" validation="SHA1" />

      I found one good artile on this here

Happy Programming !!

Monday, March 26, 2007

Add to Favorite in Firefox and IE

      I was looking for the javascript to add the link in favorite. I have tried window.external.AddFavorite(location.href, document.title) which is working only in IE. I need to do that for firefox also. After spending few mnutes on google, I found the code working in both.

<script type="text/javascript">
function bookmarksite()
{
         if (document.all)
        {
             // For IE
             window.external.AddFavorite(location.href, document.title);
         }
        else if (window.sidebar)
       {
             // For Firefox
             window.sidebar.addPanel(document.title, location.href, "");
        }
}
< /script>

< a href="javascript:bookmarksite();"> Add to favorites< /a>

Happy Programming !!

Saturday, March 24, 2007

Default button in ASP.NET

           I was creating a search page and I require that when user press enter key, by default search button's click event should be fire. I look around for the solution and find the easiest one. You just need to write below line in page load of  your code behind file.

Form.DefaultButton = btnSubmit.UniqueID;

           Here btnSubmit is the name of button.

Happy Programming!!!!

Monday, March 19, 2007

Nullable datatypes in C#

       In C# 2.0 there is a special datatypes called Nullable datatypes. You can assign null to them. Here is some basic information regarding Nullable data types.

        You can make any value types to nullable data types by writing as shown below.

public int? intA = null;

Fig - (1) Declaring integer data types so it can have null as value.

        Fig (1) shows how to declare data types do that it can have null as value. Now to check that if intA has non null value or it is null, you can use HasValue property.        

// Check HasValue method
if (intA.HasValue)
{
          Console.WriteLine("intA is not null");
}
else
{
          Console.WriteLine("intA is null.");
}

Fig - (2) Check that nullable type has non null value.

         As desribe above HasValue property returnd true if nullable types has non null value else returns false. To access the value of nullable types, "value" property is used as shown here, intA.Value. You can use nullable types in arithematic operation in same manner you are using integer (or any) types. If you are using them in Summation and if any of nullable type has value null than you will get null as result regardless of other variables value.

        Operator ?? is used check nullable value against null as shown below,

// Check ?? operator
int d = intA ?? -1;

Fig - (3) Check against null using ??.

       If  intA is null than d = -1, else d = value of intA which is intA.Value. So for default assignment you can use ?? instead of checking by HasValue property.

      I looked in to the IL for nullable data types and simple data types and here is what i found.

.field public int32 intB

Fig - (4) IL generated for simple integer.

.field public valuetype [mscorlib]System.Nullable`1<int32> intA

Fig - (5) IL generated for nullable integer.

      You can see in IL that "Nullable`1" attributes is added so that CLR can identify the nullable datatypes.

     I further look in to the Boxing of Nullable types.

int? i = 44;
// Boxing
object iBoxed = i; // iBoxed contains a boxed int.
// UnBoxing
int? i2 = (int?)iBoxed;

Fig - (6) Boxing and UnBoxing for Nullable types.

           One interested thing here is, Objects based on nullable types are only boxed if the object is non-null. If HasValue is false, then, instead of boxing, the object reference is simply assigned to null. The boxed object for nullable types and non nullable types are exactly same.

Happy Programming!

Friday, March 16, 2007

Remove/Delete element from page using JavaScript working in FireFox,IE,Opera

        Few days ago, I was recalling my Java script skill. I was generating Grid using java script script. Instead of using Display property ('none' or 'block') to show or hide the control, I was creating and removing element each time. Creating element is not a big deal. However the script for removing element is different in IE and Firefox.

       In IE, we can remove the element using, however this will not work in Firefox.

document.getElementById("ControlID").removeNode(true);

Fig -(1) Script to remove element in IE.

      In Firefox, you have to use,

var Node1 = document.getElementById("ParentControlID");
Node1.removeChild(Node1.childNodes[0]);

Fig -(2) Script to remove element in Firefox.

  Below is the sample code for the same.

      var Node1 = document.getElementById("Parent"); 
      var len = Node1.childNodes.length;
      
       for(var i = 0; i < len; i++)
       {           
            if(Node1.childNodes[i].id == "Child")
            {
                Node1.removeChild(Node1.childNodes[i]);
            }
       }

Fig -(3) Script to remove child element in Firefox.

Happy Programming !

Thursday, March 15, 2007

Create Serial Number Column using SQL Server

       There is a common requirement to show records with serial number in Grid.  The common scenario is, we take template field and label in Item Template. In Row_DataBound we can generate serial number using variable which is increamnted each time. The another approach is to genarate this column in SQL itself. Yes you can do that..! Here is a Query for that.

SELECT ROW_NUMBER()  OVER (ORDER BY  ColumnName1) As SrNo, ColumnName1,  ColumnName2 FROM  TableName

Fig- (1) Query to display Serial Number Column using SQL Server 

Happy Programming !

Sunday, March 11, 2007

Call parent window's javascript function from child window OR passing data from child window to parent window in javascript

                Hi, I was working on small application and I had a requirement as described here. I was creating a page in wjich user can add multiple cotact detail for him. The page has facility for add, delete and edit the contact. I was storing all these information in view state and finally on Save All button adding them to database. Afte the page is completed client has requested that user can have option to select contacts from database also. So I have to open a popup from which user can select multiple contacts and once user click on "Select" button on popup all the selected contacts should be available in grid on main page along with the contacts user has added manually.

               To achieve this I need have added hidden field on parent page and on child page I access that hidden field to set the IDs of selected contacts. Once the selected IDs are available on parent window, I need to postback the page so that I can take all the data for those IDs from database and add it to grid for edit or save.

              I was knowing that I can set "locationhref"  of parent window in child window and then close child window. However this will redirecr the parent page to new location (here new location is same page) but we loose viewstate data. This solution does not work in my case.

             One of my friend (we call him SP (Sehul the PRO) ) suggested me two ways to solve my problem. First, I can call "Click" event of parent window's button in child window so that parent window will post back and the code behind I had written for that button's click had;ler will be executed. Yes this is possible !!   Second, I can call javascript function written on parent window from child window. This function use ajax and execute server side code once I get selected contact IDs in hidden field.  

               Lets implement First logic. Below is the javascript to raise button click event on parent window from child window.

// Set parent window's hidden field value from child window
window.opener.document.getElementById(Client ID of Hidden Field).value = Selected IDs;

// raise button click event of parent window
window.opener.document.getElementById(Client ID Of Button).click();

// Close the child window
close();

Fig - (1) Javascript on child window to raise button click event on parent window

           I had written this script on child page. Tis will raise button click event and in post back I wrote the logic of retrieving data from database for IDs set in hidden field and displayed them in grid.

          Now the second way, call javascript function of parent window from child window.

<script language="Javascript" type="text/javascript">
function CallAlert()
{
alert("This is parent window's alert function.");
}
</script>

Fig - (2) Javascript on parent window.

<script language="Javascript" type="text/javascript">

function SetParentWindowsHiddenFieldValue()
{
window.opener.document.getElementById("HiddenField1").value = document.getElementById("TextBox1").value;
return false;
}

function CallParentWindowFunction()
{
window.opener.CallAlert();
return false;
}
</script>

Fig - (3) Javascript on child window.


          Take two buttons on child window. C all "SetParentWindowsHiddenFieldValue" on click of one button and call "CallParentWindowFunction" on click of second button and see the result.


Happy Programming.

Tuesday, March 06, 2007

Storing and Retrieving Image in SQL Server

           Hi, I saw many developers are asking this questions in different forums. Recently I saw this question on MSDN forum and I thought let me write a blog on this. I know many of us found this too easy however for new bees its bit hard.

            In this article, I had used SQL Server 2005 as back end and C# as front end. SQL Server has "Image" data type to store the image. In Oracle and some other database you can use a data type which is used to store binary value (may be BLOB). I have created a simple aspx which has File upload control and a button. When user selects a file to upload, I am checking it for valid image type and converting it to array of Bytes. Then I will store that byte array into database. Below is the code,

 

if (objFileUpload.PostedFile !=null)
{
          if (objFileUpload.PostedFile.ContentLength > 0)
         {
                  // Get Posted File.
                  HttpPostedFile objHttpPostedFile = objFileUpload.PostedFile;

                  // Check valid Image type. Create this function according to your need
                  if (CheckValidFileType(objHttpPostedFile.FileName))
                 {
                        // Find its length and convert it to byte array
                      
 int intContentlength = objHttpPostedFile.ContentLength;

                       // Create Byte Array 
                        Byte[] bytImage =new Byte[intContentlength];
                           
                        // Read Uploaded file in Byte Array
                        objHttpPostedFile.InputStream.Read(bytImage, 0, 
                                                                                    intContentlength);
                                      
                   }
              }
        }

Fig -  (1)  Read Uploaded file (here Image) in Byte Array

 

       Pass this Byte array to you DAL and use it for storing image in database. I am using Enterprise Library as DAL so my code will look like,

 

Database db =DatabaseFactory.CreateDatabase();

string sqlCommand ="StoredProcedureName";

DbCommand dbCommandWrapper = db.GetStoredProcCommand(sqlCommand);

db.AddInParameter(dbCommandWrapper,"@Image",DbType.Binary,
bytImage );

try
{
             db.ExecuteNonQuery(dbCommandWrapper);
}
catch {throw; }

Fig -  (2)  Insert Image in to database

 

      This is how you can store the Image in database. Retrieving the image is the same process. Write a SP which will return your image. Store this value in a Byte Array. Once you get the image in Byte array, you just have to write it on form as shown below,

 

Byte[] bytImage =Byte array retrieved from database.
if (bytImage !=null)
{
          Response.ContentType ="image/jpeg";
          Response.Expires = 0; Response.Buffer =true;
          Response.Clear();
          Response.BinaryWrite(bytImage); 
          Response.End();
}

Fig -  (3)  Code to display Byte array as Image on form.

     

        To use this at multiple places in your application, you create a page to which you can pass ID of Image and it will retrieve image from database and create image. To do this copy paste above code in aspx.cs file. Now on every page you require to show this image  take <asp:Image> on that page and set its ImageURL property to the path of newly created user control. See the code below,

<asp:Image ID="ViewImage" runat="server" />

Fig -  (4) Image control on any aspx page (Lets say Sample.aspx).

string strURL ="~/ViewImage.aspx?ID= 1 " ;
ViewImage.ImageUrl = strURL;

Fig -  (5)  Set Image URL for image control on code behind (Sample.aspx.cs)

 

       You can see the image will be displayed in your page where you had put Image tag.

Happy Programing.

 

Thursday, March 01, 2007

Impersonation using Code

      I was reading about impersonation and delegation. The most common way I found for impersonation is to write  a tag "<impersonate = "true" username="Name" password ="password" />"  in web.config file.  This will impersoname specific user to each request. I want to impersonate network user for only one request.

     In my project I have to create a directory which is shared on network and has rights set to network user. If I use impersonation in web.config file, all the request of my application executes under the rights of that network user ehich can be a security threat. I need to impersonate the user for a single request in which I need to create a directory on network shared location.

     Below is the code that impersonate the "Anonymous" (is explained in paragraph below code" user for perticular request.

 

HttpContext context = HttpContext.Current;   
// Get the service provider from the context           
 IServiceProvider iServiceProvider = context as IServiceProvider;
//Get a Type which represents an HttpContext           
Type httpWorkerRequestType = typeof(HttpWorkerRequest);
 // Get the HttpWorkerRequest service from the service provider           
// NOTE: When trying to get a HttpWorkerRequest type from the HttpContext           
// unmanaged code permission is demanded.           
HttpWorkerRequest httpWorkerRequest =
            iServiceProvider.GetService(httpWorkerRequestType) as HttpWorkerRequest;
 // Get the token passed by IIS           
IntPtr ptrUserToken = httpWorkerRequest.GetUserToken();
// Create a WindowsIdentity from the token           
WindowsIdentity winIdentity = new WindowsIdentity(ptrUserToken);           
Response.Write("Before impersonation: " + WindowsIdentity.GetCurrent().Name + "<br>");
// Impersonate the user           
WindowsImpersonationContext impContext = winIdentity.Impersonate();
Response.Write("Impersonating: " + WindowsIdentity.GetCurrent().Name + "<br>");
// Place resource access code here     
// Stop impersonating           
impContext.Undo();
Response.Write("After Impersonating: " + WindowsIdentity.GetCurrent().Name + "<br>");

Fig - (1) Impersonate user using code.

     By saying  "Anonymous" user,  the user which is set for Anonymous account in IIS. By default this will be "IUser_MachineName".  Change this to Network user (or user you want to impersonate) by entering username and password and uncheck "Allow IIS to control password" check box.

   To do this click on "Start --> Run " and write " inetmgr". It will show IIS. Right click on virtual directory of your application and select property. Click on "Directory Security" tab. Click "Edit" button at "Anonymous Access and Authentication Cotrol" panel. Here you can change user name and password.

Happy programming.

Wednesday, February 28, 2007

Remove extra space from Validation Summary

       Hi, You all have observe that when we use validation summary,  it takes some extra space between header text and error messages.

      You can remove extra space by using style sheet. Below is the code.

<style type="text/css">
    UL
   {
          margin: 0 ;
          padding:5px;
   }
</style>

Fig - (1) CSS to remove extra space.

Happy Programming.

Monday, February 26, 2007

Google Map API control for ASP.NET

              I have to work with google map in my current project. I search on net for the documentation of the API. Google has given really good exaples how to use that. However, everything is done using javascript. I was searching for the control that allow me to do all this at code behind. I found really good control at

             http://be.sys-con.com/read/171162_1.htm

          I have modified it according to my requirement.  If you have any question you can ask me.

Happy Programming.

Thursday, February 22, 2007

Use XML as input parameter to SP

         Few days ago, in my blog(http://chiragrdarji.wordpress.com/2007/02/19/split-function-in-sql/)  I mentioned how to pass and use multiple values in single parameter in SP. I have mentioned that you can use XML format to do the same. Let me show you how to do that.

         Cionsider that you have to delete 5 rows from table and you have value of primary key for those 5 records. You have to prepare the XML document for these 5 IDs and pass it as a parameter to SP. Below is the functiion that generates XML.

       I have passed 5 IDs as coma seperated string in "Value", and NodeName as parameters. I will Explain NodeName later.

public static string GetOpenXMLFormat(string Value,string NodeName)
{
            string strReturnVAlue = string.Empty; 
            // Create Root node.
             strReturnVAlue = "<Root>"

            if (Value.Length > 0)
            {
                  string[] strTemp = Value.Split(new string[] {","}, 
                                                          StringSplitOptions.RemoveEmptyEntries);

                  for (int i = 0; i < strTemp.Length; i++)
                 {
                       strReturnVAlue += "<" + NodeName + "IDS " + NodeName + "ID ='"
                                                                + strTemp[i] + "'/>"

                  }
             }
            strReturnVAlue += "</Root>"
            return strReturnVAlue;
}

Fig - (1) C# code generate XML document.

 

           Lets call above function GetOpenXMLFormat("1,2,3,4,5" , "Emp"). This will generate XML file as shown below.

<Root>
         <EmpIDS EmpID = 1/>
         <EmpIDS EmpID = 2/>
         <EmpIDS EmpID = 3/>
         <EmpIDS EmpID = 4/>
         <EmpIDS EmpID = 5/>
</Root>

Fig - (2) Generated XML strig.

      Consider that we pass this parameter "@EmpIDS" to any SP. Below is the code that shows how to read this parameter in SP.

 

DELARE @EmpID int

DECLARE @docHandle int

EXEC sp_xml_preparedocument @docHandle OUTPUT, "@EmpIDS

SELECT * Into #TempEntities FROM
OPENXML(@docHandle, N'/Root/IDS',1) WITH (EmpID int)

DECLARE TempCursor CURSOR FOR

SELECT SubGroupID, TrainingModuleID FROM #TempEntities

OPEN TempCursor

/* For each row in cursor*/
FETCH NEXT FROM TempCursor INTO @EmpID

/* Loop through cursor for remaining GroupID */
WHILE @@FETCH_STATUS = 0
BEGIN

      // Wirte a code to do desire operation

END

 

Fig - (3) Ream XML string parameter in SP.

         You can pass more than one attribute in XML parameter and read it. Below is the sample for 2 values 

OPENXML(@docHandle, N'/Root/IDS',1) WITH (SubGroupID int '@SubGroupID', TrainingModuleID int '@TrainingModuleID')

Fig - (3)  Read values of 2 parameters

Happy programing.

Monday, February 19, 2007

Split function in SQL

          I was working at home and extending a gridview control with some extra features I required. I have added one column with checkbox for multiple delete. To delete multiple records I need to pass either multiple ID to SP and delete all or can pass each ID one by one to SP.

        I passed all ID as coma separated string to SP.  I used split function to split the coma separated ID, so that I can use those ID in inner query. For example

DELETE FROM TableName WHERE ID IN (SELECT dbo.fun_Split(@AllID, ',' ))

Here you have to pass string value and separator as a parameter. In my case, I have used "," as seperator. Below is the function,

 

Create function fun_Split (@String nvarchar(4000), @Delimiter char(1))
Returns @Results Table (Items nvarchar(4000))
As

Begin
         Declare @Index int
         Declare @Slice nvarchar(4000)
         Select @Index = 1
        If @String Is NULL
                 Return
        While @Index != 0
        Begin
               Select @Index = CharIndex(@Delimiter, @String)
               If (@Index != 0)
                      Select @Slice = left(@String, @Index - 1)
               else
                     Select @Slice = @String

               Insert into @Results(Items) Values (@Slice)
               Select @String = right(@String, Len(@String) - @Index)
               If Len(@String) = 0
                     break
       End
       Return
End

Fig -(1) Split function SQL.

             There is another way to do the same. You can use open XML format to pass more than one parameters to SP. I will explain that in my next blog.

Happy Programing.

Friday, February 16, 2007

Dotnet 3.0 Training Material

        I was serching for good material to learn cotnet 3.0. I found the good link which allows to download PPT file. Below is the link,

        http://www.dotnet-university.com/

Using publisher policy assemblies

            As we all knows .NET support side by side execution of multiple versions of component. In most cases, updating a component is simple.However, even in the .NET world, it is possible to break assembly binding when you update a component.  One achieve that control is the publisher policy assembly.

What is a publisher policy assembly?

                 A publisher policy assembly is an assembly that configures the policy to be used when the .NET runtime binds to an assembly. The publisher policy assembly is installed into the GAC and is named using the following naming convention:

                policy.major_ver.minor_ver.assembly.dll

                    The major_ver and minor_ver refer to the major and minor version of the old version of the assembly. Therefore, if you are updating version 1.0 of Website.dll to version 2.0, and you want all existing applications to bind to the new version, the publisher policy assembly name would be:

                 policy.1.0.website.dll

After this publisher policy assembly is installed into the GAC, any application that references version 1.0 of Website.dll will bind to version 2.0 of Website.dll instead. At this point, you might be asking how the .NET runtime knows to bind to version 2.0 of Website.dll when it sees the publisher policy assembly in the GAC. The answer lies in the publisher policy file, an XML configuration file that is used to create the publisher policy assembly.

                       The publisher policy file contains the information necessary to redirect the binding from one version of an assembly to a new version. After you've created the publisher policy file, you use the .NET Assembly Linker utility (Al.exe) to create the publisher policy assembly.


                        Here is an example of a publisher policy file that redirects any reference to version 1.0 of Website.dll to version 2.0. The public key token can be obtained by looking at the properties of the assembly currently installed in the GAC.

<configuration>
<runtime>
 <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">      <dependentAssembly>
<assemblyIdentity name="website" publicKeyToken="18517ea673f8584b" culture="neutral" />
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/> </dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

 

The entire process

Scenario: You want to ensure that any ASP.NET application currently referencing version 1.0 of your server control uses version 2.0 instead after the updated version is installed. You don't want anyone to have to modify configuration files for this to happen. You have wisely determined that a publisher policy assembly is the way to go.
This is how you should proceed.

1. Change the version and recompile.    The first step is to create the new version of your component. After you've done that, you will need to modify the version number in the AssemblyInfo file for your component.

2.Create the publisher policy file.Create the publisher policy file for the assembly using the format shown above.

3.Use Assembly Linker (Al.exe) to create the publisher policy assembly. The Assembly Linker is included with the .NET Framework SDK. To create the publisher policy assembly that redirects a binding from version 1.0 of Website.dll to version 2.0 using a publisher policy file called website.config, run the following command:

al /link:website.config /out:policy.1.0.website.dll /keyfile:c:\keyfile.snk

This command will create a new assembly called policy.1.0.website.dll. This naming convention is important, as indicated in the "What Is a Publisher Policy Assembly?" section.

4.Install the publisher policy assembly into the Global Assembly Cache. The publisher policy assembly is installed into the GAC. It will be used by the .NET runtime when any application attempts to bind to version 1.0 of the Website.dll, and it will force the application to bind to the new version automatically.

5.Install the new version into the Global Assembly Cache. Install the new version of the component into the GAC. After the new version has been installed, the old version can be safely removed.

6.Restart Microsoft Internet Information Services (IIS). The final step is to restart IIS. This is necessary because of the way the .NET runtime binds to an assembly. If the .NET runtime has already bound to a specific assembly, it will reuse that binding. Therefore, for the binding redirect to the new assembly to work, you must restart the worker process.

                  After completing these steps, any application that was built with a reference to version 1.0 of Website.dll will automatically use version 2.0. Publisher policy assemblies offer a convenient way to ensure that developers have full control over assembly binding. As you've seen in this article, if your goal is to force existing applications to use a new version of your component, a publisher policy assembly provides you with the confidence that applications will always use the version you expect them to use without having to alter any configuration files or rely on manual changes by a server administrator.

 

You can find detail information at,

http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B891030

Happy Programming.

Thursday, February 15, 2007

Swap values of three variables without using fourth variable

       In my recent interview, a well known company in ahmedabad having branches in all over India, I was asked to write a programm. I have to swap the values of three variables without using fourth varable.  I found it really triky. I will first explain this with two variables and than show for three variables in two diffrent ways.

                 Lets, consider the case    a = 10 and b=20. I have to write the programm so that result will be a= 20 and b= 10. Below is the steps,

a = 10;
b=20;
a = a+b; ( a= 30)
b = a - b; (b = 30 - 20 =10)
a =  a-b; (a = 30-10 = 20)

Fig - 1 Steps to swap the values of two variables.

     Now take three variables, a= 10, b=20 and c =30. The output should be a=30, b=10 and c= 20. First way to achive this is you can use steps mentioned in Fig -1 three times. First swap a and b than a and c. Below is the steps,

 

a = 10;
b=20;
c=30;


a = a+b; ( a= 30)
b = a - b; (b = 30 - 20 =10)
a =  a-b; (a = 30-10 = 20)

// Here a= 20 and b= 10;

a = a+c; ( a= 20 + 30 = 50)
c = a - c; (c = 50 - 30 =20)
a =  a-c; (a = 50-20 = 30)

// Here a= 30 and c= 20;

Fig - 2 Steps to swap the values of three variables.

 

Second way of swapping the values of three variable is,

a = 10;
b=20;
c=30;


a = a+b+c;  ( a= 60)
b = a - (b+c);  (b = 60 - (20+30) =10)
c =  a- (b+c);  (c = 60 - (10 + 30) = 20)
a = a- (b+c);   (a = 60 - (10 + 20) = 30)

Fig - 3 Steps to swap the values of three variables.

Happy Programing.

Tuesday, February 13, 2007

Send an Email using SQL Server

         In my recent project, we have  to send an email to client when his/her subscription is about to complete. For this we need to check the database daily at and have to send an email to related client regarding their subscription end date. The simplest idea is to create the job for this task, which daily sends an email to client. The main thing is a SP which sends an email. We search on Google and found one. My friend modified it according to our requirement. I had written proper comments for each line so that any one can understand and modify it.

        SP takes From Address, To Address, CC, Subject and Body as parameter. It creates CDO object and use it to send an email. Your IIS must have SMTP server and it must be properly configured to send an email. I have also included some links from MSDN which can helps to configure SMTP server. Below is the SP,

 

--------------IIS server must be configured to send an email------------------------------
CREATE PROCEDURE usp_SnapSendMail @From varchar(2000) , @To varchar(2000), @CC varchar(2000) , @Subject varchar(1000)=" ", @Body varchar(7000) =" "

/******************************************

This stored procedure takes the parameters and sends an e-mail.
All the mail configurations are hard-coded in the stored procedure.
Comments are added to the stored procedure where necessary.
References to the CDOSYS objects are at the following
MSDN Web site: http://msdn.microsoft.com/library/default.asp?url=/ library/en-us/cdosys/html/_cdosys_messaging.asp

*******************************************/

AS
Declare @iMsg int
Declare @hr int
Declare @source varchar(255)
Declare @description varchar(500)
Declare @output varchar(1000)

--***** Create the CDO.Message Object *****

EXEC @hr = sp_OACreate 'CDO.Message', @iMsg OUT

--*****Configuring the Message Object *****

-- This is to configure a remote SMTP server.
-- http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cdosys/html/_cdosys_schema_configuration_sendusing.asp
EXEC @hr = sp_OASetProperty @iMsg, 'Configuration.fields ("http://schemas.microsoft.com/cdo/configuration/sendusing").Value','2'

-- This is to configure the Server Name or IP address.

-- Replace MailServerName by the name or IP of your SMTP Server.
EXEC @hr = sp_OASetProperty @iMsg, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/smtpserver").Value', 'dotnet-dipak'

EXEC @hr = sp_OASetProperty @iMsg, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/sendemailaddress ").Value','dotnet-dipak'

-- Save the configurations to the message object.
EXEC @hr = sp_OAMethod @iMsg, 'Configuration.Fields.Update', null

-- Set the e-mail parameters.
EXEC @hr = sp_OASetProperty @iMsg, 'To', @To
EXEC @hr = sp_OASetProperty @iMsg, 'From', @From
EXEC @hr = sp_OASetProperty @iMsg, 'CC', @CC
EXEC @hr = sp_OASetProperty @iMsg, 'Subject', @Subject

-- If you are using HTML e-mail, use 'HTMLBody' instead of 'TextBody'.
EXEC @hr = sp_OASetProperty @iMsg, 'HTMLBody', @Body
EXEC @hr = sp_OAMethod @iMsg, 'Send', NULL

-- Sample error handling.

IF @hr <>0 select @hr BEGIN EXEC @hr = sp_OAGetErrorInfo NULL, @source OUT, @description OUT IF @hr = 0 BEGIN SELECT @output = ' Source: ' + @source PRINT @output SELECT @output = ' Description: ' + @description PRINT @output END ELSE BEGIN PRINT ' sp_OAGetErrorInfo failed.' RETURN END END
-- Do some error handling after each step if you have to.
-- Clean up the objects created.
EXEC @hr = sp_OADestroy @iMsg

GO

Fig -1 SP to send an Email

 

Happy Programing.

Monday, February 12, 2007

Gridview with Radio Buttons

      In my current project, I have to display a grid which has Radio button in each row and user can select one radio button. The task was simple, according tome. I took Template Field and place radio button in item template. I set "GropName"  property to "Commom".  According to me its enough and now user can select only one radio button. However the result was unexpected and I found that user can select more than one !!!!!!. Then I came to know that, GroupName property works only when all radio buttons are in same row. Then I took HTML Control for radio button and set "Name" property. This time, the grid and radio buttons work perfectly.

    As now, Radio buttons are HTML controls, I am not able to get it on server side. When user select any radio button and press submit, Control will not available at code behind, you can use "e.Item.FindControl" as it is not "runat='server'". I want ID "Primary Key" value for selected radio button. To achive this I took the help of Javascript. I wrote javascript function that sets the values of "Primary Key" in hidden field when user clicks on any radio button. Now when user clicks on Submit button, user can get selected value froim hidden field.

 

<asp:Repeater ID="rptJobPsting" runat="server" OnItemDataBound="rptJobPsting_ItemDataBound">
<ItemTemplate>
     <table>
           <tr>
               <td valign="top">
                        <input type="radio" id="JobPosting" onclick="CheckISRMSSelectd(this.id,this.checked,'<%#Eval("PackageAmount")%>');"
name="JobPosting" value="<%#Eval("PackageID")%>" />
            </td>
         </tr>
       </table>
</ItemTemplate>
</asp:Repeater>

Fig. - 1 Repeater Control with HTML Radio Button.

 

function CheckISRMSSelectd(ControlID,Value,Amount)
{
document.getElementById(HiddenFieldName).value = Amount + " Rs";
}

Fig. - 2 Javascript functions to check selected

 

Happy Programming.

Print the page using Javascript

          Printing the page using javascript is very common functionality that every web developer requires. Every one has implemented that, though I would like to write a blog for this. My requirement is that, I have to hide few controls like buttons, drop downlist etc. before printing the page. To implemet this, I had set the display properties of those controls to "none" before printing and then again reset it. Below is the scrpt for that,

function PrintPage(Control)
{

// Pass the controls ID, which you do not want to print and
// its display property to "none"
Control.style.display = "none"
var PrintValue = document.getElementById('dvPrint').innerHTML;
var WinPrint = window.open('','','left=' + screen.width + ',top=' + screen.height + ',width=1,height=1,toolbar=0,scrollbars=0,status=0');
WinPrint.document.write(PrintValue);
WinPrint.document.close();
WinPrint.focus();
WinPrint.print();
WinPrint.close();
// Set display property to ""
Control.style.display = "";
return false;
}

Monday, February 05, 2007

Select Distinct form Datatable

 

I need to write a code by which I can show distinct product name in drop down list and I have to do that from code once I have received dataset from DAL. I can iterate through all records and sore the distinct values in Array. I thought some other way for this. My function will take datatable as argument and returns new datatable with only one colun on which yu want distinct records. You may change it and return all the columns just by changing few lines. Below is the function,

 

private DataTable SelectDistinct(string ReturnTableName, DataTable SourceTable, string ReturnFieldName, string AdditionalFilterExpression)
{
DataTable dt = new DataTable(ReturnTableName);
dt.Columns.Add(ReturnFieldName, SourceTable.Columns[ReturnFieldName].DataType);
object LastValue = null;
foreach (DataRow dr in SourceTable.Select("", ReturnFieldName + " Asc"))
{
if (LastValue == null || !(ColumnEqual(LastValue, dr[ReturnFieldName])))
{
LastValue = dr[ReturnFieldName];
dt.Rows.Add(new object[] { LastValue });
}
}

return dt;
}

//Following function compares the value of two objects and returns true or false based on the same.
private bool ColumnEqual(object A, object B)
{
// Compares two values to see if they are equal. Also compares DBNULL.Value.
// Note: If your DataTable contains object fields, then you must extend this
// function to handle them in a meaningful way if you intend to group on them.

if (A == DBNull.Value && B == DBNull.Value) // both are DBNull.Value
return true;
if (A == DBNull.Value || B == DBNull.Value) // only one is DBNull.Value
return false;
return (A.Equals(B)); // value type standard comparison
}

Happy Programing.

Thursday, February 01, 2007

Converting DataSet into Recordset

         

           I was working on one of my most challenging application, before few months. In that we have to use third party DLL for generating PDF file in ASP.NET 2.0. The requirement is that we have to use the DLL which client was using for his ASP application. The main hurdle  for me is that, the DLL accepts only Recordset as input.

           I search on the net however I did not found any solution. After few days of searching I tried to implement by my own. I took the help of my senior "Nikhil" and we foung the solution. Below is the code for converting DataSet into Recordset.

 

static public ADODB.Recordset ConvertToRecordset(DataTable inTable)
{
     ADODB.Recordset result = new ADODB.Recordset();
     result.CursorLocation = ADODB.CursorLocationEnum.adUseClient;

     ADODB.Fields resultFields = result.Fields;
     System.Data.DataColumnCollection inColumns = inTable.Columns;

    foreach (DataColumn inColumn in inColumns)
    {
          resultFields.Append(inColumn.ColumnName
         , TranslateType(inColumn.DataType)
         , inColumn.MaxLength
         , inColumn.AllowDBNull ? ADODB.FieldAttributeEnum.adFldIsNullable :
         ADODB.FieldAttributeEnum.adFldUnspecified
        , null);
    }

    result.Open(System.Reflection.Missing.Value
   , System.Reflection.Missing.Value
   , ADODB.CursorTypeEnum.adOpenStatic
   , ADODB.LockTypeEnum.adLockOptimistic, 0);

   foreach (DataRow dr in inTable.Rows)
   {
              result.AddNew(System.Reflection.Missing.Value,
              System.Reflection.Missing.Value);

              for (int columnIndex = 0; columnIndex < inColumns.Count; columnIndex++)
             {
                     resultFields[columnIndex].Value = dr[columnIndex];
              }
     }

     return result;
}

static ADODB.DataTypeEnum TranslateType(Type columnType)
{
         switch (columnType.UnderlyingSystemType.ToString())
        {
                    case "System.Boolean":
                               return ADODB.DataTypeEnum.adBoolean;

                    case "System.Byte":
                              return ADODB.DataTypeEnum.adUnsignedTinyInt;

                   case "System.Char":
                              return ADODB.DataTypeEnum.adChar;

                   case "System.DateTime":
                              return ADODB.DataTypeEnum.adDate;

                   case "System.Decimal":
                              return ADODB.DataTypeEnum.adCurrency;

                   case "System.Double":
                             return ADODB.DataTypeEnum.adDouble;

                   case "System.Int16":
                              return ADODB.DataTypeEnum.adSmallInt;

                   case "System.Int32":
                             return ADODB.DataTypeEnum.adInteger;

                    case "System.Int64":
                              return ADODB.DataTypeEnum.adBigInt;

                   case "System.SByte":
                             return ADODB.DataTypeEnum.adTinyInt;

                   case "System.Single":
                            return ADODB.DataTypeEnum.adSingle;

                   case "System.UInt16":
                             return ADODB.DataTypeEnum.adUnsignedSmallInt;

                    case "System.UInt32":
                              return ADODB.DataTypeEnum.adUnsignedInt;

                   case "System.UInt64":
                             return ADODB.DataTypeEnum.adUnsignedBigInt;

                    case "System.String":
                   default:
                             return ADODB.DataTypeEnum.adVarChar;
         }
}

 

You can email me, if you have any questions.

Happy Programming.

Read value from Registry

 

                Before few months when I was ne in Cygnet, I was assign a task to read store connection string in registry and read the value from there whenever require. This is something new and I had never implemented it before.

                  Thanks to my collegue (now friend ) SEHUL a little master, who helped me in doing this. Below is the code.

Microsoft.Win32.RegistryKey rgk = Microsoft.Win32.RegistryKey.OpenRemoteBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, "MachineName");

rgk = rgk.OpenSubKey(@"HARDWARE\DESCRIPTION\SYSTEM\CentralProcessor\0");
string strValue =Convert.ToString( rgk.GetValue("Identifier"));
MessageBox.Show(strValue);

Happy programming.

Friday, January 26, 2007

Accessing Active Directory using C#

 

            I was reading an article about Active Directory as Active directory is installed in our office recenly. It was really nice article and the auther has mentioned that you can access active directory using c# or any language. I tried to implement that, obviously I had search on google and found some cod for same. I chose the one and modify it according to my need. Below is the code,

 

using System;
using System.Web;
using System.Web.UI.WebControls;
using System.Data;
using System.Collections;
using System.DirectoryServices;

namespace DirectorySearcher_infovish
{
/// <summary>
/// Summary description for DirectorySearcher.
/// </summary>
public class DirectorySearch
{
public Hashtable objHash;
static int count=0;
SortedList objSortedList;
public string domain;

public DirectorySearch()
{
}

public void FillEmployee(System.Web.UI.WebControls.DropDownList ddlEmpName)
{
string domain = System.Configuration.ConfigurationSettings.AppSettings["DomainIP"];
DirectoryEntry de = new DirectoryEntry("LDAP://"+domain);
de.Username = username; // Domain Admin user name
de.Password = password; // Domain Admin password
DirectorySearcher ds = new DirectorySearcher(de);
ds.Filter = "(&(objectClass=user)(objectCategory=person))";
ds.Sort.PropertyName = "CN"
ds.Sort.Direction = SortDirection.Ascending;
ds.SearchScope = SearchScope.Subtree;
ds.PageSize = 4000;

count++;
try
{
objSortedList = new SortedList();
foreach(SearchResult result in ds.FindAll())
{
DirectoryEntry deTemp = result.GetDirectoryEntry();
try
{
objSortedList.Add (deTemp.Properties["cn"].Value.ToString(),deTemp.Properties["Mail"].Value.ToString());
}
catch(Exception ex)
{
ex.Message.ToString();
}
}
FillGroup(ddlEmpName);
}
catch(Exception ex)
{
HttpContext.Current.Response.Write(ex.ToString());
}
finally
{
}
}

}

}

Happy Programming.

Friday, January 19, 2007

Use File Dependancy for Caching in Asp.net 2.0

        Today I get some free time, so I thought lets work on other project currently running in organisation. I found that we are using caching one of the project and database is SQL Server 2000. We have to set dependancy for cached data. I have implemented this previously and asked my Project Lead to let me do that part. However when I started working on that I found I forgot the few things ( Specially SP that generates a text file when data in perticular table or tables be changed).

         I seach on my old archives and foud the SP (obviosly that is not written by me, as I not that much good in SQL anyway). Lets start with the things what I did. I have created a demo application which has two pages. One with read only Grid and other with editable grid. The basic Idea is when ever changes occure in few tables or selected table, one text file is generated (is it is not already generated) or append.

         Lets start with SP, below is the SP that append or generate text file.

CREATE PROCEDURE sp_AppendToFile(@FileName varchar(255), @Text1 varchar(255)) AS

DECLARE @FS int, @OLEResult int, @FileID int

EXECUTE @OLEResult = sp_OACreate 'Scripting.FileSystemObject', @FS OUT

IF @OLEResult <> 0 PRINT 'Scripting.FileSystemObject'

execute @OLEResult = sp_OAMethod @FS, 'OpenTextFile', @FileID OUT, @FileName, 8, 1

IF @OLEResult <> 0 PRINT 'OpenTextFile'

execute @OLEResult = sp_OAMethod @FileID, 'WriteLine', Null, @Text1

IF @OLEResult <> 0 PRINT 'WriteLine'

EXECUTE @OLEResult = sp_OADestroy @FileID

EXECUTE @OLEResult = sp_OADestroy @FS

Fig - (1)  SP: to modify Text file.

         My requirement is that whenever records in Employee table chage, it should modify the data that is available in cache and data should be displayed from Server instead of cache. To do this I have created one trigger on Employee table which call Sp (shown in Fig - (1)) and change the text file. Below is the trigger that I used,

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go

ALTER TRIGGER [UpdateEmployee]
ON [dbo].[Employee]
FOR INSERT, UPDATE , DELETE
AS
BEGIN

exec sp_AppendToFile 'FileName.txt' , 'Message'

END

Fig - (2) Trigger: This will change Text file

 

  Now for coding, below is the code that I have used for inserting dataset in cache with file dependency.

 

if (Cache["Data"] == null)
{
     SqlDataAdapter sda = new SqlDataAdapter(cmd);
     sda.Fill(dsTemp);
    System.Web.Caching.CacheDependency objDependancy   =new System.Web.Caching.CacheDependency(@"FileName.txt");
Cache.Insert("Data", dsTemp, objDependancy,   DateTime.Now.AddDays(1), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.High, null);


}
else
{
          dsTemp = (DataSet)Cache["Data"];
}

I hope this will help you. Happy Programming.