views:

1271

answers:

3

Here's my problem: I have to call a web service with a secure header from a classic ASP page that returns a complex data type. For various reasons concerning a 3rd party tool it has to be classic ASP. We decided that I should create an external dll to do this - which I did (in c#) so it returns a dataset (Something ASP can understand). However now I need to expose that function to the ASP page. Because this is classic ASP I think the only straightforward way to do this is to expose this class library as a COM object. I need to know the down and dirty easiest way to accomplish this task. What do I have to do to my dll?

I have never created a COM object before only used. Somebody said my class has to be static and I can't have a constructor. Is this true? Can someone layout the steps for me?

HELP! (o:

Edit: This specific problem is now solved however as Robert Rossney noted I can't do anything with the DataSet in classic ASP. This has led me to post a second question here regarding implementing XmlTextWriter - Robert if you see this I think you could really help!

+2  A: 

No, that (static/no ctor) isn't true. Quite the opposite, in fact, since COM will need to create an instance! You simply need to make the class COM visible. Mainly, this is just adding some attributes, and registering it as a COM dll (regasm).

http://msdn.microsoft.com/en-us/library/zsfww439.aspx

Marc Gravell
Can my default constructor have agruments? For instance I want them to ass the username and pw that will be used in the wse security header then call the appropriate function for the response they need.
silverbugg
no. Add an 'init' method to supply the user and pwd to your class.
gbjbaanb
Do all of my fields have to be public or can I expose my fields through public properties to maintain proper data hiding?
silverbugg
Public properties with private fields should be fine.
Marc Gravell
+2  A: 

Creating a class that returns a DataSet is not so difficult:

using System;
using System.Data;
using System.Runtime.InteropServices;

namespace COMTest
{
   [Guid("AC4C4347-27EA-4735-B9F2-CF672B4CBB4A")]
   [ComVisible(true)]
   public interface ICOMTest
   {
       [ComVisible(true)]
       DataSet GetDataSet();
   }

   [Guid("CB733AB1-9DFC-437d-A769-203DD7282A8C")]
   [ProgId("COMTest.COMTest")]
   [ComVisible(true)]
   public class COMTest : ICOMTest
   {
       public DataSet GetDataSet()
       {
           DataSet ds = new DataSet("COMTest");
           return ds;
       }
   }

}

You'll need to check the "Register for COM Interop" box in the Project properties, you'll also need to sign the assembly, and you'll need to make sure that the IIS user can access your bin\Debug directory.

Once you've done this, you can create an instance from ASP just fine:

<%
Dim o
Set o = Server.CreateObject("COMTest.COMTest")
Response.Write("Server.CreateObject worked.")
Response.Write("<br/>")
Dim ds
Set ds = o.GetDataSet()
If Not ds is Nothing Then
  Response.Write("o.GetDataSet returned an object.  Can we use it?")
  Response.Write("<br/>")
  Response.Write("We have a DataSet, and its DataSetName is: ")
  Response.Write(ds.DataSetName)
End If
%>

And here you will be sad. For while the method that returns a DataSet is visible to COM, none of the DataSet's properties or methods are.

Robert Rossney
Do I have to add the Guids to all the helper classes in my dll or just the main interface and class?
silverbugg
Also do all of my fields have to be public - or can I expose my fields through public properties to maintain proper data hiding?
silverbugg
+1 for making me laugh with "And here you will be sad." :)
Mike Powell
Sorry to come back to this so late. You only mark the class and the interface with GUIDs. And not only can you expose your fields through public properties, that's the only way you can expose them - you can't expose fields through an interface.
Robert Rossney
A: 

Somebody said my class has to be static and I can't have a constructor. Is this true?

A COM class needs to have a default constructor, which will be used by clients when they call CoCreateInstance. After the object is created, you can set properties on it, or call other methods.

This is similar to the way that .Net treats serializable objects... you construct it with a default constructor, then set all its properties. (If you like RAII, you're out of luck with both COM and .Net. Get over it;)

As to the static comment, no, that isn't true, as Marc pointed out.

Gene
Actually, only the XmlSerializer required a default ctor; BinaryFormatter and DataContractSerializer have more... "interesting" approaches to object construction.
Marc Gravell