|
Executing ASMX files without a web server
This console application takes a SOAP message (on stdin) and an ASMX filename and a SOAPAction header (as command-line parameters) and returns the resulting SOAP message on stdout. The ASMX file should be in the same directory as the executable; full paths are not supported.
using System;
using System.Web;
using System.Web.Hosting;
using System.IO;
using System.Runtime.Remoting;
using System.Globalization;
namespace AspHostTest
{
public class SoapWorkerRequest : SimpleWorkerRequest
{
string soapstr;
string soapAction;
public SoapWorkerRequest(string page,string soapstr,
string soapAction,TextWriter output) : base(page,null,output)
{
this.soapstr = soapstr;
this.soapAction = soapAction;
}
public override string GetHttpVerbName()
{
return "POST";
}
public override int ReadEntityBody(byte[] buffer, int size)
{
char [] chars = soapstr.ToCharArray();
for (int i=0; i<chars.Length; i++)
buffer[i] = (byte) chars[i];
return chars.Length;
}
public override string GetKnownRequestHeader(int index)
{
string retval;
switch (index)
{
case 11:
retval = String.Format("{0}",soapstr.Length);
break;
case 12:
retval = "text/xml; charset=utf-8";
break;
default:
retval = null;
break;
}
return retval;
}
public override string[][] GetUnknownRequestHeaders()
{
string [] vals = {"SOAPAction",soapAction};
string [][] namesvals = {vals};
return namesvals;
}
public override string MapPath(string path)
{
if (path == GetFilePath())
return GetFilePathTranslated();
return base.MapPath(path);
}
}
public class MyExeHost : MarshalByRefObject
{
public void ProcessRequest(String page,string soapmsg,string soapAction)
{
HttpWorkerRequest hwr =
new SoapWorkerRequest(page,soapmsg,soapAction,Console.Out);
HttpRuntime.ProcessRequest(hwr);
}
}
class MyAspHost
{
public static object CreateApplicationHost(Type hostType,
string virtualDir, string physicalDir)
{
if (!(physicalDir.EndsWith("\\")))
physicalDir = physicalDir + "\\";
string aspDir = HttpRuntime.AspInstallDirectory;
string domainId = DateTime.Now.ToString(
DateTimeFormatInfo.InvariantInfo).GetHashCode().ToString("x");
string appName = (virtualDir + physicalDir).GetHashCode().ToString("x");
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationName = appName;
setup.ConfigurationFile = "web.config";
AppDomain ad = AppDomain.CreateDomain(domainId, null, setup);
ad.SetData(".appDomain", "*");
ad.SetData(".appPath", physicalDir);
ad.SetData(".appVPath", virtualDir);
ad.SetData(".domainId", domainId);
ad.SetData(".hostingVirtualPath", virtualDir);
ad.SetData(".hostingInstallDir", aspDir);
ObjectHandle oh = ad.CreateInstance(hostType.Module.Assembly.FullName,
hostType.FullName);
return oh.Unwrap();
}
static void Main(string[] args)
{
MyExeHost myHost = (MyExeHost)CreateApplicationHost(typeof(MyExeHost),
"/",Directory.GetCurrentDirectory());
myHost.ProcessRequest(args[0],Console.In.ReadToEnd(),args[1]);
}
}
}
To compile the program, open a Visual Studio .NET command prompt (or any other command prompt session with the C# compiler in the path) and run this command:
csc /t:exe /r:System.Web.dll WsHostTest.cs
Put the exe file in a directory with an ASMX file. Here’s the simple file I’ve used in my tests:
<%@ WebService Language="C#" Debug="true" Class="foo" %>
using System.Web.Services;
public class foo
{
[WebMethod()]
public string echo(string input)
{
return input;
}
}
I also created a file with the SOAP message I wanted to use as input for the program. Here is the contents of this file:
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<echo xmlns="http://tempuri.org/">
<input>Howdy</input>
</echo>
</soap:Body>
</soap:Envelope>
</pre>
To call the program, I entered this command line:
WsHostTest echo.asmx http://tempuri.org/echo <soaptext.txt
|
© Copyright 2003 Jim Klopfenstein.
Last update: 2/10/2003; 8:43:53 AM.
|
|