ASP.NET MVC应用程序的自托管

我有一个完整的ASP.NET MVC应用程序(由5个程序集组成,.NET 4.5.1,ASP.NET MVC 5.2.2),它在Visual Studio(使用IISExpress)中运行良好。

我现在想要一个控制台应用程序,它接受MVC应用程序并托管它(自托管)。

我尝试使用Microsoft.Owin.Host.HttpListenerNancy.Owin但是当我得到404页面时,我的配置缺少映射到我的MVC应用程序。

我有

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

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

但显然MyMvcApplication从正在运行的MVC应用程序中使用MyMvcApplication的配置。 怎么做? 或者如何自我托管呢?

我在网上找到的答案是指旧版本,我希望今天能有更简单的方法。

由于ASP.NET vNext尚未可用且我的应用程序使用MVC5,我必须将MVC应用程序完全迁移到Nancy或类似的东西。 MVC5过于依赖IIS。

为了解决这个问题,我决定采用中间解决方案,因为性能不是问题:

我的控制台应用程序创建IIS配置文件并启动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(); 

如果有人想,这是“停止”片段的一部分:

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

要使iis进程保持普通,你应该向它发送WM_QUIT。 这可能对此有所帮助:

  ///  /// Sends a WM_QUIT message to another process. ///  /// PID of the other process 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); } } ///  /// Provides the native methods to post messages to other windows processes. ///  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); }