asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search





Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

Active Server Components with VS 5.0
By Wayne Berry
Rating: 4.5 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

    In This Issue

    This issue is a rewrite of part one of a four-part series on Active Server objects. In the issue is a simple example of creating a Active Server Component in Visual Studio 5.0 using the Active Template Library 2.0. The component that we are going to create will get the user's cookie, or assign a cookie if the user doesn't have one.

    The previous issue had demonstrated creating a COM object using Microsoft Visual C 4.2 and ATL 1.1. If you are still using MSVC 4.2 we recommend you upgrade, Visual Studio makes COM object much easier to program. If you have Microsoft's Visual Studio 97, you can get started right away.

    Creating an ATL Project

    The first step in creating an Active Server Component is to create an ATL project. We will create the ATL Project using the ATL COM Wizard. The code that the wizard produces is nothing more then a DLL shell. The shell code has the ability to register the objects that will be defined later, create these objects through a class factory and a DllMain to support the DLL. The shell by itself is not an Active Server object. The DLL shell that the ATL Wizard created can hold more than one Active Server Object. This shell/project can contain many individual objects that can share the same code.

    Using the ATL COM Wizard

    1. Open Microsoft Developer Studio 97.
    2. File | New.
    3. Click on the Project Tab.
    4. From the list of projects choose ATL COM AppWizard.
    5. For Project name type SMUM. It is important to note here that this is not the name of the object but the name of the project. I like to name the project the same as the company that the project will be licensed under. I also prefer to have the of the project (Company) also be the first part of the common name of the object. In the example 'SMUM' stands for Sign Me Up Marketing. The Prog Id of the object in this example will be SMUM.Example. The reason that I prefer to not name the project the same name as the object is that there may be more than one object within a project/shell. Also, the ATL Wizard will have problems with file names later if the object and the project are called the same name.

      Figure 01 : New

    6. Press OK. A dialog called ATL COM AppWizard - Step 1 of 1 will appear.
    7. Check Allow merging of proxy/stub code.
    8. Click On Finish.
    9. Click on OK.

      Figure 02 : ATL COM AppWizard - Step 1 of 1

    Files Effected

    • SMUM.cpp : This file contains the code for the project, including: code for the Class Factory, registration and DllMain.
    • SMUM.def: This is the definition file that tells the compiler which procedure to export. Nothing interesting here, the class factory and the registration functions are exported.
    • SMUM.idl: This is the Interface Definition File, the ATL COM Wizard doesn't implement any interfaces through the .idl file until objects are added in step 2.
    • SMUM.rc: This is the DLL resource file, nothing exciting here.
    • StdAfx.cpp, StdAfx.h: Precompiled header files.
    • dlldatax.c: This file contains code for merging the proxy/stub.

    Step 2

    The next step is to create an Active Server Component within the newly created project., The ATL Object Wizard creates these files:

    • Example.cpp
    • Example.h
    It also adds code to the project's SMUM.idl describing the interface of the Example object.

    Files Effected

    The next step is to create an Active Server Component within the newly created project., The ATL Object Wizard creates these files:

    • Example.cpp
    • Example.h
    It also adds code to the project's SMUM.idl describing the interface of the Example object.

    Step 2 : Creating an Active Server Component

    The second step is to add an Active Server component to the project shell created in Step 1. This also is done with a wizard, the ATL Object Wizard.

    ATL Object Wizard

    1. From the menu bar click on Insert | New ATL Object .
    2. A dialog called "ATL Object Wizard" will appear.
    3. Since we are creating a Component choose component from the left-hand list box.
    4. In the right-hand list box choose the type of component, ActiveX Server Component.

      Figure 03 : ATL Object Wizard

    5. Click on Next>.
    6. Another Dialog will appear called "ATL Wizard Object Properties".
    7. For Short Name type in the name of the Component. In this example we will be calling it Example. Notice that while you type, the other properties are automatically filled in.
    8. In step one, I mentioned that the example object Prog ID would be called "SMUM.Example", so highlight the first part of the Prog ID and replace it with SMUM. Make sure not to Highlight the period that separates the first part of the Prog ID with the second part. For some reason you can not type a period in this edit box. Erasing the period will mean that you will have to start over from scratch.
    9. Also modify the Type to read Sign Me Up Marketing Example Component. This way when you test the component from ActiveX Control Test Container you will be able to find it quickly.

      Figure 04 : ATL Wizard Object Properties

    10. Click on OK to create the Object.

    Object Member Variables

    When creating an Active Server object, with the ATL Object Wizard, by default the wizard adds member variables that Interface the Application, Request, Response, Server and Session objects.

    Planning Your Project

    Hold On. Ok, you just ran through the steps to create an Active Server Object with the ATL Object wizard. What really happened? What did the wizard do? The wizard inserted code and created files to support the COM object named Example. This is the same code that it would have created if you had chosen to create a Simple Object instead of an Active Server Component. The difference is that the Wizard added additional code to get to the Active Server Components: Application, Request, Response, Server and Session. If you do not need to get to the methods and properties of these interfaces you might be better off making a Simple Object instead.

    The Simple Object

    Simple Objects are sometimes much better for large projects where you are going to use the same object over and over again. With an Active Server Component, the component has the ability to access the Active Server objects (Application, Request, Response, Server and Session), through interfaces in the Active Server Component code. This is convenient if the component is only going to be used in an Active Server environment. For instance if you want to create a customer object based on a cookie you can call an Active Server Component from an Active Server Page like this:

     Set Creator=Server.CreateObject("SMUM.CustomerCreator.1")

    Set Customer = Creator.CreateCustomer

    Customer.EmailAddress = "webmaster@postpointsoft.com"
    When the CustomerCreator object performs the CreateCustomer method, the Cookie value is retrieved from the Request interface within the CustomerCreator object. The cookie call to the Request object is hidden from the Active Server Page Developer. The Creator object also sets the Cookie in the Response interface if the user currently does not have a cookie. Finally, the email address is written to a database with the cookie serving as the primary key.

    Consider this example where the Creator object is a simple object instead of an Active Server Component.

     Set Creator=Server.CreateObject("SMUM.CustomerCreator.1")

    Set Customer = Creator.CreateCustomer(Request.Cookies("SMUMID"))

    Response.Cookies("SMUMID") = Customer.Cookie

    Customer.EmailAddress = "webmaster@postpointsoft.com"
    In this example we have to pass the Cookie in the Creator object and assign the Cookie once we have created the Customer object. This technique makes more work for the Active Server Page programmer. If it is more work then why is it better to create a simple object? The answer lies within the scope of the project.

    For instance, once all the email addresses are collected from the web site, you may want to view each customer from your desktop. With the simple object, you could create a Visual Basic application that viewed each email address in turn. However, you would not be able to call the Active Server component from Visual Basic, since the instantiation of the Active Server interfaces would fail.

    This is the point, simple objects can be called from Visual Basic and Active Server pages, and Active Server components can only be called for Active Server Pages. So, for a little more work you can get a lot more use out of your object. This is important. It could effect your life, your job, and your relationship, all right maybe not your relationship. With a little planning you could have same amount of code pulling double duty and saving you a lot of work.

    Going On

    If you want to ignore my advice or have a bad relationship already and want to use a Active Server component, I will show you how.

    In Step 3 I am going to show you how to add a method to your component using Visual Studio 97.

    Creating a Method

    Let's implement a method to get and set a cookie. First thing that we need to do is add a method called GetCookie to the Example interface.

    1. Go to the Project Window of the SMUM project.
    2. Click on the Class View Tab.
    3. Expand the Cexample class until we can see the interface entitled: IExmaple.
    4. Right click on IExample and choose Add Method.

      Figure 05 : Adding a Method in the Project View

    5. A dialog should appear called Add Method to Interface.
    6. For Method Name type in GetCookie.
    7. For Parameters type in [out,retval] BSTR *pVal.

      Figure 06 : Add Method to Interface

    8. Click on OK.

    The Benefits of Visual Studio 97

    By adding a method through the project view, the interface description is inserted into the *.idl and supporting code for the class is generated. All that needs to be done now is to implement GetCookie in the Example class.

    In Step 4 we are going to add the functionality to the GetCookie method created in Step 3. This method gets the current cookie, if not avialable creates a cookie and returns it's value.

    Too quickly get to the section of code where Visual Studio added the method, in the project window: expand the project, then expand the IExample interface, finally double click on the GetCookie method. Add the following code to the GetCookie method that you just create in Step 3.

    The Code

    
    STDMETHODIMP CExample::GetCookie(BSTR * pVal)
    {
    	GUID				guid;
    	TCHAR				lpszCookie[25];
    	VARIANT				varOptional;
    	HRESULT				hr;
    
    	// Check the Pointer 
    	if (pVal==NULL)
    		return E_POINTER; 
    
    	// Optimistically set the Returning 
    	// HRESULT
    	hr=S_OK;
    
    	// Configure the Optional Variant
    	// This configuration follows
    	// the documentation for the
    	// Active Server Object Interfaces
    	V_ERROR(&varOptional) == DISP_E_PARAMNOTFOUND;
    
    	// Check to make sure all the interfaces
    	// loaded correctly.  This is the part
    	// that would fail if you called this
    	// object from Visual Basic.
    
    	if (m_bOnStartPageCalled)
    	{
    		// Allocate The Request Dictionary Objects
    		// So that we can pass them to the Active
    		// Server Object Interfaces
    		CComPtr piReadDict;
    		CComPtr piWriteDict;
    
    		// Pointer to the Write Cookie Interface
    		IWriteCookie		*piWriteCookie;
    	
    		// From the Request Interface Retrieve
    		// a Dictionary of Cookies
    		hr=m_piRequest->get_Cookies(&piReadDict);
    
    		if (FAILED(hr))
    			return hr;
    
    		// Allocate and Set Variants to pass to 
    		// the Dictionary
    		CComVariant vtIn(_T("GUID"));
    		CComVariant	vtOut;
    
    		// Get the Cookie from the dictionary
    		// named SMUMID and put it in vtOut
    		hr = piReadDict->get_Item(vtIn, &vtOut);
    
    		if (FAILED(hr))
    			return hr;
    
    		// vtOut Contains an IDispatch Pointer. 
    		// To fetch the value  for the cookie, you
    		// must get the Default Value for the 
    		// Object stored in vtOut using VariantChangeType.  
    		hr = VariantChangeType(&vtOut, &vtOut, 0, VT_BSTR);
    
    		if (FAILED(hr))
    			return hr;
    
    		// If the Cookie isn't set then
    		// the length of vtOut will be 0
    		if (!wcslen(V_BSTR(&vtOut)))
    		{
    			// There isn't a Cookie assigned
    			// So we have to create one.
    
    			// Use a GUID for the Unqiue User Cookie
    			CoCreateGuid(&guid);
    
    			// Put the GUID into a String
    			wsprintf(lpszCookie,
    				_T("%X%X%X%X%X%X%X%X%X%X%X"),
    				guid.Data1,
    				guid.Data2, guid.Data3,
    				guid.Data4[0], guid.Data4[1],
    				guid.Data4[2], guid.Data4[3],
    				guid.Data4[4], guid.Data4[5],
    				guid.Data4[6], guid.Data4[7]);			
    
    			// Create a Variant from the String
    			CComVariant	vtCookieValue(lpszCookie);
    
    			// Get the writable Cookie Dictionary 
    			// from the Response Object.  Notice
    			// that it is the Response Object and
    			// not the request object like above.
    			hr=m_piResponse->get_Cookies(&piWriteDict);
    
    			if (FAILED(hr))
    				return (hr);
    
    			// Get the Writable Interface for
    			// the GUID cookie from the Cookie Dictionary
    			// Notice here that the GUID cookie
    			// doesn't exist in the dictionary, but we
    			// can still ask for it's interface
    			hr = piWriteDict->get_Item(vtIn, &vtOut);
    
    			if (FAILED(hr))
    				return(hr);
    
    			// Make it easy on ourselves, get and cast
    			// the IDistpach value to the dual interface
    			// that we want to call
    			piWriteCookie = (IWriteCookie*)(vtOut.ppdispVal);
    			
    			// Create the Cookie using the Name GUID and the Value of
    			// the GUID that we generated
    			hr = piWriteCookie->put_Item(varOptional,
    				V_BSTR(&vtCookieValue));
    
    			if (FAILED(hr))
    				return(hr);
    
    			// Create a Expiration Date sometime in the future
    			// To keep the example simple, I am using my birthday
    			// in 2010.  10/4/2010.  Some other time we will show
    			// how to generate a VB DATE (double) without MFC.
    			DATE	dtExpiration=40455.0;
    			
    			// This is required if you want the browser
    			// to retain the cookie between sessions
    			hr = piWriteCookie->put_Expires(dtExpiration);
    
    			if (FAILED(hr))
    				return(hr);
    
    			// Assign the out,retval
    			*pVal = ::SysAllocString(V_BSTR(&vtCookieValue)); 
    
    			// A little help for Debugging
    			ATLTRACE (_T("Setting Cookie to: %s\n"),
    				V_BSTR(&vtCookieValue));
    		}
    		else
    		{
    			// Assign the out,retval
    			*pVal = ::SysAllocString(V_BSTR(&vtOut));
    			
    			// A little help for Debugging
    			ATLTRACE (_T("Cookie was set to: %s\n"),
    				V_BSTR(&vtOut));
    		}
    	}
    
    	return hr;
    }
    
    

    The Finally Step

    Once you have added the procedure above, build the DLL. After compilation and linking Visual Studio will register the DLL. This way you can use the Component on your development machine if you have IIS. Otherwise you will have to move it to a machine that has IIS installed. Make sure to register the component on the new machine, if you move it. The last step is to add the component to your asp page.

    The last step is to add the component you just built to your Active Server page.

    The Wrong Way

    As always with setting cookies you must assign the cookie header before the main body of your page. For instance this is the wrong way to send the code:

    
    <HTML>
    <BODY>
    <%
    Set Example=Server.CreateObject("SMUM.Example.1")

    ' The Cookie Header is set with this
    ' call if a cookie doesn't exist
    ' which is too late since some of the body text has
    ' been sent already.
    Cookie = Example.GetCookie()
    %>
    The Cookie is :
    </BODY>
    </HTML>

    The Right Way

    Here is the right way to call the Active Server Component :

    
    <%
    ' Here is where the OnStartPage method is called
    Set Example=Server.CreateObject("SMUM.Example.1")

    'Here is the method call to assign the cookie
    Cookie = Example.GetCookie()
    %>
    <HTML>
    <BODY>
    <%=Cookie%>
    </BODY>
    </HTML>

    Only the Component

    If you do not want to be bothered with Microsoft Visual Studio, compiling the source code or using Active Template Library, you can download just the component and the Active Server Page here. Make sure that you register the object before calling it. This is the Release version

    042297d.zip (6 K)

    Only the Source

    Here is the source for the component and Visual Studio 97 project described in this issue of 15 Seconds.

    042297c.zip (26 KB)

    Registering the Component

    Once you download the component to your machine, you will need to register the object before you can call it with through Active Server. Here is how, from a dos window in the directory that the object is located type:

     regsvr32 smum.dll 

    Thanks George

    Special thanks to George V. Reilly, who gave some important insight in how Active Server Components work.

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Other Articles
    Sep 11, 1997 - The Last-Modified Header in ASP
    A complete discussion of the Last Modified header and the Expires header including the effect they have on Active Server page and various browsers.
    [Read This Article]  [Top]
    Jul 31, 1997 - Creating a Category Site with ASP
    In this issue 15 Seconds implements a catalog site that is build with Active Server pages and SQL Server. Along with the implementation there is source code and a discussion of the advantages and disadvantages of creating a catalog site that gets its content from a database. Included are pages for displaying products, creating a menu page, category page, and running a search across a database.
    [Read This Article]  [Top]
    Apr 6, 1997 - Creating a List Server with ASP
    This issue describes how to make a list server using Active Server, SQL Server, and Stephen Genusa's ASPMail Component. Included are source and instructions for adding the user to the list from a Active Server page, removing the user from the list via a Active Server page, and sending mail to the whole list.
    [Read This Article]  [Top]
    Jan 24, 1997 - Simple ASP Chat
    This 15 Seconds' issue contains source code and step by step instructions for creating a chat session using Active Server pages, HTML and a standard web browser. Also demonstrated is writing and reading of a file with an Active Server page.
    [Read This Article]  [Top]
    Mailing List
    Want to receive email when the next article is published? Just Click Here to sign up.

    Support the Active Server Industry

    internet.comearthweb.comDevx.commediabistro.comGraphics.com

    Search:

    Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

    Jupitermedia Corporate Info

    Legal Notices, Licensing, Reprints, Permissions, Privacy Policy.
    Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers