首页 文章

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

提问于
浏览
18

我有一个完整的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<Startup>(so))
        {
            Console.WriteLine("Press Enter to Exit");
            Console.ReadLine();
        }
    }

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

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

1 回答

  • 12

    由于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 . 这可能对此有所帮助:

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

相关问题