Click to See Complete Forum and Search --> : web service and ocx


mcordonn
February 24th, 2006, 03:05 PM
I am a beginner and I am lost.

What is the best way to have a web service method call an ocx (or another method in a .Net application)?

I tried to create a static class (in the web service) which instantiates the ocx. It works with the MSCalendar but not with my ocx.

Is it because the service is stateless and the ocx must run in its own thread? If so what should I do?

Can someone give me a few tips or is there a book / article that could help me?

Thanks in advance.
Michel.

mmetzger
February 24th, 2006, 04:53 PM
It all really depends on what you need to do. If the OCX requires any measure of interactivity you can't really do it as the UI is never presented. If it's a COM dll, you can wrap it in .NET and call it from there.

mcordonn
February 24th, 2006, 10:09 PM
mmetzger, thank you very much for your reply.

Can you give me more details?

Let me be more specific. Say:

(S) is a .Net asp web service project and [s] one of its public methods,
(A) is .Net application project and [a] one of its public methods.

I want [a] to be called when [s] is called. ( [a] will then access a COM dll )

In other words I want something to happen in an application if a function of a web service is called.

It is very easy to access the service from an application by adding a reference to (S) in (A), but what about the opposite?

How do I go from [s] to [a]?

Thanks again for your help.
Michel.

mmetzger
February 24th, 2006, 10:33 PM
Typically the way you'd do this is make a class library in .net (aka - [a]) that you could instantiate in [s]. You can then call it accordingly. The trick is making sure all necessary permissions are in place (either filesystem and / or CAS permissions.)

Basically, the .net class is a wrapper for what you want the COM object to do. You just instantiate it with the web service.

Be careful though as some COM objects can be really memory intensive in this format, especially if it wasn't designed with web request behavior in mind.

I hope that helps...

mcordonn
February 25th, 2006, 07:50 AM
mmetzger, I really appreciate your help :thumb:

It works! I have two more questions though:

1-
I cannot create the COM object as a local variable of [a] because the instance would be lost after the call. I would not be able to re-access the same object later on, and would thus loose its properties, ...

I made the COM object a static variable of the web service (S) to avoid that issue. I read however that since a web service is stateless, IIS can decide to 'dispose' it and then 'recreate' it if necessary. In that case I may also loose an instance of the object. Is it true?

2- What if I really need to have [s] call [a] (and then the COM dll) in a .Net application (with GUI) instead of a class library?
You wrote that I can't really do it. Does it become an interprocess communication issue? What are the options in that case?

Thank you very much.
I hope this discussion will help other members too.

Michel.

mmetzger
February 25th, 2006, 05:22 PM
I'll try to answer based on what I know...

1) IIS (more over ASP.NET) can decide to extinguish objects at any time. You may want to try adding the object to the Application or Session variable. This really doesn't save you from the issue, but you can at least check to see if the instance is null and restart it.

2) As far as I know, you cannot interact with a GUI program with a non-logged in user (ie, non-interactive.) Since ASP.NET / IIS runs as a service, it's technically not logged in. One of the more experienced guys may be able to tell you a way of doing this but I'd imagine it has to do with dealing directly with the window handles (which once again I'm not sure exist for service accounts.) I do know that typically you'll get an exception starting an interactive program / method as a service account...

Hope that helps... May I ask, what is this object / program you're interacting with. Is there any other way to meet the requirement?

mcordonn
February 26th, 2006, 10:01 PM
mmetzger,

Here is the whole story:

- The goal is to capture images with a device that must be accessible from any location in a network using a web service and its methods.
- The device is controlled by a COM dll
- The device acts like a state machine. It must be turned on, configured before capturing images (the COM object must therefore be preserved throughout a session).

A prototype has been built by a former colleague. He created a standard .Net application that behaves like a web service. The interface is based on wse 2.0 and uses uri end point references, soap message senders & receivers, … (fyi it also uses Plumbwork Orange to send events back to the consumer app when the state of the device changes).

Everything works pretty well but (it seems to me that) the interface is not quite like that of an ASP.Net service. It is not hosted by IIS and cannot be discovered or described. Also, the interface is only available if the application is running. There may be other issues I don't know about yet.

I thought that using a ‘real’ web service project in VS and hosting the rest of the code in a class library might work. Your last message however makes me think that it won’t since the COM object may not persist. (There also won’t be a gui to display the status of the device, but that is a minor issue).

It would be nice if a .Net application could have an ASP.Net web service interface, but I don’t think it is possible.

At this time I wonder if I should wrap the existing interface in a ASP.Net web service (ASP.Net web service <=> “wse2.0 interface” <=> .Net application with gui). I don’t know if it is doable and if it would impact the performance a lot.

Does the above make sense? Would you consider a different approach?

Thanks for following-up :thumb:
I was not expecting so much help :)

Michel.

(my terminology may be inaccurate since I am new to web services and ASP.Net)

mmetzger
February 27th, 2006, 06:58 AM
Ok, that explains things a little more. A couple options I can think of:

1) If you want to wrap the COM dll and save it in the state variables (I'm not actually sure that will work, but it very well could) you can have an accessor type of code that checks if the instance is null. If it is, reload it along with all the configuration code. Problems here include speed (ie, I have no idea the timing requirements this has, the device or the project) and if the device doesn't like reconnection continuously.

2) You can add an ASP.NET style hosting to any given application. Take a look at the System.Web.Hosting namespace. I haven't done too much work in this area but it may do what you need. It would require the app to be constantly running but may be an easy add-on. Take a look at Cassini (http://www.asp.net/Projects/Cassini/Download/Default.aspx?tabindex=0&tabid=1) for an example server Microsoft wrote using this. I'm not sure this will do exactly what you need but it should be able to do everything asp.net inside IIS does (outside of other ISAPI filters / etc.)

3) You could create a web service (a proxy I suppose in this case) but I think the underlying complexity is going to be pretty nasty (ie, authentication, if something breaks, etc.)

I guess if anything I'd try #2... it sounds the most fun... ;)

mcordonn
February 27th, 2006, 11:36 AM
Okay. I think I better understand what my options are.
I have just one final question: Do you any good web site or book describing what you wrote earlier: "IIS (more over ASP.NET) can decide to extinguish objects at any time"? I have not found much on the subject so far.

Thanks a lot for the tips. :wave:
Michel.

mmetzger
February 27th, 2006, 05:42 PM
I haven't really seen any books on that subject, it's just more from practice. I've had some really nasty bugs relating to Session, Cache, and Application variables having invalid references. As long as you check to make sure it's not null, you should be fine. An example (using a dataset) would be like:


private DataSet retrieveFromCache()
{
DataSet ds;
try
{
ds = (DataSet)Cache["mydataset"];
if (ds == null)
{
ds = new DataSet();
SqlConnection conn = new SqlConnection(connectstring);
SqlDataAdapter da = new SqlAdapter(query, conn);
da.Fill(ds, "mytable");
Cache["mydataset"] = ds;
}
}
catch (System.Exception ex)
{
// Exception code...
}
return ds;
}


}