One good reason to use .NET with Visual FoxPro is to publish Web Services. Since the SOAP Toolkit is severely limited in what types of services it can publish using .NET to handle exporting of services is fairly straight forward to do and many developers have surely gone that route.
But what you might not be aware of is that there’s a serious issue with Web Services when used with Visual FoxPro in that .NET Web Services run in Multithreaded Apartments (MTA) which means that they are running in a threading model that assumes that all code is multi-threaded. Visual FoxPro COM components however are Single Threaded (STA) and while they will load on MTA their behavior may become erratic if multiple instances are simultaneously executed. Essentially what happens is that in MTA threaded apartments .NET creates one STA thread on which all COM objects are then loaded which means:
- Only one COM object can execute at a time
- There’s potential for thread leakage as all of them share the same thread
and the same Thread Local Storage (TLS)
Which spells big problems for performance and can easily lead to corruption of data buffers and other global storage that VFP internally uses. In other words it doesn’t work out of the box.
I just ran into this with one of my customers who’s running a relatively small application that publishes some summary reports via a Web Service interface and they ended up getting some cross talk where data was getting mixed up between two clients. Ouch.
Unlike ASP.NET (ASPX) pages, Web Services in .NET do not have an ASPCOMPAT setting so you can’t easily coerce a Web Service request to be initiated on an STA thread. ASPCOMPAT cause ASP.NET to go through some internal thread management by basically offloading requests to a separate pool of threads made available by COM+ and running the requests of these STA threads instead. Alas, this functionality is not available directly for Web Services.
When I was researching this topic I ran into an MSDN article from Jeff Prosise which provides a hacky solution to this problem by creating a custom ASP.NET Handler for ASMX requests and routing it through the ASP.NET Page handler first. The Page handler includes methods to initiate requests on ASPCompat STA threads and his solution basically highjacks the page handler just for this functionality and then manually processes the Web Service request.
Here’s the code from handler Jeff’s article and I verified indeed that it works properly with VFP COM components:
using System;
using System.Web;
using System.Web.UI;
using System.Web.Services.Protocols;
using System.Web.SessionState;
public class AspCompatWebServiceStaHandler :
System.Web.UI.Page, IHttpAsyncHandler, IRequiresSessionState
{
protected override void OnInit(EventArgs e)
{
IHttpHandler handler =
new WebServiceHandlerFactory().GetHandler(
this.Context,
this.Context.Request.HttpMethod,
this.Context.Request.FilePath,
this.Context.Request.PhysicalPath);
handler.ProcessRequest(this.Context);
this.Context.ApplicationInstance.CompleteRequest();
}
public IAsyncResult BeginProcessRequest(
HttpContext context, AsyncCallback cb, object extraData)
{
return this.AspCompatBeginProcessRequest(
context, cb, extraData);
}
public void EndProcessRequest(IAsyncResult result)
{
this.AspCompatEndProcessRequest(result);
}
}
You need to add this class to your APP_CODE directory and then register the handler in Web.config:
<?xml version="1.0"?>
<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="*.asmx"
type="AspCompatWebServiceStaHandler" />
</httpHandlers>
</system.web>
</configuration>
It ain’t pretty but it works. This makes your Visual FoxPro components run properly with ASMX Web Services. It’s a shame there’s not a flag somewhere on the ASMX handler to provide this, but so it goes…
Hopes this saves somebody some time…
Other Posts you might also like