【问题标题】:Can I run a ASPX and grep the result without making HTTP request?我可以在不发出 HTTP 请求的情况下运行 ASPX 并 grep 结果吗?
【发布时间】:2010-03-07 01:04:41
【问题描述】:

我怎样才能在没有 URL 和 HTTP 的情况下对一个简单的 ASP.NET 文件进行函数调用,并捕获它生成的字节流?

更多背景信息,

我需要某种模板,可以在里面放一点逻辑,来渲染一些类似 INI 的文本文件。我放弃了从 Java 移植的那些库,并提出了使用 ASP.NET 作为模板引擎的解决方案。 (我不是用它来构建网站,甚至不是 HTML。)

我写了一个 ASP.NET 页面(没有 WebForm,没有 MVC),它接受 XML POST,它根据一组简单但不太简单的规则生成一个长文本文件。

我从 DB 对象生成 XML,提交到 ASP 页面,grep 结果,它工作得很好。但是,问题是我们希望将其用作库,由 WCF 使用。正因为如此,我没有使用相对路径,我不得不将 ASP 的 URL 存储在配置中的某个位置,我不想这样做。

它将托管在 IIS 服务器上,但不会从任何前端 ASP 调用(至少不是直接调用),也永远不会从最终用户调用。

PS。我最初是在为 C# 寻找一个简单的模板引擎,但 they 太旧且不再需要维护,文档很差,缺少集成的编辑器/调试器,太简单,而且他们可能会说不同的语言。

PPS。我也考虑过 T4,但它在 VS 2008 中没有编辑器和调试器。

【问题讨论】:

  • 有两个 t4 编辑器插件可用,来自 Clarius 和 Tangible。有形有一个免费版本。 T4 可以通过简单地放置 System.Diagnostics.Debugger.Break 进行调试;声明。

标签: c# asp.net iis template-engine


【解决方案1】:

如果您为 ASPNET 运行时构建主机,则可以在没有 IIS、没有 HTTP 消息的情况下运行 ASPX 页面。

例子:

public class MyAspNetHost : System.MarshalByRefObject
{
    public void ProcessRequest(string page)
    {
        var request = new System.Web.Hosting.SimpleWorkerRequest
            (page,               // the page being requested
             null,               // query - none in this case
             System.Console.Out  // output - any TextWriter will do
            );

        // this will emit the page output to Console.Out
        System.Web.HttpRuntime.ProcessRequest(request);
    }

    public AppDomain GetAppDomain()
    {
        return System.Threading.Thread.GetDomain();
    }
}


public class Example
{   
    public void Run(IEnumerable<String> pages)
    {
        // ASPNET looks for assemblies - including the assembbly
        // that contains any custom ASPNET host - in the bin\
        // subdirectory of the physical directory that backs the
        // ASPNET Host.  Because we are going to use the current
        // working directory as the physical backing directory for
        // the ASPNET host, we need to ensure there's a bin
        // subdirectory present.

        bool cleanBin = false;
        if (!Directory.Exists("bin"))
        {
            cleanBin = true;
            Directory.CreateDirectory("bin");
        }

        // Now, ensure that the assembly containing the custom host is
        // present in that bin directory.  The assembly containing the
        // custom host is actually *this* assembly.  

        var a = System.Reflection.Assembly.GetExecutingAssembly();
        string destfile= Path.Combine("bin", Path.GetFileName(a.Location));
        File.Copy(a.Location, destfile, true); 

        host =
            (MyAspNetHost) System.Web.Hosting.ApplicationHost.CreateApplicationHost
            ( typeof(MyAspNetHost),
              "/foo",   // virtual dir - can be anything
              System.IO.Directory.GetCurrentDirectory() // physical dir
              );

        // process each page
        foreach (string page in pages)
            host.ProcessRequest(page);
    }
}

如果你想清理那个 bin 目录,你必须先让 AppDomain 卸载。你可以这样做,像这样:

    private ManualResetEvent aspNetHostIsUnloaded;

    private void HostedDomainHasBeenUnloaded(object source, System.EventArgs e)
    {
        // cannot clean bin dir here.  The AppDomain is not yet gone.
        aspNetHostIsUnloaded.Set();
    }

    private Run(IEnumerable<String> pages)
    {
        try 
        {
            ....code from above ....
        }
        finally
        {
            if (host!= null)
            {
                aspNetHostIsUnloaded = new ManualResetEvent(false);

                host.GetAppDomain().DomainUnload += this.HostedDomainHasBeenUnloaded;

                AppDomain.Unload(host.GetAppDomain());

                // wait for it to unload
                aspNetHostIsUnloaded.WaitOne();

                // optionally remove the bin directory
                if (cleanBin)
                {
                    Directory.Delete("bin", true);
                }

                aspNetHostIsUnloaded.Close();
            }
        }
    }

这对于测试 ASPX 页面以及诸如此类的事情是有意义的。但是对于您的情况,我不确定这是否正确。有更直接的方法来生成文本文件。但是,它可能适合你。如果您真的喜欢模板引擎的想法,那么托管 ASPNET 可能正是您的理想之选。

在您的情况下,您可能希望修改自定义主机,以便每个页面的输出转到 StringWriter 而不是 Console.Out,然后您可以执行 Grep(或者更可能使用 Regex 进行搜索) 在该输出上。您可能还想修改它以接受所有输入数据作为查询字符串。您需要格式化页面请求才能做到这一点。

编辑:有a good article on MSDN Magazine on this technique of hosting the ASPNET runtime。从 2004 年 12 月开始。


EDIT2:有一种更简单的方法来管理 bin 目录。只需创建一个名为 bin 的符号链接,指向“.”。然后,您可以在调用 AppDomain.Unload() 后删除符号链接,而无需等待。看起来像这样:

    public void Run(string[] pages)
    {
        bool cleanBin = false;
        MyAspNetHost host = null;
        try
        {
            // This creates a symlink.
            // ASPNET always looks for a bin\ directory for the privateBinPath of the AppDomain.
            // This will create the bin dir, pointing to the current dir.
            if (!Directory.Exists("bin"))
            {
                cleanBin = true;
                CreateSymbolicLink("bin", ".", 1);
            }

            host =
                (MyAspNetHost) System.Web.Hosting.ApplicationHost.CreateApplicationHost
                ( typeof(MyAspNetHost),
                  "/foo",   // virtual dir - can be anything
                  System.IO.Directory.GetCurrentDirectory() // physical dir
                  );

            foreach (string page in pages)
                host.ProcessRequest(page);
        }
        finally
        {
            // tell the host to unload
            if (host!= null)
            {
                AppDomain.Unload(host.GetAppDomain());

                if (cleanBin)
                {
                    // remove symlink - can do without waiting for AppDomain unload
                    Directory.Delete("bin");
                }
            }
        }
    } 

这消除了 ManualResetEvent、复制文件、同步等的需要。它假定自定义 ASPNet 主机的程序集以及您运行的 ASPX 页面所需的所有程序集都包含在当前工作目录中。

【讨论】:

  • 谢谢,贾斯汀。很久! (是迪诺·基耶萨)
【解决方案2】:

这听起来很像在服务器上生成 HTML 电子邮件的问题。这里有一些答案可以做到这一点(对于 MVC):

ASP.NET MVC: How to send an html email using a controller?

对于非 MVC,您可以通过将控件 (ASCX) 加载并呈现到文件来以类似的方式继续操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-01
    • 2012-10-03
    • 2020-03-02
    • 1970-01-01
    相关资源
    最近更新 更多