【问题标题】:Self-host of ASP.NET MVC applicationASP.NET MVC 应用程序的自托管
【发布时间】:2015-01-29 08:57:53
【问题描述】:

我有一个功能齐全的 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 的配置。怎么做?或者如何自托管?

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

【问题讨论】:

  • 据我现在研究,这在 ASP.NET 5 (vNext; MVC 6) 之前是不可能的,并且使用 nancy 托管我的应用程序将需要从 ASP.NET MVC 迁移到 Nancy(也可能使用 Razor 模板引擎)。对吗?
  • 如上所述,您不能“自托管”MVC,而 Nancy 是一个与 MVC 完全不同的 Web 开发框架 - 它不是托管 MVC 的替代方式,您不能只是将它们混搭就这样在一起。
  • 那么问题是是否还有其他东西可以自托管,或者 MVC5 是否只需要 IIS 托管而没有任何解决方法。
  • 后者在当前版本中。
  • Nancy 应用程序可以自托管,是的,您可以将 Razor 与 Nancy 一起使用。如果您想了解有关 Nancy 的更多信息,请访问 www.nancyfx.org。

标签: c# asp.net-mvc owin nancy self-hosting


【解决方案1】:

由于 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);
    }

【讨论】:

  • 好吧,为什么不同时重定向 stdinput 并发送 Q 以优雅地停止 iis。比您可以等待 HasExited 并在失败时仍然停止该过程。
猜你喜欢
  • 2011-01-11
  • 1970-01-01
  • 2012-05-09
  • 2014-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多