2014-12-01 7 views
18

Ich habe eine voll funktionsfähige ASP.NET MVC-Anwendung (bestehend aus 5 Assemblys, .NET 4.5.1, ASP.NET MVC 5.2.2), die in Visual Studio (welches IISExpress benutzt).Self-Host von ASP.NET MVC-Anwendung

Ich möchte jetzt eine Konsolenanwendung haben, die die MVC-Anwendung übernimmt und sie hostet (Self-Hosting).

Ich versuchte mit Microsoft.Owin.Host.HttpListener und Nancy.Owin aber während ich 404 Seiten bekomme, fehlt meinen Konfigurationen die Zuordnung zu meiner MVC-App.

Ich habe

public class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     app.UseNancy(); 
    } 
} 

und

static void Main(string[] args) 
    { 
     StartOptions so = new StartOptions("http://localhost:9000/"); 
     using (WebApp.Start<Startup>(so)) 
     { 
      Console.WriteLine("Press Enter to Exit"); 
      Console.ReadLine(); 
     } 
    } 

Aber offensichtlich die Konfiguration MyMvcApplication aus der laufenden MVC-Anwendung zu verwenden, fehlt. Wie geht das? Oder wie kann man es sonst selbst hosten?

Die Antworten, die ich im Web gefunden habe, beziehen sich auf ältere Versionen und ich hoffte, heute einen einfacheren Weg zu haben.

+2

Soweit ich jetzt erforscht dies vor ASP.NET nicht möglich sein wird, 5 (vNext; MVC 6) und meine Anwendung mit nancy Hosting erfordert von ASP.NET zu migrieren MVC zu Nancy (die auch Razor Template-Engine verwenden könnte). Richtig? – ZoolWay

+2

Wie oben können Sie MVC nicht "selbst hosten", und Nancy ist ein völlig anderes Web-Entwicklungs-Framework als MVC - es ist keine alternative Möglichkeit, MVC zu hosten und Sie können sie nicht einfach so zusammenmischen. –

+0

Die Frage ist dann, ob es etwas anderes gibt, das sich selbst hostet, oder ob MVC5 einfach IIS-Hosting benötigt, ohne eine Umgehungslösung. – ZoolWay

Antwort

12

Da ASP.NET vNext noch nicht verfügbar ist und meine App MVC5 verwendet, müsste ich die MVC App komplett zu Nancy oder ähnlichem migrieren. MVC5 ist zu abhängig von IIS.

dieses mittlerweile ich auf eine Zwischenlösung entschieden zu lösen, wie die Leistung ist kein Problem:

Meine Konsole app eine IIS-Konfigurationsdatei erstellt und startet eine IIS Express:

 // start IIS 
     bool systray = Debugger.IsAttached; 
     ProcessStartInfo psi = new ProcessStartInfo(iisExecutable, String.Format("/config:\"{0}\" /site:Ecm2.Web /trace:info /systray:{1}", configFile, systray)); 
     psi.UseShellExecute = false; 
     psi.RedirectStandardInput = false; 
     psi.RedirectStandardOutput = true; 
     psi.RedirectStandardError = true; 
     psi.CreateNoWindow = true; 

     if (this.iisProcess != null) throw new NotSupportedException("Multiple starts not supported"); 
     this.iisProcess = new Process(); 
     this.iisProcess.StartInfo = psi; 
     this.iisProcess.ErrorDataReceived += OnErrorDataReceived; 
     this.iisProcess.OutputDataReceived += OnOutputDataReceived; 
     this.iisProcess.Start(); 
     this.iisProcess.BeginErrorReadLine(); 
     this.iisProcess.BeginOutputReadLine(); 

Wenn jemand möchte Teil des Fragments „Stop“, das ist:

 if (this.iisProcess == null) throw new Exception("Does not look like there was something started yet!"); 

     if (this.iisProcess.HasExited) 
     { 
      log.WarnFormat("IIS has already exited with code '{0}'", this.iisProcess.ExitCode); 
      this.iisProcess.Close(); 
      return; 
     } 

     log.InfoFormat("Stopping IIS instance #{0}", this.instanceId); 
     ProcessCommunication.SendStopMessageToProcess(this.iisProcess.Id); 
     bool exited = this.iisProcess.WaitForExit(30000); 
     if (!exited) 
     { 
      log.WarnFormat("Failed to stop IIS instance #{0} (PID {1}), killing it now", this.instanceId, this.iisProcess.Id); 
      this.iisProcess.Kill(); 
     } 

     this.iisProcess.Close(); 

um den iis Prozess zu stoppen gewöhnlichen Sie WM_QUIT es senden soll. Dies könnte für diese hilfreich sein:

/// <summary> 
    /// Sends a WM_QUIT message to another process. 
    /// </summary> 
    /// <param name="pid">PID of the other process</param> 
    public static void SendStopMessageToProcess(int pid) 
    { 
     log.DebugFormat("Sending stop message to PID #{0}", pid); 
     try 
     { 
      for (IntPtr ptr = NativeMethods.GetTopWindow(IntPtr.Zero); ptr != IntPtr.Zero; ptr = NativeMethods.GetWindow(ptr, 2)) 
      { 
       uint num; 
       NativeMethods.GetWindowThreadProcessId(ptr, out num); 
       if (pid == num) 
       { 
        HandleRef hWnd = new HandleRef(null, ptr); 
        NativeMethods.PostMessage(hWnd, 0x12, IntPtr.Zero, IntPtr.Zero); 
        return; 
       } 
      } 
     } 
     catch (ArgumentException ex) 
     { 
      log.Error(String.Format("Failed to send WM_QUIT to PID #{0}", pid), ex); 
     } 
    } 

    /// <summary> 
    /// Provides the native methods to post messages to other windows processes. 
    /// </summary> 
    internal class NativeMethods 
    { 
     // Methods 
     [DllImport("user32.dll", SetLastError = true)] 
     internal static extern IntPtr GetTopWindow(IntPtr hWnd); 
     [DllImport("user32.dll", SetLastError = true)] 
     internal static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd); 
     [DllImport("user32.dll", SetLastError = true)] 
     internal static extern uint GetWindowThreadProcessId(IntPtr hwnd, out uint lpdwProcessId); 
     [DllImport("user32.dll", SetLastError = true)] 
     internal static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam); 
    } 
+0

Nun, warum nicht auch stdinput umleiten und senden 'Q', um es anmutig zu stoppen. Dann können Sie auf HasExited warten und den Prozess trotzdem stoppen, wenn dies fehlschlägt. –

Verwandte Themen