[英]Self-host of ASP.NET MVC application
I have a full-working ASP.NET MVC application (consisting of 5 assemblies, .NET 4.5.1, ASP.NET MVC 5.2.2) which runs fine in Visual Studio (which uses IISExpress). 我有一个完整的ASP.NET MVC应用程序(由5个程序集组成,.NET 4.5.1,ASP.NET MVC 5.2.2),它在Visual Studio(使用IISExpress)中运行良好。
I would now like to have a console application which takes the MVC application and hosts it (self hosting). 我现在想要一个控制台应用程序,它接受MVC应用程序并托管它(自托管)。
I tried with Microsoft.Owin.Host.HttpListener
and Nancy.Owin
but while I get 404 pages my configurations lacks the mapping to my MVC-app. 我尝试使用
Microsoft.Owin.Host.HttpListener
和Nancy.Owin
但是当我得到404页面时,我的配置缺少映射到我的MVC应用程序。
I got 我有
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseNancy();
}
}
and 和
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();
}
}
But obviously the configuration to use MyMvcApplication
from the running MVC application is missing. 但显然
MyMvcApplication
从运行的MVC应用程序中使用MyMvcApplication
的配置。 How to do that? 怎么做? Or how to selfhost it otherwise?
或者如何自我托管呢?
The answers I found on the web refer to older versions and I was hoping to have a more easy way today. 我在网上找到的答案是指旧版本,我希望今天有更简单的方法。
As ASP.NET vNext is not yet available and my app uses MVC5 I would have to migrate the MVC app completly to Nancy or something similar. 由于ASP.NET vNext尚不可用且我的应用程序使用MVC5,我必须将MVC应用程序完全迁移到Nancy或类似的东西。 MVC5 is too dependend on IIS.
MVC5过于依赖IIS。
To solve this meanwhile I decided on an intermediate solution as performance is not an issue: 为了解决这个问题,我决定采用中间解决方案,因为性能不是问题:
My console app creates an IIS config file and launches an IIS express: 我的控制台应用程序创建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 someone would like, this is part of the "stop" fragment: 如果有人想,这是“停止”片段的一部分:
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();
To stop the iis process ordinary you should send WM_QUIT to it. 要停止普通的iis进程,你应该向它发送WM_QUIT。 This might be helpful for this:
这可能对此有所帮助:
/// <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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.