Search code examples
c#.netasp.nethttpmono

How to host a simple ASP.NET web interface in a Windows Services


For a simple appliance that runs on a Windows & .NET operating system, we need to create a simple configuration web interface to control it. Just like your router's configuration page, nothing more complicated than that.

Installing IIS or any other web server should be avoided, what we need is a self supporting process within a windows service on a basic windows XP installation + .NET.

Mono compatibility is a plus.

Thanks a million


Solution

  • Actually the easiest way is to use the built-in WCF stuff (.Net 3.5)... To do this you create a interface for your 'WCF' service that contains one or more methods that return Stream:

    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        [WebInvoke(UriTemplate = "/{*arguments}", Method="GET", BodyStyle=WebMessageBodyStyle.Bare)]
        Stream Get(string arguments);
    }
    

    You can define several methods and arguments and let WFC do the work, or as the example above, push everything into a single method. The resulting implementation can access the full Uri and query parameters as follows:

    public class ServiceType : IService
    {
        public Stream Get(string arguments)
        {
            UriTemplateMatch uriInfo = WebOperationContext.Current.IncomingRequest.UriTemplateMatch;
            WebOperationContext.Current.OutgoingResponse.ContentType = "text/html";
    
            MemoryStream rawResponse = new MemoryStream();
            TextWriter response = new StreamWriter(rawResponse, Encoding.UTF8);
            response.Write("<html><head><title>Hello</title></head><body>");
            response.Write("<b>Path</b>: {0}<br/>", arguments);
            response.Write("<b>RequestUri</b>: {0}<br/>", uriInfo.RequestUri);
            response.Write("<b>QueryParameters</b>: {0}<br/>", uriInfo.QueryParameters.ToString());
            response.Write("</body></html>");
            response.Flush();
    
            rawResponse.Position = 0;
            return rawResponse;
        }
    }
    

    Now all you have to do is start up the WCF web/http self-host ...

    static void Main()
    {
        Uri baseAddress = new Uri("http://localhost:8000/");
        WebServiceHost svcHost = new WebServiceHost(typeof(ServiceType));
    
        ServiceEndpoint svcEndpoint = svcHost.AddServiceEndpoint(typeof(IService),
          new WebHttpBinding(), baseAddress);
        svcEndpoint.Behaviors.Add(new WebHttpBehavior());
    
        svcHost.Open();
        Console.WriteLine("Press enter to quit...");
        Console.ReadLine();
    
        svcHost.Close();
    }
    

    NOTE: for the above example to work on Vista/Win7 you need to grant permissions with the following command-line:

    netsh http add urlacl url=http://+:8000/ user=DOMAIN\USER