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é: 6 040 / 187

Note :
Aucune note

Commentaire sur cette source (13)
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
            {
                //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

Conclusion


Vous pouvez faire un copier/coller d'une de vos WebApp ASPNET 2.0 dans cet exemple et tester si ca fonctionne.
Normalement tout fonctionne sauf les redirections en fin de traitement PostBack (auquel je m'attaquerais surement dans les semaines à venir...).

Faites moi un commentaire si vous détecter un BUG.

Si quelqu'un réussit à améliorer le code qu'il n'hésite pas à m'en faire part ou à poster sa nouvelle source sur le site.


 

Fichier Zip

Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip

Historique

12 mai 2008 12:35:00 :
MAJ: 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).
16 mai 2008 08:01:49 :
MAJ V4: J'ai ajouter quelques fonctionnalités indispensables : - Gestion des sous-repertoires de la WebApp (dont App_GlobalRessources) - Gestion des fichiers Non-ASP (images, css, html)

Commentaires et avis

signaler à un administrateur
Commentaire de godvicien le 07/05/2008 11:50:50

Arf. J'ai complètement oublier de dire que ce code ne fonctionne pas sous Windows Vista, qui bloque l'utilisation du HttpListener, visiblement pour des question de sécurité. Il doit y avoir un bout de code à rajouter pour cela fonctionne sous Vista, mais lequel ??

Si quelqu'un trouve la solution pour faire marcher cet exemple sous Vista, je pourrai être très gratifiant (je serais même prêt à payer, c'est vous dire).

De même si quelqu'un trouve la solution pour faire fonctionner cet exemple avec Firefox...

signaler à un administrateur
Commentaire de wizad le 07/05/2008 12:12:42

Voici une bonne explication de la chose : http://channel9.msdn.com/ShowPost.aspx?PostID=334866

signaler à un administrateur
Commentaire de sebmafate le 07/05/2008 14:37:49 administrateur CS

Je n'accroche pas à ce genre de projet... en fait, la raison pour laquelle les applications ASP.Net se répendent en entreprise, ce n'est pas le design, car il est possible de faire des trucs très sympa, très clair, très lisible, très puissant,... en Windows Forms. Non : c'est la maintenance !
Quand tu dois mettre à jour un site intranet, tu interviens sur 1 serveur IIS (voire plus si c'est une ferme)... Dans ton cas, tu perds complètement cet avantage.

Quant aux applications Windows Forms... il est de plus en plus rare de voir une base Access (quand bien même ce soit une tare), on trouve du SqlServer Express, du MSDE2000 (oui encore) voire du SqlServer Compact.

En tout cas, je ne suis pas prêt de changer une application Windows Forms par une pseudo application Web locale. (Surtout que maintenant ClickOnce gomme la contrainte du déploiement)

signaler à un administrateur
Commentaire de godvicien le 08/05/2008 10:50:32

Alors, tu n'échangerais pas ton baril de WinForms contre mon baril de WebForms, sans même avoir essayé ?
Je crois que pour dire ca tu n'as pas de clients à satisfaire, ou alors tu es un pro des WinForms. Car, pour mon application, la skin de base est une WinForm, et à chaque fois c'est la même remballe : C'est condensé, riche, complexe, bref peu-lisible pour quelqu'un  qui n'a pas été spécialement formé à l'interface.

La philosophie d'un client lourd ou client riche, à base de WinForms, est d'être très puissant en offrant un maximum de fonctionnalités sur chaque formulaire. Mon formulaire principale cumule les fonctions de :
- champs de recherches
- listings de résultats
- consultation de fiches
- création de fiches
Tout ca sur le même formulaire, alors qu'en WebApp il y aurait une page par fonctionnalité. Pour être franc les WinForms ont vite tendance à devenir de véritables usines à gaz qui concentrent trop de fonctionnalités. Les utilisateurs de base ne sont pas habitués à autant de fonctionnalités, ils préfèrent une navigation claire par page dans un navigateur Web. Je n'ai pas l'intention de former tous mes utilisateurs donc je décide de me lancer dans l'aventure...

Au fait je précise que malgrès l'utilisation des Visual Express 2008 le projet est compilé pour le Framework .Net 2.0, donc il est possible d'ouvrir les fichiers solution du projet avec Visual Studio 2005 en changeant simplement la version de ces fichiers .sln (textes).

Si vous recompilez le tout n'oubliez pas de mettre une copie de ServerLocalASPNET.exe (ou .dll) dans le dossier /bin/ de l'application, car c'est la que cherchera la fonction de création du Host Server. Il doit y trouver la classe 'ServerLocalASPNET'.

signaler à un administrateur
Commentaire de sebmafate le 08/05/2008 13:03:17 administrateur CS

En fait... les apparances sont parfois trompeuses... 99% de boulot consiste en la conception et la réalisation d'applications en WebForms !
Mais, j'ai aussi une très bonne culture du WinForms.

Maintenant, chacun ses choix. Mais pour moi, quitte à avoir une application à déployer sur _chaque_ poste, autant que ce soit du Windows Forms : pour la puissance, la souplesse et la robustesse.

signaler à un administrateur
Commentaire de Warny le 08/05/2008 21:13:35

seb -> si l'exemple présenté ici n'est pas le plus pertinent, ce code reste interressant.
En effet, si tu programme un service, par définition sans interface, il peut être interessant, voire très pertinent, d'exposer une interface web pour le piloter.
Et puis n'oublions pas qu'une célebre application de p2p (eMule) peut exposer  du web pour être contrôlée à distance.
Il existe même un antivirus d'entreprise (officescan) dans laquelle les clients exposent un service web pour être contactés par le serveur pour être notifiés des mises à jour importantes.
Même dans une application de gestion, on pourrait imaginer une interface qui permette à l'administrateur de vérifier le bon fonctionnement du programme client, de vérifier l'état de la machine, d'installer ou de désinstaller des programmes ou des modules à distance...
Tout ça pour dire que la technique qui est présentée ici est interressante, ce qui compte ensuite, c'est de lui trouver une application, ce qui, et je le conçois parfaitement, n'entre pas dans le périmètre de la majorité des applications.

signaler à un administrateur
Commentaire de billou_13 le 09/05/2008 09:51:33

Bonjour,

Le débat est fort intéressant et pourrait durer un bon moment: peut-on mélanger client lourd/client léger ?
Pour ma part, je pense que non pour les même raisons que Sebmafate. Un client lourd a ses avantages fortement appréciables. Néanmoins, il est vrai que les entreprises (du moins, basé sur mon expérience) ont tendance à faire route vers des clients légers (comme disait Seb: plus appréciable pour leur côté maintenance).
Mais je ne pense vraiment pas que ce soit le côté graphique et interface qui rebutent les gens à utiliser les logiciels client lourd.

Enfin tout ça pour dire que l'intérêt de ce code n'est pas moindre. Il m'intéresse beaucoup et, faute à moi de ne pas télécharger tous les codes du site, il fera partie de la rare liste de code que j'aurais téléchargé sur code source afin de le dépouiller. Il m'apprendra certainement beaucoup de choses dans ma courte expérience du .Net.
Et pour cela (ne pas avoir laisser dormir le code sur ton ordi sans jamais le poster), je t'en remercie GodVicien

Bonne journée,


Billou_13


PS: Et n'oubliez pas, avant de s'occuper de supprimer les clients lourds, faudrait surement penser à s'occuper de la communauté JAVA d'abord ^^

signaler à un administrateur
Commentaire de godvicien le 12/05/2008 14:44:33

@Warny: Exact ! On peut tout a fait concevoir une interface d'administration à distance (par internet) du client lourd.

J'ai fais le teste à l'instant, ca fonctionne en réseau local (pas essayé par internet). Il suffit d'indiquer l'ip de la machine sur le formulaire de la V3. Le serveur écoute alors tout les requêtes du réseau. Reste qu'il me semble que les box-internet modernes masquent l'ip de la machine sur internet. Faut donc faire quelques testes.

J'ai donc mis à jour la source pour vous donner la version finale qui intègre une dll (ServerASPNET.dll) qu'il faut simplement placer dans le répertoire /bin/ de votre WebApp. Et d'instancier ensuite la classe 'ServerASPNET' dans votre client lourd.

Vous pouvez maintenant mettre une note à mon code...

signaler à un administrateur
Commentaire de godvicien le 16/05/2008 08:08:38

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)


A part ca j'ai découvert que l'on pouvait débuguer la WebApp avec ce server comme pour une WebApp sous IIS.
C'est magique, il suffit d'inserer un point d'arret dans une page web.

signaler à un administrateur
Commentaire de godvicien le 17/05/2008 13:29:56

Je viens de d?couvrir un gros bug : ce system ne g?n?re pas le code 'AutoPostBack' des controls serveur ASP.

Pourquoi ? Myst?re ...

signaler à un administrateur
Commentaire de godvicien le 17/05/2008 18:28:03

Voici le code correctif qu'il faut ajouter ? chaque page aspx qui utilise des controls avec AutoPostBack,
a mettre dans le code-behind de la page :

    /// <summary>
    /// Override: nothing.
    /// </summary>
    /// <param name="control"></param>
    public override void VerifyRenderingInServerForm(Control control)
    {
        //nothing
    }
    /// <summary>
    /// Override: call Render_WithAutoPostBack().
    /// </summary>
    /// <param name="htmlWriterResponse"></param>
    protected override void Render(HtmlTextWriter htmlWriterResponse)
    {
        this.Render_WithAutoPostBack(htmlWriterResponse);

    }
    /// <summary>
    /// Render the html of the page with AutoPostBack events.
    /// </summary>
    /// <param name="htmlWriterResponse"></param>
    protected void Render_WithAutoPostBack(HtmlTextWriter htmlWriterResponse)
    {
        //TODO: update the list of YOUR controls that have the AutoPostBack properties
        Control[] controlsWithAutoPostBack =
            new Control[] { this.ddlSemanticLangs };

        //make a new htmlTextWriter on a stringWriter
        StringWriter stringWriter = new StringWriter();
        HtmlTextWriter htmlTextWriter = new HtmlTextWriter(stringWriter);
        //render the page
        base.Render(htmlTextWriter);
        htmlTextWriter.Flush();
        string html = stringWriter.ToString();

        //add inputs hidden for AutoPostBack function
        html = html.Replace("<input type=\"hidden\" name=\"__VIEWSTATE\" id=\"__VIEWSTATE",
            "<input type=\"hidden\" name=\"__EVENTTARGET\" id=\"__EVENTTARGET\" value=\"\" />\n" +
            "<input type=\"hidden\" name=\"__EVENTARGUMENT\" id=\"__EVENTARGUMENT\" value=\"\" />\n" +
            //"<input type=\"hidden\" name=\"__LASTFOCUS\" id=\"__LASTFOCUS\" value=\"\" />\n" +
            "<script type=\"text/javascript\">\n" +
            "   var theForm = document.forms['aspnetForm'];\n" +
            "   if (!theForm) {\n" +
            "       theForm = document.aspnetForm;\n" +
            "   }\n" +
            "function __doPostBack(eventTarget, eventArgument) {\n" +
            "   if (!theForm.onsubmit || (theForm.onsubmit() != false)) {\n" +
            "       theForm.__EVENTTARGET.value = eventTarget;\n" +
            "       theForm.__EVENTARGUMENT.value = eventArgument;\n" +
            "       theForm.submit();\n" +
            "   }\n" +
            "}\n" +
            "</script>\n" +
            "<input type=\"hidden\" name=\"__VIEWSTATE\" id=\"__VIEWSTATE");

        //loop to treat each control with AutoPostBack
        foreach (Control control in controlsWithAutoPostBack)
        {
            //get render of the control
            StringWriter strWriter = new StringWriter();
            HtmlTextWriter htmlWriter = new HtmlTextWriter(strWriter);
            control.RenderControl(htmlWriter);
            htmlWriter.Flush();
            string htmlControl = strWriter.ToString();
            //get id of the control
            XmlDocument xmlControl = new XmlDocument();
            xmlControl.LoadXml(htmlControl);
            string idControl = "id=\"" + xmlControl.DocumentElement.Attributes["id"].Value + "\"";
            //build onchange function
            string onchange = "onchange=\"javascript:setTimeout('" + this.GetPostBackEventReference(control).Replace("'", "\\'") + "', 0)\"";
            //affect in html
            html = html.Replace(idControl, idControl + " " + onchange);

        }//next control

        //write html in the response
        htmlWriterResponse.WriteLine(html);

    }


Comme vous pouvez le voir il suffit de mettre a jour la liste des controls qui utilisent le AutoPostBack au d?but de la fonction Render_WithAutoPostBack().

signaler à un administrateur
Commentaire de lamzilichakib le 02/12/2008 19:12:14

Est ce que l'application peut ferme l'IE lors de stop?

//disable stop
this.btnStopServer.Enabled = false;
//close page
_ServerASPNET.CloseBrowserOnWebApp();
//stop the server
_ServerASPNET.StopThread_ServerASPNET();
//enable start
this.btnStartServer.Enabled = true;

signaler à un administrateur
Commentaire de Warny le 02/12/2008 22:27:26

Non, bien sûr. Le protocole http se déconnecte de son serveur dès que la page a fini d'être téléchargée (ce n'est pas tout à fait vrai mais rien ne transite du serveur vers le client sans demande du client) et il n'existe aucune commande http pour fermer un navigateur distant.

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

[ASP.NET 2.0] activation des extension de service Web dans IIS [ par Verrisan ] Bonjour tout le monde, Dans le gestionnaire des services Internet (IIS), dans la rubrique "Externsion du service Web", j'ai "ASP.NET v2.0.50215" et d ASP.NET et IIS ??!!! [ par patoche92 ] Bonjour à tous et à toutes.Je suis confronté à un grave problème : Je n'arrive pas à faire tourner ASP.NET.....J'ai installé IIS qui fonctionne très b pb avec outlook [ par Jula ] recoucou,voilà, j'ai un problème en essayant d'utiliser msoutl9:je fais au début:msoutl9.Application objOutlook = new msoutl9.ApplicationClass();et à ASP.NET + héritage de classe [ par Volfield ] Bonjour, J'ai fait une classe Conf qui hérite de la classe Page.Le problème c'est que quand je fais mes autres pages qui hérite de Conf, il ne connais MessageBox et asp.Net [ par danounouche ] Bonjour je voudrai savoir comment affichier une fenetre du style MessageBox a partir d'une forme asp.net...Qualqu'un aurait-il une idee? asp.net+c#+fichier [ par Volfield ] Je cherche à downloader des fichiers à partir d'un formulaire avec une balise &lt;input type="file" name="monfichier"&gt;Avant je faisais du php et je ASP.net+c#+générer un pdf [ par Volfield ] Bonjour, je réalise un site en asp.net(c#) et je cherche une librairie de préférence gratuite qui génère des fichiers pdf.Est-ce que cela existe? Si o C# J# VB.Net et ASP.Net [ par isoz ] Bonjour!Je cherche à m'amuser un peu avec visual studio .Net. Pour cela, j'essaie de créer une solution (*.sln) contenent un projet C# (*.cproj) ayant Installation d'IIS ... [ par maevacmoi ] Hello !J'ai un fichier d'installation .msi, qui contient mon application C#.net. Lors de l'exécution de ce fichier, il demande l'installation du frame tableau en c# [ par aurelie ] J'aimerais savoir si il est possible en c# de créer un tableau, où on peut déterminer la valeur que l'on souhaite passer en index. Je voudrais faire l


Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Téléchargements

Logiciels à télécharger sur le même thème :

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,452 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.