Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

WEB SKIN : CRÉEZ UNE INTERFACE ASPNET POUR VOTRE CLIENT LOURD DOTNET SANS IIS. HÉBERGEMENT INTERNE DE WEBAPP.


Information sur la source

Catégorie :.NET Source .NET ( DotNet ) Classé sous : webskin, webapp, client lourd, iis, asp Niveau : Initié Date de création : 07/05/2008 Date de mise à jour : 16/05/2008 08:01:47 Vu / téléchargé: 4 469 / 114

Note :
Aucune note

Commentaire sur cette source (11)
Ajouter un commentaire et/ou une note

Description

Cliquez pour voir la capture en taille normale
Vous en rêviez : Un client lourd DotNet peut héberger une WebApp complète sans avoir à installer IIS sur chaque poste.

Imaginez. Souvent, en entreprise, le schéma classique consiste en une base de donnée hébergée à l'entreprise, et des applications dites 'clients lourds' installées chez les commerciaux ou les clients. Généralement ces 'clients lourds' sont développés à l'aide d'une base Access, et avec une interface utilisateur constituée de WinForms (si ce n'est parfois directement en VBA).

Problème : Les interfaces à base de WinForm sont généralement laides, condensées, complexes, et incompréhensible pour un néophyte bien plus habitué à naviguer dans des interfaces Web. Je vous propose ici LA solution : Créer une 'WebSkin' à votre affreux 'client lourd' pour le rendre plus digeste à vos commerciaux ou clients. Profitez de la puissance de ASP.Net pour réaliser une interface claire, basée sur les pages qui pourront être données à de vrais Web Designers.

Grand habitué de csharpfr.com, ayant souvent trouvé des sources intéréssantes pour mes applications, sur ce sujet que je savais possible, je n'ai malheureusement trouvé aucune source. J'ai donc décidé de retrousser mes manches et de m'y coller moi-même. Je vous livre le résultat d'une petite semaine de travail, largement aidé par le livre référence "Pratique de .Net 2 et C#" de Patrick Smacchia, que je ne saurais que trop conseiller à tous les développeurs C#.

Cet exemple est réalisé avec Visual C# 2008 Express, et Visual Web Developper 2008 Express.

Cette technique est extrêmement puissante et permet d'héberger simplement la totalité d'une WebApp ASP.Net sur chaque poste ou est installée le 'client lourd', accessible en localhost sans connexion internet. On obtient donc une application déconnectée de la base entreprise, mais consultable localement en mode déconnecté à travers une belle interface Web.

Il y a un BUG sous Windows Vista qui bloque le HttpListener pour des questions de sécurités. Il doit y avoir un bout de code à rajouter pour que ca fonctionne sous Vista, mais lequel ? J'ai chercher un peu sur le web mais je n'ai rien trouvé.

Je ne suis pas Web Developper (bien que je vais devoir m'y mettre) donc l'exemple de la WebApp fournie est très sommaire. Juste pour vérifier que la technique fonctionne. A ce propos le code qui ne semble pas marcher, et c'est logique puisqu'on se passe de IIS, est la redirection de la page à la fin d'un traitement :
this.Response.Redirect("Welcome.aspx");//BUG in Local Server ASPNET

Il faut donc feinter et inclure une fonction javascript dans la page retournée à la fin du traitement qui fait la redirection directement depuis le browser de l'utilisateur. Le code ci-dessus est alors remplacé par :
//use body.onLoad
HtmlGenericControl body = this.FindControl("body") as HtmlGenericControl;
body.Attributes["onLoad"] = "RedirectWelcome()"; //nom de la fonction javascript

Laquelle fonction javascript est écrite directement dans la page aspx :
<script language="javascript" type="text/javascript">
function RedirectWelcome() {
    window.location = "Welcome.aspx";
}
</script>

Voilà l'astuce. Pour le reste tout semble fonctionner normalement (avec IE).

Bonne lecture, et bon tests...

MAJ V2 V3:

J'ai du intégrer cette exemple dans mon application, et pour cela j'ai du revoir tout le code de l'exemple. J'ai donc fais une V2 et une V3, dont le résultat est une dll bien pratique qui doit être insérée dans le dossier /bin/ de votre WebApp. Puis il suffit d'implémenter la classe 'ServerASPNET' qui encapsule toute la complexité du fonctionnement du server ASPNET local. On peut même instancier plusieur 'ServerASPNET', un pour chaque WebApp, et ainsi constituer une ferme de WebApp. A partir de la pourquoi pas redevelopper un serveur Web complet compatible ASPNET ?  

En particulier il doit être possible de pallier le BUG de redirection à la fin d'un traitement (voir le code).

MAJ V4:

J'ai ajouté quelques fonctionnalités indispensables :
- Gestion des sous-repertoires de la WebApp (dont App_GlobalRessources)
- Gestion des fichiers Non-ASP (images, css, html)

 

Source

  • using System;
  • using System.IO;
  • using System.Net;
  • using System.Text.RegularExpressions;
  • using System.Threading;
  • using System.Web;
  • using System.Web.Hosting;
  • using System.Windows.Forms;
  • namespace Peerocracy.PAPICS.Client.Beta0.Skin
  • {
  • /// <summary>
  • /// Class ServerASPNET that can start a thread for a Server ASPNET.
  • /// This can process one WebApp.
  • /// This can be closed to stop http listening.
  • /// </summary>
  • public class ServerASPNET : IDisposable
  • {
  • #region Properties
  • /// <summary>
  • /// Return true if the ServerASPNET is running.
  • /// </summary>
  • public bool IsStarted
  • {
  • get { return _isStarted; }
  • }
  • private bool _isStarted = false;
  • /// <summary>
  • /// The full path to the WebApp.
  • /// The WebApp must have a /bin/ folder that contains this dll.
  • /// </summary>
  • public string WebAppPath
  • {
  • get { return _WebAppPath; }
  • set
  • {
  • //check if not already started
  • if (this.IsStarted)
  • {
  • this.ConsoleWrite("Error: Cannot change Path of WebApp until server stopped.");
  • return;
  • }
  • //null value
  • if (value == null || !new DirectoryInfo(value).Exists)
  • {
  • this.ConsoleWrite("Error: the given WebAppPath folder not exist.");
  • return;
  • }
  • //affect
  • _WebAppPath = value;
  • }
  • }
  • private string _WebAppPath = null;
  • /// <summary>
  • /// The name of WebApp.
  • /// Use to build the URI to listen : http://IptoListen:PortToListen/WebAppName/.
  • /// </summary>
  • public string WebAppName
  • {
  • get { return _WebAppName; }
  • set
  • {
  • //check if not already started
  • if (this.IsStarted)
  • {
  • this.ConsoleWrite("Error: Cannot change Name of WebApp until server stopped.");
  • return;
  • }
  • //null value
  • if (value == null || value.Length == 0)
  • {
  • this.ConsoleWrite("Error: the given WebAppName is null.");
  • return;
  • }
  • //affect
  • _WebAppName = value;
  • }
  • }
  • private string _WebAppName = "WebAppName";
  • /// <summary>
  • /// This is the address IP to listen.
  • /// Use to build the URI to listen : http://IptoListen:PortToListen/WebAppName/.
  • /// Must be : 'localhost' or the public IP of this station.
  • /// See GetIPHostStation().
  • /// </summary>
  • public string IPtoListen
  • {
  • get { return _IPtoListen; }
  • set
  • {
  • //check if not already started
  • if (this.IsStarted)
  • {
  • this.ConsoleWrite("Error: Cannot change IP to listen until server stopped.");
  • return;
  • }
  • //null value
  • if (value == null || value.Length == 0)
  • value = "localhost";
  • //affect
  • _IPtoListen = value;
  • }
  • }
  • private string _IPtoListen = "localhost";
  • /// <summary>
  • /// This is the port of this station to listen http request.
  • /// Use to build the URI to listen : http://IptoListen:PortToListen/WebAppName/.
  • /// </summary>
  • public int PortToListen
  • {
  • get { return _PortToListen; }
  • set
  • {
  • //check if not already started
  • if (this.IsStarted)
  • {
  • this.ConsoleWrite("Error: Cannot change Port to listen until server stopped.");
  • return;
  • }
  • //null value
  • if (value <= 0) return;
  • //affect
  • _PortToListen = value;
  • }
  • }
  • private int _PortToListen = 8008;
  • /// <summary>
  • /// Define the URI to listen : http://IptoListen:PortToListen/WebAppName/.
  • /// Set: fill the properties : _IPtoListen, _PortToListen, _WebAppName.
  • /// </summary>
  • public string URItoListen
  • {
  • get
  • {
  • return "http://" + _IPtoListen + ":" + _PortToListen + "/" + _WebAppName + "/";
  • }
  • set
  • {
  • //null value
  • if (value == null || !value.StartsWith("http://"))
  • return;
  • //regex.Match
  • Match matchURI = new Regex(@"^http://(?'IPtoListen'[^:/]*):(?'PortToListen'[^/]*)/(?'WebAppName'.*?)/$", RegexOptions.Compiled).Match(value); ;
  • //affect properties
  • this.IPtoListen = matchURI.Groups["IPtoListen]"].Value;
  • this.PortToListen = Int32.Parse(matchURI.Groups["PortToListen"].Value);
  • this.WebAppName = matchURI.Groups["WebAppName"].Value;
  • }
  • }
  • /// <summary>
  • /// The thread that contains the _HostProcessor_ASPNET.
  • /// Init by fct StartThread_ServerASPNET().
  • /// </summary>
  • public Thread Thread_ServerASPNET
  • {
  • get { return _Thread_ServerASPNET; }
  • }
  • private Thread _Thread_ServerASPNET = null;
  • /// <summary>
  • /// Class of the host _HostProcessor_ASPNET.
  • /// Init by fct StartThread_ServerASPNET().
  • /// </summary>
  • public HostProcessorASPNET HostProcessor_ASPNET
  • {
  • get { return _HostProcessor_ASPNET; }
  • }
  • private HostProcessorASPNET _HostProcessor_ASPNET = null;
  • #endregion
  • #region Ctors
  • /// <summary>
  • /// Ctor, nothing.
  • /// </summary>
  • public ServerASPNET()
  • {
  • _timerUpdateConsoleProcessor = new System.Windows.Forms.Timer();
  • _timerUpdateConsoleProcessor.Interval = 1000; //1sec
  • _timerUpdateConsoleProcessor.Tick += new EventHandler(this.timerUpdateConsoleProcessor_Tick);
  • }
  • /// <summary>
  • /// Ctor with given uriToListen, and webAppPath.
  • /// </summary>
  • /// <param name="uriToListen">The URI to listen http requests.</param>
  • /// <param name="webAppPath">The full path of the WebApp.</param>
  • public ServerASPNET(string uriToListen, string webAppPath)
  • : this()
  • {
  • //affect
  • this.URItoListen = uriToListen;
  • this.WebAppPath = webAppPath;
  • }
  • /// <summary>
  • /// Ctor with given uriToListen, and webAppPath, and rtfConsole.
  • /// </summary>
  • /// <param name="uriToListen">The URI to listen http requests.</param>
  • /// <param name="webAppPath">The full path of the WebApp.</param>
  • /// <param name="rtfConsole">The RichTextBox control of the console.</param>
  • public ServerASPNET(string uriToListen, string webAppPath, RichTextBox rtfConsole)
  • : this(uriToListen, webAppPath)
  • {
  • //affect
  • this.ConsoleRtf = rtfConsole;
  • }
  • #endregion
  • #region Functions
  • /// <summary>
  • /// Return the list of the address IP of this Host Station.
  • /// </summary>
  • /// <returns>One string for each IP.</returns>
  • public string[] GetIPHostStation()
  • {
  • //get IPs
  • IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());
  • //make new string[]
  • string[] IPs = new string[ips.Length];
  • //fill new string[]
  • for (int i = 0; i < ips.Length; i++)
  • IPs[i] = ips[i].ToString();
  • //return
  • return IPs;
  • }
  • /// <summary>
  • /// Start the ServerASPNET.
  • /// Start a new background thread for the function fctRunThread_ServerASPNET.
  • /// </summary>
  • public void StartThread_ServerASPNET()
  • {
  • //check if not closed
  • if (_isDisposed) return;
  • //check if not already started
  • if (this.IsStarted)
  • {
  • this.ConsoleWrite("Local Server ASPNET already started !");
  • return;
  • }
  • //check if given WebApp path
  • if (_WebAppPath == null || !new DirectoryInfo(_WebAppPath).Exists)
  • throw new Exception("Error: Cannot start until given the path of WebAppPath property.");
  • //check if given WebApp name
  • if (_WebAppName == null || _WebAppName.Length == 0)
  • throw new Exception("Error: Cannot start until given the name of WebAppName property.");
  • //make new background thread
  • _Thread_ServerASPNET = new Thread(this.RunThread_ServerASPNET);
  • _Thread_ServerASPNET.IsBackground = true;
  • //start thread
  • _Thread_ServerASPNET.Start();
  • //wait for started
  • while (!this.IsStarted)
  • {
  • Application.DoEvents();
  • Thread.Sleep(10);
  • }
  • //console
  • if (this.ConsoleRtf != null)
  • _strConsoleBeforeConsoleProcessor = this.ConsoleRtf.Text;
  • _timerUpdateConsoleProcessor.Start();
  • }
  • /// <summary>
  • /// Stop the ServerASPNET.
  • /// Stop the thread of the ServerASPNET.
  • /// </summary>
  • public void StopThread_ServerASPNET()
  • {
  • //check if not closed
  • if (_isDisposed) return;
  • //check if server already stopped
  • if (!this.IsStarted)
  • {
  • this.ConsoleWrite("Local Server ASPNET already stopped !");
  • return;
  • }
  • try
  • {
  • //stop listening
  • _HostProcessor_ASPNET.StopHttpListening();
  • //_HostProcessor_ASPNET = null;
  • }
  • catch (Exception err)
  • { }
  • //abort thread
  • _Thread_ServerASPNET.Abort();
  • //_Thread_ServerASPNET = null;
  • _isStarted = false;
  • //console
  • _timerUpdateConsoleProcessor.Stop();
  • this.UpdateConsoleFromProcessor();
  • this.ConsoleWrite("Stop: Server Aborted !");
  • }
  • /// <summary>
  • /// Run the ServerASPNET.
  • /// Call by fct StartThread_ServerASPNET();
  • /// Exec in new thread.
  • /// </summary>
  • private void RunThread_ServerASPNET()
  • {
  • //check if not closed
  • if (_isDisposed) return;
  • //console
  • //this.ConsoleClean();
  • this.ConsoleWrite("Start new Server ASPNET threaded on this station,");
  • this.ConsoleWrite(" for URI to listen : '" + this.URItoListen + "'.");
  • this.ConsoleWrite(" for WebApp : '" + _WebAppPath + "'.");
  • //search the dll containing the class 'HostProcessorASPNET'
  • //search in '_WebAppPath/bin/*.dll|exe'
  • _HostProcessor_ASPNET =
  • (HostProcessorASPNET)ApplicationHost.CreateApplicationHost(
  • typeof(HostProcessorASPNET), @"/", _WebAppPath); //BUG if not found this dll in '_WebAppPath/bin'
  • ////subscribe on events
  • ////BUG: because different 'Domain Application'.
  • //_HostProcessor_ASPNET.OnConsoleChanged +=
  • // new HostProcessorASPNET.ConsoleChangedEventHandler(_HostProcessor_ASPNET_OnConsoleChanged);
  • //_HostProcessor_ASPNET.OnIsStartedChanged +=
  • // new HostProcessorASPNET.IsStartedChangedEventHandler(_HostProcessor_ASPNET_OnIsStartedChanged);
  • //start http listening : lost control
  • this.ConsoleWrite("OK: Server ASPNET is started.");
  • //_strConsoleBeforeConsoleProcessor = this.ConsoleRtf.Text;
  • _isStarted = true;
  • _HostProcessor_ASPNET.StartHttpListening(this.URItoListen, this.WebAppPath);
  • //never reach
  • return;
  • }
  • //void _HostProcessor_ASPNET_OnIsStartedChanged(object sender, EventArgs args)
  • //{
  • // _isStarted = _HostProcessor_ASPNET.IsStarted;
  • //}
  • //void _HostProcessor_ASPNET_OnConsoleChanged(object sender, ConsoleChangedEventArgs args)
  • //{
  • // this.ConsoleWrite(args.NewLineText);
  • //}
  • /// <summary>
  • /// Start a new IE browser on the default page of the running WebApp.
  • /// </summary>
  • public void StartBrowserOnWebApp()
  • {
  • this.StartBrowserOnWebApp(null, true);
  • }
  • /// <summary>
  • /// Start a new browser on the given page of the running WebApp.
  • /// </summary>
  • /// <param name="page">The name of the page to show.</param>
  • /// <param name="isIEBrowser">True for open IE browser, or false for default browser.</param>
  • public void StartBrowserOnWebApp(string page, bool bIEBrowser)
  • {
  • //check if closed
  • if (_isDisposed) return;
  • //check if started
  • if (!this.IsStarted) return;
  • //null value
  • if (page == null) page = "";
  • //search page
  • if (page.StartsWith("/"))
  • page = page.Substring(1);
  • if (!page.StartsWith("http://"))
  • page = this.URItoListen + page;
  • //if start in IE
  • if (bIEBrowser)
  • {
  • //show in new Process: IE
  • string iexplore = Path.Combine(Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles"),
  • "Internet Explorer"), "iexplore.exe");
  • System.Diagnostics.Process.Start(iexplore, page);
  • return;
  • }
  • //show in new process: DefaultBrowser
  • System.Diagnostics.Process.Start(page);
  • return;
  • }
  • #endregion
  • #region Console Membres
  • /// <summary>
  • /// Internal timer to update the console from Processor.
  • /// </summary>
  • private System.Windows.Forms.Timer _timerUpdateConsoleProcessor;
  • /// <summary>
  • /// Update the console from the Processor.
  • /// </summary>
  • private void timerUpdateConsoleProcessor_Tick(object sender, EventArgs e)
  • {
  • if (!_isStarted) return;
  • this.UpdateConsoleFromProcessor();
  • }
  • /// <summary>
  • /// Update the console from the Processor.
  • /// </summary>
  • private void UpdateConsoleFromProcessor()
  • {
  • if (_isDisposed) return;
  • //null value
  • if (_rtfConsole == null) return;
  • //check if invoke is required
  • if (_rtfConsole.InvokeRequired)
  • {
  • //not same thread: invoke
  • dlgUpdateConsoleFromProcessor Delegate = new dlgUpdateConsoleFromProcessor(this.UpdateConsoleFromProcessor);
  • _rtfConsole.Invoke(Delegate);
  • }
  • //test if differents
  • else if (_rtfConsole.Text != _strConsoleBeforeConsoleProcessor + _HostProcessor_ASPNET.Console)
  • {
  • //same thread: affect
  • _rtfConsole.Text = _strConsoleBeforeConsoleProcessor + _HostProcessor_ASPNET.Console;
  • }
  • }
  • /// <summary>
  • /// Delegate to synchronous threads on function UpdateConsoleFromProcessor().
  • /// </summary>
  • private delegate void dlgUpdateConsoleFromProcessor();
  • /// <summary>
  • /// Define the RichTextBox console of the server.
  • /// </summary>
  • public RichTextBox ConsoleRtf
  • {
  • get { return _rtfConsole; }
  • set
  • {
  • _rtfConsole = value;
  • }
  • }
  • private RichTextBox _rtfConsole = null;
  • /// <summary>
  • /// This string contains the console state before the consoleProcessor.
  • /// </summary>
  • private string _strConsoleBeforeConsoleProcessor = "";
  • /// <summary>
  • /// fctCleanConsole: ThreadSafe: Clean the text of the rtfConsole control.
  • /// </summary>
  • public void ConsoleClean()
  • {
  • if (_isDisposed) return;
  • //null value
  • if (_rtfConsole == null) return;
  • //check if invoke is required
  • if (_rtfConsole.InvokeRequired)
  • {
  • //not same thread: invoke
  • dlgConsoleClean Delegate = new dlgConsoleClean(this.ConsoleClean);
  • _rtfConsole.Invoke(Delegate);
  • }
  • else
  • {
  • //same thread: affect
  • _rtfConsole.Text = "";
  • }
  • }
  • /// <summary>
  • /// Delegate to synchronous threads on function ConsoleClean().
  • /// </summary>
  • private delegate void dlgConsoleClean();
  • /// <summary>
  • /// fctWriteConsole: ThreadSafe: Write given text to rtfConsole control.
  • /// </summary>
  • /// <param name="text">Text line to write in console control.</param>
  • public void ConsoleWrite(string text)
  • {
  • if (_isDisposed) return;
  • //null value
  • if (_rtfConsole == null) return;
  • if (text == null) text = "";
  • //show in rtfConsole
  • if (_rtfConsole.InvokeRequired)
  • {
  • //not same thread: invoke
  • dlgConsoleWrite Delegate = new dlgConsoleWrite(this.ConsoleWrite);
  • _rtfConsole.Invoke(Delegate, new object[] { text });
  • }
  • else
  • {
  • //new line char
  • if (!text.EndsWith("\n"))
  • text += "\n";
  • //same thread: affect
  • _rtfConsole.Text += text;
  • }
  • }
  • /// <summary>
  • /// Delegate to synchronous threads on function ConsoleWrite().
  • /// </summary>
  • private delegate void dlgConsoleWrite(string text);
  • #endregion
  • #region IDisposable Membres
  • /// <summary>
  • /// True if this is disposed or closed.
  • /// </summary>
  • private bool _isDisposed = false;
  • /// <summary>
  • /// Idem as Dispose().
  • /// </summary>
  • public void Close()
  • {
  • this.Dispose();
  • }
  • /// <summary>
  • /// Close the http listening properly and abort the thread.
  • /// </summary>
  • public void Dispose()
  • {
  • //check if already disposed
  • if (_isDisposed) return;
  • //dispose with managed ressources
  • this.Dispose(true);
  • //GC dont call finalizer of this
  • GC.SuppressFinalize(this);
  • }
  • /// <summary>
  • /// Finalizer: dispose but managed ressources.
  • /// </summary>
  • ~ServerASPNET()
  • {
  • this.Dispose(false);
  • }
  • /// <summary>
  • /// Internal: Dispose.
  • /// </summary>
  • /// <param name="isDisposeManagedRessources"></param>
  • protected virtual void Dispose(bool isDisposeManagedRessources)
  • {
  • //check if already disposed
  • if (_isDisposed) return;
  • //set disposed
  • _isDisposed = true;
  • //dispose unmanaged ressources
  • this.StopThread_ServerASPNET();
  • if (isDisposeManagedRessources)
  • {
  • //dispose managed ressources
  • _HostProcessor_ASPNET = null;
  • _Thread_ServerASPNET = null;
  • _rtfConsole = null;
  • }
  • }
  • #endregion
  • }//class
  • /// <summary>
  • /// This class treat each http request from browser in function of given URI to listen.
  • /// </summary>
  • public class HostProcessorASPNET : MarshalByRefObject, IDisposable
  • {
  • #region Properties
  • /// <summary>
  • /// Return true if the processor is started and listening http requests.
  • /// </summary>
  • public bool IsStarted
  • {
  • get { return _IsStarted; }
  • }
  • private bool _IsStarted = false;
  • /// <summary>
  • /// Event on IsStarted changed.
  • /// BUG: cannot subscribe bacause different 'Application Domain'.
  • /// </summary>
  • public event IsStartedChangedEventHandler OnIsStartedChanged;
  • public delegate void IsStartedChangedEventHandler(object sender, EventArgs args);
  • /// <summary>
  • /// Return the URI to listen http requests.
  • /// Format : http://IptoListen:PortToListen/WebAppName/.
  • /// </summary>
  • public string URItoListen
  • {
  • get { return _URItoListen; }
  • //set ?
  • }
  • private string _URItoListen = null;
  • /// <summary>
  • /// Memorize the WebApp name.
  • /// </summary>
  • private string _WebAppName = null;
  • /// <summary>
  • /// Internal path to the WebApp directory.
  • /// </summary>
  • private string _PathWebApp = null;
  • /// <summary>
  • /// Internal HttpListener.
  • /// </summary>
  • private HttpListener _HttpListener = null;
  • /// <summary>
  • /// Internal Regex to find no ASP files.
  • /// </summary>
  • private Regex _rgxNoAspFile;
  • #endregion
  • #region Functions
  • /// <summary>
  • /// Stop the HttpListener properly. Set to null.
  • /// </summary>
  • public void StopHttpListening()
  • {
  • //check if closed
  • if (_isDisposed) return;
  • //check if started
  • if (!_IsStarted) return;
  • //stop HttpListener
  • _HttpListener.Stop();
  • _HttpListener.Abort();
  • _HttpListener = null;
  • //isStarted
  • _IsStarted = true;
  • this.ConsoleWrite("");
  • this.ConsoleWrite("Stop: HttpListening aborted !");
  • }
  • /// <summary>
  • /// Start the http listening on the given uriToListen.
  • /// </summary>
  • /// <param name="uriToListen">The URI to listen : http://IptoListen:PortToListen/WebAppName/.</param>
  • public void StartHttpListening(string uriToListen, string pathWebApp)
  • {
  • //check if closed
  • if (_isDisposed) return;
  • this.ConsoleClean();
  • //check if started
  • if (_IsStarted)
  • {
  • this.ConsoleWrite("Error: HostProcessorASPNET already started.");
  • return;
  • }
  • //check WebApp path
  • if (!new DirectoryInfo(pathWebApp).Exists)
  • {
  • this.ConsoleWrite("Error: Cannot find the WebApp path : '" + pathWebApp + "'.");
  • return;
  • }
  • //affect
  • _PathWebApp = pathWebApp;
  • //build _rgxNoAspFile //TODO
  • _rgxNoAspFile = new Regex(@"\.(gif|jpe?g?|png|tiff?|css|html?)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
  • //check uriToListen
  • if (uriToListen == null || !uriToListen.StartsWith("http://"))
  • {
  • this.ConsoleWrite("Error: URI to listen dont start with 'http://'.");
  • return;
  • }
  • _URItoListen = uriToListen;
  • //get _WebAppName
  • _WebAppName = new Regex(@"^https?://[^:/]*:?[^/]*/(?'WebAppName'.*?)/$")
  • .Match(_URItoListen).Groups["WebAppName"].Value;
  • //create new HttpListener
  • _HttpListener = new HttpListener();
  • //add uri to listen.
  • _HttpListener.Prefixes.Add(_URItoListen);
  • try
  • {
  • //start the listener
  • _HttpListener.Start();
  • }
  • catch (HttpListenerException err)
  • {
  • //TODO find exception on Vista
  • if (err.ErrorCode == 404) //HACK find exception on Vista
  • //error on windows vista
  • this.ConsoleWrite("Error Cause Windows Vista : Cant start the 'HttpListener' class.");
  • else
  • //error on windows xp
  • this.ConsoleWrite("Error: Cant start the 'HttpListener' class.");
  • this.ConsoleWrite("WinErr: " + err.ToString());
  • return;
  • }
  • //show started
  • this.ConsoleWrite("OK: 'HttpListener' Started and now listen http requests.");
  • _IsStarted = true;
  • if (this.OnIsStartedChanged != null)
  • this.OnIsStartedChanged(this, new EventArgs());
  • //start the global loop to treat each request from browser
  • this.RunHttpListening();
  • //never reach
  • }
  • /// <summary>
  • /// Internal: global loop to treat each request from browser.
  • /// </summary>
  • private void RunHttpListening()
  • {
  • //start the global loop to treat each request from browser
  • while (true) //to quit: _HttpListener.Abort()
  • {
  • //get httpContext from _HttpListener
  • HttpListenerContext httpContext;
  • try
  • {
  • //wait for http request from browser : lost constrol
  • this.ConsoleWrite("");
  • this.ConsoleWrite(" 'HttpListener' wait for http request from browser ...");
  • Application.DoEvents();
  • httpContext = _HttpListener.GetContext(); //to quit: _HttpListener.Abort()
  • Application.DoEvents();
  • }
  • catch (HttpListenerException err)
  • {
  • //if aborted
  • this.ConsoleWrite(" 'HttpListener' waiting aborted !");
  • this.ConsoleWrite(" Err: " + err.ToString());
  • return;
  • }
  • //get name of the page to show without '/WebAppName/'
  • string page = httpContext.Request.Url.LocalPath.Substring(1);
  • //delete '/WebAppName/'
  • if (page.StartsWith(_WebAppName))
  • page = page.Substring(_WebAppName.Length + 1);
  • //set default page if null
  • if (page.Length == 0)
  • page = "default.aspx";
  • //get query of the request
  • string query = httpContext.Request.Url.Query;
  • //add POSTed data in the body of request
  • if (httpContext.Request.HasEntityBody)
  • {
  • //read the content of the 'HTML form inputs' as a string
  • Stream streamFormInputs = httpContext.Request.InputStream;
  • StreamReader readerFormInputs = new StreamReader(streamFormInputs, httpContext.Request.ContentEncoding);
  • string sFormInputs = readerFormInputs.ReadToEnd();
  • readerFormInputs.Close();
  • streamFormInputs.Close();
  • //add to query
  • query += (query.Length != 0 ? "&" : "") + sFormInputs;
  • }
  • //show in console
  • string text = "/" + _WebAppName + "/" + page + (query.Length != 0 ? "?" + query : "");
  • this.ConsoleWrite(" Http Request received : '" + text + "'");
  • //get file relativ path
  • string file = page.Replace('/', '\\');
  • //treat App_GlobalResources
  • if (file.Contains("App_GlobalResources"))
  • file = file.Substring(file.IndexOf("App_GlobalResources"));
  • //treat no ASP files
  • if (_rgxNoAspFile.IsMatch(file))
  • {
  • //get full path file
  • string pathFile = Path.Combine(_PathWebApp, file);
  • //check if exist
  • if (!new FileInfo(pathFile).Exists)
  • {
  • //if no exist : close response
  • httpContext.Response.Close();
  • continue;
  • }
  • //open a FileStream
  • FileStream streamFile;
  • try
  • {
  • streamFile = new FileStream(pathFile, FileMode.Open);
  • }
  • catch (Exception err)
  • {
  • this.ConsoleWrite("Error: Opening FileStream to file : '" + pathFile + "'.");
  • continue;
  • }
  • //get streamResponse
  • Stream streamResponse = httpContext.Response.OutputStream;
  • //make new buffer
  • int bufferLength = 512;
  • Byte[] buffer = new Byte[bufferLength];
  • //read the file
  • int bytesRead = streamFile.Read(buffer, 0, bufferLength);
  • while (bytesRead > 0)
  • {
  • //write in the response
  • streamResponse.Write(buffer, 0, bytesRead);
  • //read the file
  • bytesRead = streamFile.Read(buffer, 0, bufferLength);
  • }
  • //close the streams
  • streamFile.Close();
  • httpContext.Response.OutputStream.Flush();
  • httpContext.Response.Close();
  • continue;
  • }
  • //new writer unicode
  • StreamWriter writerResponse = new StreamWriter(httpContext.Response.OutputStream,
  • System.Text.Encoding.Unicode);
  • //call ProcessRequest
  • this.ProcessRequest(file, query, writerResponse);
  • //close the response
  • try
  • {
  • writerResponse.Flush();
  • writerResponse.Close();
  • httpContext.Response.Close();
  • }
  • catch (Exception err)
  • {
  • }
  • }//while
  • //never reach
  • }
  • /// <summary>
  • /// Process to the full ASPNET response from the given fields.
  • /// </summary>
  • /// <param name="fileName">The name of the file to process.</param>
  • /// <param name="query">The full query of the http request.</param>
  • /// <param name="writerResponse">The writer of the response.</param>
  • public void ProcessRequest(string fileName, string query, TextWriter writerResponse)
  • {
  • //check if not closed
  • if (_isDisposed) return;
  • //check if started
  • if (!_IsStarted) return;
  • //create new aspnetWorker
  • SimpleWorkerRequest aspnetWorker = new SimpleWorkerRequest(fileName, query, writerResponse);
  • //process to the full ASPNET response
  • HttpRuntime.ProcessRequest(aspnetWorker);
  • //TODO chercher des fonctionnalités avec F1
  • //peut-être est-il possible d'implementer une fonctionnalité de redirection ?
  • //if (aspnetWorker.IsClientConnected)
  • //{
  • // string mapPath = aspnetWorker.MapPath();
  • // aspnetWorker.
  • //}
  • //send the response to client
  • aspnetWorker.FlushResponse(true);
  • }
  • #endregion
  • #region Console
  • /// <summary>
  • /// Return the text of the console.
  • /// </summary>
  • public string Console
  • {
  • get { return _strConsole; }
  • }
  • private string _strConsole = null;
  • /// <summary>
  • /// Event on Console text changed.
  • /// BUG: because different 'Application Domain'.
  • /// </summary>
  • public event ConsoleChangedEventHandler OnConsoleChanged;
  • public delegate void ConsoleChangedEventHandler(object sender, ConsoleChangedEventArgs args);
  • /// <summary>
  • /// Clean the text of the console.
  • /// Call by a new HttpListening.
  • /// </summary>
  • private void ConsoleClean()
  • {
  • //affect
  • _strConsole = "";
  • if (this.OnConsoleChanged != null)
  • this.OnConsoleChanged(this, new ConsoleChangedEventArgs(null));
  • }
  • /// <summary>
  • /// Write given line to the console.
  • /// </summary>
  • /// <param name="text">Text line to write in console control.</param>
  • private void ConsoleWrite(string text)
  • {
  • //null value
  • if (text == null) text = "";
  • //new line char
  • if (!text.EndsWith("\n"))
  • text += "\n";
  • //affect
  • _strConsole += text;
  • if (this.OnConsoleChanged != null)
  • this.OnConsoleChanged(this, new ConsoleChangedEventArgs(text));
  • }
  • #endregion
  • #region IDisposable Membres
  • /// <summary>
  • /// True if this is disposed/closed, and cannot function.
  • /// </summary>
  • private bool _isDisposed = false;
  • /// <summary>
  • /// Idem that Dispose();
  • /// </summary>
  • public void Close()
  • {
  • this.Dispose();
  • }
  • /// <summary>
  • /// Stop the _HttpListener properly. _HttpListener = null;
  • /// </summary>
  • public void Dispose()
  • {
  • //check if already disposed
  • if (_isDisposed) return;
  • //dispose with managed ressources
  • this.Dispose(true);
  • //Garbage Collector dont call finalizer of this
  • GC.SuppressFinalize(this);
  • }
  • /// <summary>
  • /// Finalizer: dispose but managed ressources.
  • /// </summary>
  • ~HostProcessorASPNET()
  • {
  • this.Dispose(false);
  • }
  • /// <summary>
  • /// Internal: Stop the HttpListener properly.
  • /// </summary>
  • /// <param name="isDisposeManagedRessources">Internal: true to annul HttpListener.</param>
  • protected virtual void Dispose(bool isDisposeManagedRessources)
  • {
  • //check if already disposed
  • if (_isDisposed) return;
  • //set disposed
  • _isDisposed = true;
  • //dispose unmanaged ressources
  • this.StopHttpListening();
  • if (isDisposeManagedRessources)
  • {
  • //dispose managed ressources
  • _HttpListener = null;
  • }
  • }
  • #endregion
  • }//class HostProcessorASPNET
  • /// <summary>
  • /// The EventArg for the event OnConsoleChanged.
  • /// </summary>
  • public class ConsoleChangedEventArgs : EventArgs
  • {
  • /// <summary>
  • /// The new line added to the console.
  • /// Is null if console is cleaned.
  • /// </summary>
  • public string NewLineText
  • {
  • get { return _NewLineText; }
  • }
  • private string _NewLineText = null;
  • /// <summary>
  • /// Ctor, init the EventArg with given newLineText.
  • /// </summary>
  • /// <param name="newLineText">The new line added to the console.</param>
  • public ConsoleChangedEventArgs(string newLineText)
  • {
  • //affect
  • _NewLineText = newLineText;
  • }
  • }//class ConsoleChangedEventArgs
  • }//namespace
using System;
using System.IO;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using System.Web.Hosting;
using System.Windows.Forms;

namespace Peerocracy.PAPICS.Client.Beta0.Skin
{
    /// <summary>
    /// Class ServerASPNET that can start a thread for a Server ASPNET.
    /// This can process one WebApp.
    /// This can be closed to stop http listening.
    /// </summary>
    public class ServerASPNET : IDisposable
    {

        #region Properties


        /// <summary>
        /// Return true if the ServerASPNET is running.
        /// </summary>
        public bool IsStarted
        {
            get { return _isStarted; }
        }
        private bool _isStarted = false;

        /// <summary>
        /// The full path to the WebApp.
        /// The WebApp must have a /bin/ folder that contains this dll.
        /// </summary>
        public string WebAppPath
        {
            get { return _WebAppPath; }
            set
            {
                //check if not already started
                if (this.IsStarted)
                {
                    this.ConsoleWrite("Error: Cannot change Path of WebApp until server stopped.");
                    return;
                }
                //null value
                if (value == null || !new DirectoryInfo(value).Exists)
                {
                    this.ConsoleWrite("Error: the given WebAppPath folder not exist.");
                    return;
                }
                //affect
                _WebAppPath = value;
            }
        }
        private string _WebAppPath = null;

        /// <summary>
        /// The name of WebApp.
        /// Use to build the URI to listen : http://IptoListen:PortToListen/WebAppName/.
        /// </summary>
        public string WebAppName
        {
            get { return _WebAppName; }
            set
            {
                //check if not already started
                if (this.IsStarted)
                {
                    this.ConsoleWrite("Error: Cannot change Name of WebApp until server stopped.");
                    return;
                }
                //null value
                if (value == null || value.Length == 0)
                {
                    this.ConsoleWrite("Error: the given WebAppName is null.");
                    return;
                }
                //affect
                _WebAppName = value;
            }
        }
        private string _WebAppName = "WebAppName";

        /// <summary>
        /// This is the address IP to listen.
        /// Use to build the URI to listen : http://IptoListen:PortToListen/WebAppName/.
        /// Must be : 'localhost' or the public IP of this station.
        /// See GetIPHostStation().
        /// </summary>
        public string IPtoListen
        {
            get { return _IPtoListen; }
            set
            {
                //check if not already started
                if (this.IsStarted)
                {
                    this.ConsoleWrite("Error: Cannot change IP to listen until server stopped.");
                    return;
                }
                //null value
                if (value == null || value.Length == 0)
                    value = "localhost";
                //affect
                _IPtoListen = value;
            }
        }
        private string _IPtoListen = "localhost";

        /// <summary>
        /// This is the port of this station to listen http request.
        /// Use to build the URI to listen : http://IptoListen:PortToListen/WebAppName/.
        /// </summary>
        public int PortToListen
        {
            get { return _PortToListen; }
            set
            {
                //check if not already started
                if (this.IsStarted)
                {
                    this.ConsoleWrite("Error: Cannot change Port to listen until server stopped.");
                    return;
                }
                //null value
                if (value <= 0) return;
                //affect
                _PortToListen = value;
            }
        }
        private int _PortToListen = 8008;

        /// <summary>
        /// Define the URI to listen : http://IptoListen:PortToListen/WebAppName/.
        /// Set: fill the properties : _IPtoListen, _PortToListen, _WebAppName.
        /// </summary>
        public string URItoListen
        {
            get
            {
                return "http://" + _IPtoListen + ":" + _PortToListen + "/" + _WebAppName + "/";
            }
            set
            {