Опубликован: 11.05.2007 | Доступ: свободный | Студентов: 1598 / 158 | Оценка: 4.36 / 4.25 | Длительность: 16:06:00
Дополнительный материал 2:

Приложение II. Использование ASP.NET без IIS

Ключевые слова: ASP, net, IIS, Windows, server, Размещение, файл

Приложение II. Использование ASP.NET без IIS

В учебном процессе или при тестировании приложений иногда возникает потребность работы с веб службами ASP.NET без использования IIS. При использовании .NET Framework 2.0 и операционной системы Windows XP SP2 или Windows Server 2003 можно достаточно просто создать свой носитель веб служб на основе классов HttpListener и HttpRuntime, при этом служба IIS может быть не установлена в системе. Далее приведен пример простого класса, позволяющего осуществлять размещение приложений ASP.NET в учебных целях.

// SevaAspHost.cs
using System;
using System.IO;
using System.NET;
using System.Web;
using System.Web.Hosting;
using System.Text.RegularExpressions;

namespace Seva.AspHost
{
    public class AspHost: MarshalByRefObject
    {
        private HttpListener listener;
            
        private string virtualDir;
        private string hostingDir;
            
        public string VirtualDir
        {
            get {return virtualDir;}
        }
        
        public string HostingDir
        {
            get {return hostingDir;}
        }
            
        public static AspHost CreateHost(string[] prefixes, string aspVirtualDir, 
            string aspHostingDir)
        {            
            if (!HttpListener.IsSupported)
            {
                throw new NotSupportedException(
                    "Требуется Windows XP SP2/Server 2003.");
            }            
            AspHost host = (AspHost) ApplicationHost.CreateApplicationHost(
                typeof(AspHost), aspVirtualDir, aspHostingDir);            
            host.Init(prefixes, aspVirtualDir,  aspHostingDir);           
            return host;
        }

        public void Init(string[] prefixes, string aspVirtualDir, 
            string aspHostingDir)
        {                                
            virtualDir = aspVirtualDir;
            hostingDir = aspHostingDir;
            listener = new HttpListener();

            foreach (string prefix in prefixes)
                listener.Prefixes.Add(prefix);
        }
        
        public void Start()
        {
            listener.Start();
        }

        public void Stop()
        {
            listener.Stop();
        }
        
        public void ProcessRequest()
        {
            HttpListenerContext context = listener.GetContext();
         
            HttpListenerWorkerRequest workerRequest =
                new HttpListenerWorkerRequest(context, this);
            
            HttpRuntime.ProcessRequest(workerRequest);            
        }
    }
    
    public class HttpListenerWorkerRequest: HttpWorkerRequest 
    {
        private HttpListenerContext context;
        private AspHost host;
        
        
        public HttpListenerWorkerRequest(HttpListenerContext listenerContext, 
                AspHost aspHost)
        {
            context = listenerContext;
            host = aspHost;
        }
        
        public override void EndOfRequest()
        {
            context.Response.OutputStream.Close();
            context.Response.Close();
        }

        public override void FlushResponse(bool finalFlush)
        {
            context.Response.OutputStream.Flush();
        }

        public override string GetHttpVerbName()
        {
            return context.Request.HttpMethod;
        }

        public override string GetHttpVersion()
        {
            return string.Format("HTTP/{0}",
                context.Request.ProtocolVersion.ToString());
        }
        
        public override string GetLocalAddress()
        {
            return context.Request.LocalEndPoint.Address.ToString();
        }
        
        public override int GetLocalPort()
        {
            return context.Request.LocalEndPoint.Port;
        }
        
        public override string GetQueryString()
        {            
            return context.Request.Url.Query.TrimStart(new char[]{'?'});
        }
        
        public override string GetRawUrl()
        {
            return context.Request.RawUrl;
        }
        
        public override string GetRemoteAddress()
        {
            return context.Request.RemoteEndPoint.Address.ToString();
        }
        
        public override int GetRemotePort()
        {
            return context.Request.RemoteEndPoint.Port;
        }
        
        public override string GetUriPath()
        {
            return context.Request.Url.LocalPath;
        }
        
        public override void SendKnownResponseHeader(int index, string value)
        {
            context.Response.Headers[GetKnownResponseHeaderName(index)] = value;
        }
        
        public override void SendResponseFromMemory(byte[] data, int length)
        {
            context.Response.OutputStream.Write(data, 0, length);
        }
        
        public override void SendStatus(int statusCode, string statusDescription)
        {
            context.Response.StatusCode = statusCode;
            context.Response.StatusDescription = statusDescription;
        }
        
        public override void SendUnknownResponseHeader(string name, string value)
        {
            context.Response.Headers[name] = value;
        }
        
        public override void SendResponseFromFile(IntPtr handle, long offset, 
            long length) 
        {
        }
        
        public override void SendResponseFromFile(string filename, long offset,
            long length) 
        { 
        }

        public override string GetAppPath()
        {
            return host.VirtualDir;
        }
        
        public override string GetAppPathTranslated()
        {
            return host.HostingDir;
        }              
        
        public override string GetUnknownRequestHeader(string name)
        {
            return context.Request.Headers[name];
        }
        
        public override string GetKnownRequestHeader(int index)
        {
            switch (index)
            {
                case HeaderUserAgent:
                    return context.Request.UserAgent;
                default:
                    return        
                        context.Request.Headers[GetKnownRequestHeaderName(index)];
            }
        }
        
        public override string GetFilePath()
        {
            string s = context.Request.Url.LocalPath;
            Regex re = new Regex(@"^(.*\.as\wx)\/\w+$");                 
            Match m = re.Match(s); 
            if (m.Success) 
                s = m.Groups[1].Value;           
            return s;
        }
        
        public override string GetFilePathTranslated()
        {
            string s = GetFilePath().Substring(host.VirtualDir.Length);
            return host.HostingDir + s.Replace('/', '\\');
        }

        public override string GetPathInfo()
        {
            return context.Request.Url.LocalPath.Substring(GetFilePath().Length);
        }
        
        public override int ReadEntityBody(byte[] buffer, int size)
        {
            return context.Request.InputStream.Read(buffer, 0, size);
        }
    }
}
Листинг II.1.

Далее приведен пример использования этого класса, позволяющий хранить ASP страницы в поддиректории www и обращаться к ним по локальным адресам и порту 8080.

// AspServer.cs
using System;
using System.IO;

using Seva.AspHost;

class Program
{
    static void Main(string[] args)
    {
        
        string[] prefixes = new string[] 
        {
            "http://localhost:8080/", "http://127.0.0.1:8080/"
        };

        AspHost host = AspHost.CreateHost(prefixes, "/", 
            Directory.GetCurrentDirectory()+@"\www");
                    
        host.Start();
        
        foreach (string s in prefixes)
            Console.WriteLine(s);
        
        while (true)
            host.ProcessRequest();
    }
}

Используемый при вызове метода ApplicationHost.CreateApplicationHost тип (в данном случае – AspHost ) должен находиться, как один из вариантов, в глобальной сборке. Далее приводится make файл для создания простейшего носителя ASP.NET.

all: ASPServer.exe

ASPServer.exe: *.cs AspHost.dll
    csc /out:ASPServer.exe AspServer*.cs /r:AspHost.dll

AspHost.dll: SevaAspHost.cs AspHost.key
    csc /out:ASPHost.dll /t:library SevaAspHost.cs /keyfile:AspHost.key

AspHost.key:
    sn -k AspHost.key

install:
    gacutil -i ASPHost.dll
    if not exist www md www

После команды nmake && nmake install в поддиректорию www можно помещать страницы ASP.NET с расширениями aspx и asmx.