Http://www.microsoft.com/china/msdn/library/webservices/webservices/servicestation.mspx
Run Asmx without IIS
Release Date: 1/7/2005
| Update Date: 1/7/2005
Aaron Skonnard
Download this article: ServiceStation0412.exe (165KB)
When Microsoft® .NET Framework is first published, it introduces a breakthrough web service framework, which is asmx. Designing ASMX's purpose is to simplify the development process of Web services as much as possible, so even if you are not an XML expert, you can also create and run web services. ASMX is achieved by hiding most of the base XML and Web service details. Unlike the Forced Developer Direct Soap Envelope and Web Service Description Language (WSDL) file, ASMX introduces an automatic mapping layer to achieve a connection with traditional .NET code.
ASMX also is tightly integrated with popular ASP.NET HTTP pipelines. Therefore, it has the advantages of traditional ASP.NET web applications, such as advanced host environments and process models, reliable configuration and deployment options, and flexible extension points. As a result, ASMX is usually the first choice for most web service developers. Most developers mistakenly think that ASMX requires IIS; after all, they have seen this situation. But in fact, ASMX has no dependency and IIS in technology.
The need for housing main web services under conditions without IIS is very practical. In some environments, there may be various reasons to cause IIS on a computer that must be a host Web service. Fortunately, under the conditions without IIS, you can host ASMX in your process. This can be achieved since the .NET Framework 1.0 release, but you must provide your web server to receive HTTP requests. Cassini is an example web server developed by the ASP.NET team, which can meet this need and allow you to run the ASP page without IIS. However, for most developers, writing their own web servers or use sample web servers such as Cassini are unreasonable.
Since the release of Windows ServerTM 2003 and Windows® XP SP2, a new HTTP protocol stack appears, named http.sys. With some new hosted classes (especially httplistener) in http.sys and .NET Framework 2.0, you can easily build a web server for your application without having to install IIS on your computer. These progress make it possible to run ASMX in any environment. Please note that .NET Framework 2.0 is currently just a beta version, so there will be changed.
ASP.NET HTTP architecture
ASP.NET is specifically designed to avoid relying on IIS. The basic architecture is a line consisting of a .NET class that is incorporated into the incoming HTTP message. It is seen as a pipeline because each HTTP request has to pass a series of objects, and each object performs some processing.
The HTTPRuntime class is located at the front end of the pipeline, responsible for starting the process. When the static ProcessRequest method of the HTTPRuntime class is used, the line begins to execute. ProcessRequest has an HTTPWORKERREQUEST object that contains all information about the current request. HTTPRuntime uses information in httpWorkerRequest to populate httpcontext objects. It then instantizes the appropriate HTTPAppLication class, which calls any IHTTPModule implementations registered to the application for pre-processing or later processing. At this time, the appropriate IHTTPHANDLER implementation is identified. This process will happen every HTTP request that enters the pipeline. All ASP.NET features (including ASMX functions) are included in these line classes. For example, when the request arrives at the System.Web.Services.Protocols.WebServiceHandlerFactory class, it began to support the processing of the ASMX endpoint, which is responsible for identifying, compiling (if needed) and instantiate the ASMX class, and call incoming Soap message target webmedhod.
Figure 1 HTTP pipeline and web server
The pipeline is completely autonomous and IIS is independent of each other. Even when used with IIS, it is also running in a process with INetInfo.exe. The name of this process depends on the host OS (ASPNET_WP.EX on Windows XP, W3WP.exe on Windows Server 2003). In addition to their own process model, the pipeline has independent configuration, and is separated from the IIS metadata. The only wireless line is a web server that can be used to receive incoming HTTP requests. You still need some components that can listen to incoming HTTP messages, such as IIS 5.0 or http.sys. Even so, these components are only responsible for receiving HTTP requests and handing them to the ASP.NET pipeline, and anything will be processed by it (see Figure 1).
Once this request enters the auxiliary process, the auxiliary process creates an HTTPWORKERREQUEST object (indicating that the incoming request) and calls httpruntime.processRequest to start the line. Thanks to this reasonable design, you can call HttPruntime directly in your application.
Host HTTP pipeline
The class required by the host ASP.NET can be found in System.Web and System.Web.hosting namespace. The class that needs to be used at the beginning is mainly ApplicationHost, Httprise and a class derived from HttpWorkerRequest. First call ApplicationHost.createApplicationHost. This method newly creates an application domain (AppDomain) that can handle ASP.NET requests. Since you are explicitly created AppDomain, you must specify the virtual directory and the appropriate physical directory when calling.
In addition to creating new AppDomain, CreateApplicationHost is also instantified an object in this new AppDomain where you can communicate through this object. When the method is performed, you have to specify the type where you want to instantiate. Since this object will be used across the appdomain boundary, it must be derived from MarshalByrefObject. You may want to use your own class, which has the method you need to interact with AppDomain. For example, at least you want a ProcessRequest method, which can be submitted to the new ASP.NET request for processing. There is a class available here to implement this:
Public Class Mysimplehost: MarshalByrefObject: MarshalByrefObject
{
Public void processRequest (String file)
{
... // Use the asp.net http pipeline to process request
}
}
In this example, ProcessRequest accepts the file name of the page to be processed. In ProcessRequest, you can use HTTPRuntime to start the pipeline processing. HttPruntime has a static method, name is also called ProcessRequest, which has an HttpWorkerRequest type parameter.
HttpWorkerRequest is an abstract class, but fortunately, .Net comes with a simple, named SimpleWorkerRequest, which is intended to process simple HTTP GET requests. When you instantiate SimpleWorkerRequest, you must specify the name of the page you want to process, an optional query string and a TextWriter (the pipeline will write it). Once you have an HTTPWORKERREQUEST object, you can call the pipeline by calling ProcessRequest, as shown below:
... // MySIMPLEHOST.PROCESSREQUEST
SimpleWorkerRequest SWR =
New SimpleWorkerRequest (Page, Null, Console.out);
HTTPRUNTIME.PROCESSREQUEST (SWR);
For MySIMPLEHOST, you need to call ApplicationHost.createApplicationHost in the host application to instantiate this object. Then, you can send the request to the HTTP pipeline using mysimplehost.processRequest, as shown in the following code segment:
... // Console Host Application
MySIMPLEHOST MSH = (MySIMPLEHOST)
ApplicationHost.createApplicationHost (Typeof (MySIMPLEHOST), "/",
Directory.getcurrentDirectory ());
FOREACH (String Page In Args)
Msh.ProcessRequest (Page);
ApplicationHost.createApplicationHost's implementation is desirable to find a specified type of assembly in one of the following two locations: In the global assembly cache (GAC), or in the bin directory of the specified physical directory. Since there is no documentation, this reinforcement of CreateApplicationHost can be changed, so according to your project configuration and deployment scenario, you may need to install an assembly in it.
Figure 2 contains the code of the entire console application of the host ASP.NET. This example can be downloaded. You specify the name of the ASP.NET file in the command line and an optional query string. The program then passes them to the pipeline by calling mysimplehost.processRequest. In this column download, I have a few ASP.NET files for you to try, including a file called Math.asmx. When you run an application, specify "Math.asmx WSDL" in the command line, you will see the WSDL definition generated by the ASMX window (equivalent to Math.asmx in IIS) in the console window. Browse http://host/math.asmx? WSDL). If you specify "Math.asmx" only in the command line, it will print the readable document page generated by the ASMX.
This is obviously an unrealistic example because you must specify the ASP.NET page in the command line. In practical applications, this information is incorporated by HTTP. To support HTTP, you need to integrate a web server in your application.
IIS
Http.sys is a new low-level HTTP protocol stack that can be used in Windows Server 2003 and Windows XP SP2. Http.sys is a kernel mode component that provides its HTTP service for all applications in your computer. This means that HTTP support is deeply dependent on OS. Even IIS 6.0 also reform so that http.sys can be used (see Figure 3).
Figure 3 HTTP.SYS architecture
Before version 6.0, IIS relies on the TCP / IP kernel and the Windows Sockets API (Winsock) to receive HTTP requests. Since Winsock is a user mode component, each receiving operation needs to switch between kernel mode and user mode. Now http.sys can cache responses directly in the kernel. When the caching response is processed, the HTTP Stack is placed in the kernel, which allows the removable context to switch to the possible context to increase efficiency and overall throughput.
When http.sys receives the request, it can forward the request to the correct access to the correct process. In addition, if the auxiliary process cannot accept the request, http.sys stores the request until the auxiliary process starts and accepts it. This means that the auxiliary process fails does not interrupt the service. When IIS 6.0 is started, the WWW service communicates with Http.sys and registers routing information for each IIS application configured. WWW services will communicate with http.sys to update its routing information when creating an application or removing an application in IIS.
As you can see in Figure 3, http.sys lays the foundation for the IIS 6.0 web architecture, but it does not contact IIS in any way. Any application running in a computer can use http.sys to receive HTTP requests. Similar to WWW services, you can register your application with http.sys and start listening to incoming HTTP requests. The .NET Framework 2.0 introduces a hosted class that allows these managers to be easily implemented.
Httplistener: Realize your own web server
System.net contains several new classes used to interact with http.sys. Httplistener is a key one in these classes. It can be used to create a simple web server (or listener) that responds to incoming HTTP requests. This listener maintains active status within the survival of the HTTPListener object, but you can notify it to start and stop listening by command.
To use httplistener, you must instantiate it first. Then use the HTTP URL that the listener should process by adding a URL prefix to the Prefixes property. Each URI must contain a scheme ("http" or "https"), host, port (optional), and path (optional). Each prefix must be tail with a forward slash: httplistener listener = new httplistener ();
Listener.prefixes.add ("http: // localhost: 8081 / foo /");
Listener.prefixes.add ("http://127.0.0.1:8081/foo/);
Listener.start ();
For a specific URL prefix, there can be only one httplistener listens to it. If you try to add a copy, you will get Win32Exception. When you specify a port, you can replace the host name to "*" to indicate that the listener should process all the URIs with the port unless another HttPlistener matches them. Or can replace the host name to " " to indicate that the listener accepts all requests for the specified port, as shown below:
Httplistener Listener = new httplistener ();
Listener.prefixes.add ("http: // : 8081 /");
Listener.start ();
You can also specify the authentication scheme used by the listener via the AuthenticationScheme property. HTTPListener supports anonymity, basic, brief, and Windows authentication. It also supports a secure socket layer (SSL) connection, so basic authentication can be safely used by HTTPS, as shown below:
Httplistener Listener = new httplistener ();
Listener.authenticationschemes = AuthenticationsChemes.basic
Listener.prefixes.add ("https: // : 8081 /");
Listener.start ();
As you have just seen, once you specify the URI prefix to be processed, you must call the START method (note: At least one prefix must be added before calling START). Start does not really do what is important - it is just simply preparing listener objects to start receiving requests.
To receive a request, you must call getContext as shown below:
HttplistenerContext CTX = listener.getContext ();
GetContext is a synchronous call that blocks when the request is waiting to arrive. It will not return until a request is received. HTTPListener also provides an asynchronous reception request mechanism through beginTContext and endgetContext. GetContext and EndgetContext returns an HttPlistenerContext object that represents the received HTTP request.
You can use HTTPListener to integrate your own web server with the sample application shown in Figure 2. You need to do just forward the request from httplistener to the HTTP pipeline in your code. You can add a loop that continually calls getContext and uses the information in the returned HTTPListenerContext object to call the ProcessRequest. Then use the HTTPListenerContext class to find the requested file name (using the request.url.localpath property, such as "/math.asmx") and query strings (using the request.url.query property, such as "? WSDL"). With this code, you can request an ASP.NET page via HTTP, as shown in Figure 4. After making these changes and run the program, the console application starts waiting for GetContext to return. Now you can open a web browser and locate the registered URI (for example, http: // localhost: 8081 / math.asmx). After this operation is complete, getContext returns and submits the request to the HTTP pipeline. You should then look at the response of the write console window, as doing it earlier.
HTTPListenerContext is similar to HTTPContext, which provides the request, response, and user properties that interacts with all aspects of the HTTP message. The type of request attribute is httplistenerRequest, and the type of Response property is httplistenerResponse. HTTPListenerRequest is used to access requests HTTP methods, URLs, headers, user agents, mains, and other parts. HTTPListenerResponse is used to write an HTTP response to the client. The user property returns to IPrincipal, which has information about users through authentication.
You can use these properties to further extend this example so that it can write directly to the HTTP response stream. This can be implemented: Modify the signature of MySIMPLEHOST.PROCESSREQUEST to accept a TextWriter. Once is done, you can pack httplistenercontext.response.outputStream in the StreamWriter object and incorporated it.
Figure 6 Browser output
Figure 5 provides a complete code of the modified example, which integrates an HTTPListener. When you run an example, you can use a browser to read and locate the document page generated by the ASMX (see Figure 6). A message is printed in the console window each time the application receives a request (see Figure 7).
Figure 7 Console application output
This example demonstrates a host model that can handle HTTP GET requests and query strings. SimpleWorkerRequest is just designed for this simple condition, it cannot handle more advanced POST operations. Therefore, this example cannot completely host the host ASMX endpoint, and the ASMX endpoint needs to have POST support to process incoming SOAP requests.
Host Asmx
To fully support the ASMX endpoint, you need a custom HTTPWORKERREQUEST that knows how to handle request / response stream. It should be based on the HttplistenerContext object obtained from getContext. This is a very tricky task because HttpWorkerRequest is very large, and the document is not fully standardized. Therefore, I provided an example implementation called HTTPListenerWorkerRequest (shown in Figure 8). At this point, you may try back to the previous example and replace all instances of SimpleWorkerRequest to httplistenerWorkerRequest. However, doing this requires you to pass the HTTPListenerContext object to ProcessRequest. Unfortunately, httplistenerContext is not derived from MarshalByrefObject to prevent it from passing across the AppDomain boundary. To achieve this, you need to redesign this example.
First, you need a class that package the HTTPListener object and allows it to control across AppDomain. I have a class named httplistenerwrapper in Figure 9. This is the type you specified when you call CreateApplicationHost from now. It has a configure method that instantiates the included HTTPListener object and registers the URI prefixed. It has START and STOP methods, which simply entrusts the listener. It also has a ProcessRequest method to handle anything else - call getContext, instantiate new HttplistenerWorkerRequest, and incorporate it in HttPruntime.ProcessRequest, which processes the request. You can use the following classes in the host application:
HttplistenerWrapper Listener =
(Httplistenerwrapper) ApplicationHost.createApplicationHost
TypeOf (httplistenerwrapper), "/", directory.getcurrentdirectory ());
Listener.configure (Prefixes, "/", Directory.getCurrentDirectory ());
Listener.start ();
While (true) listener.processRequest ();
Now you have a full-featured host for the ASMX endpoint. There is another complete example of the provided download, which demonstrates the operation of this code. Now, when the console application runs, you should be able to use SOAP or to call ASMX WebMethods through the form provided by the HTML document page.
Host Model: Web Services on Desktop
Since you know how to host ASMX in the process of choice, now you want to know when you should use this technology. On a special computer, IIS cannot be run due to various situations, but you may still want to use the ASMX programming model to serve the host web service on this node. If this is this, the technology discussed in this column is a good choice.
Unlike inetinfo.exe (it provides many services for different communication types), http.sys is a simplified kernel, only processing HTTP traffic. So it has reduced the attack surface. If you have Windows XP SP2 or Windows Server 2003 on your computer, you can host ASMX in your own process without IIS. This means that you can host ASMX in the console application, Windows Form application, or Windows NT® service according to your specific needs. However, I should point out that when you use this method, you abandon the advanced process model provided by IIS through the W3WP.exe (or ASPNET_WP.exe) assist process. This means you have lost some functions such as process management (start, failure detection, recycling), thread pool management and ISAPI support. When you host ASMX, you provide this process, so you have to provide process models and related services.
Figure 10 Web services on the desktop
In your own process, host Asmx, the most attractive situation may be the case where you need to run a web service on your desktop. For example, you may have a Windows Form Application that requires notifications from a web server or other internal enterprise-wide Windows service (see Figure 10). On the desktop, you don't need to have a advanced process model as in the server, but it is still good to use ASMX's effective programming model. Http.sys and ASMX hosts are well suited for this situation. I have provided other examples in the download (a Windows Form Application and a Windows Service for Host Asmx) to clarify these concepts.
We are located
I introduced basic knowledge of host ASP.NET HTTP pipeline in the process of choice. Also discussed how to use http.sys and new HTTPListener managed classes (and related classes) to build a web server for your application. HTTPListener makes it easy to receive an HTTP message and forward them to the ASP.NET page for processing. With these technologies, you can run ASMX anywhere.
For more information on this topic, see "New Features for Web Service Developers in Beta 1 of the .NET Framework 2.0", "Http.sys Response Cache", and "Download ASP.NET CASSINI Sample Web Server".
Please send you the questions and comments you want to AARON to SSTATION@microsoft.com.
Aaron Skonnard is one of the founders of PluralSight (a family education and content creation company), which in this company mainly engaged in XML and Web service technology. He is senior editor of MSDN Magazine and has written several books, including Essential XML Quick Reference (Addison-Wesley, 2001). His contact information is www.pluralsight.com/aaron.
Go to the original English page