c# asp.net-mvc owin nancy self-hosting

c# - Auto-anfitrión de la aplicación MVC ASP.NET



asp.net-mvc owin (1)

Como ASP.NET vNext aún no está disponible y mi aplicación utiliza MVC5, tendría que migrar la aplicación MVC completamente a Nancy o algo similar. MVC5 es demasiado dependiente de IIS.

Para resolver este problema, me decidí por una solución intermedia, ya que el rendimiento no es un problema:

La aplicación de mi consola crea un archivo de configuración de IIS e inicia un 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();

Si alguien quisiera, esto es parte del fragmento de "parada":

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();

Para detener el proceso iis ordinario, debe enviarle WM_QUIT. Esto podría ser útil para esto:

/// <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); }

Tengo una aplicación ASP.NET MVC que funciona completamente (y consta de 5 ensamblajes, .NET 4.5.1, ASP.NET MVC 5.2.2) que funciona bien en Visual Studio (que usa IISExpress).

Ahora me gustaría tener una aplicación de consola que tome la aplicación MVC y la hospede (hosting propio).

Intenté con Microsoft.Owin.Host.HttpListener y Nancy.Owin pero aunque obtengo 404 páginas, a mi configuración le falta la asignación a mi aplicación MVC.

tengo

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

y

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(); } }

Pero, obviamente, falta la configuración para usar MyMvcApplication de la aplicación MVC en ejecución. ¿Como hacer eso? ¿O cómo autohostenlo de otra manera?

Las respuestas que encontré en la web se refieren a versiones anteriores y esperaba tener una forma más fácil hoy.