.Net MVC - 将模型呈现为html的源代码? (在MVC外部渲染视图)

时间:2018-03-12 13:54:02

标签: c# asp.net-mvc razor

我正在尝试从控制台应用程序渲染html,而不依赖于RazorEngine等工具。我想看看是否可以使用直接的mvc代码;同时了解更多有关MVC视图如何呈现工作的信息。

我一直在关注源代码: https://github.com/mono/aspnetwebstack

从RazorView开始,沿着兔子洞走下去,似乎降压停在"公共覆盖无效的ExecutePageHierarchy()"

我有点困惑,因为它似乎取决于摘要"执行"在解决方案中的任何地方都没有定义的功能。

这给了我关于视图数据如何与html混合的信息。我期待看到一些正在寻找@ Model.Prop的正则表达式,并用给定的视图数据替换。

查看解决方案中的UT也没什么帮助。它们似乎只是定义了Write函数并检查渲染是否以正确的顺序将它们拼接在一起:

[Fact]
    public void RenderPageNestedSubPageAnonymousTypeTest()
    {
        // Test that PageData for each level of nesting returns the values as specified in the 
        // previous calling page.
        //
        // ~/index.cshtml does the following:
        // @(PageData["foo"] ?? "null")
        // @RenderPage("subpage.cshtml", new { foo = 1 , bar = "hello" })
        //
        // ~/subpage1.cshtml does the following:
        // @(PageData["foo"] ?? "sub1nullfoo")
        // @(PageData["bar"] ?? "sub1nullbar")
        // @(PageData["x"] ?? "sub1nullx")
        // @(PageData["y"] ?? "sub1nully")
        // @RenderPage("subpage2.cshtml", new { bar = "world", x = "good", y = "bye"})
        //
        // ~/subpage2.cshtml does the following:
        // @(PageData["foo"] ?? "sub2nullfoo")
        // @(PageData["bar"] ?? "sub2nullbar")
        // @(PageData["x"] ?? "sub2nullx")
        // @(PageData["y"] ?? "sub2nully")
        //
        // Expected result: null 1 hello sub1nullx sub1nully sub2nullfoo world good bye
        var page = Utils.CreatePage(
            p =>
            {
                p.Write(p.PageData["foo"] ?? "null ");
                p.Write(p.RenderPage("subpage1.cshtml", new { foo = 1, bar = "hello" }));
            });
        var subpage1Path = "~/subpage1.cshtml";
        var subpage1 = Utils.CreatePage(
            p =>
            {
                p.Write(p.PageData["foo"] ?? "sub1nullfoo");
                p.Write(" ");
                p.Write(p.PageData["bar"] ?? "sub1nullbar");
                p.Write(" ");
                p.Write(p.PageData["x"] ?? "sub1nullx");
                p.Write(" ");
                p.Write(p.PageData["y"] ?? "sub1nully");
                p.Write(" ");
                p.Write(p.RenderPage("subpage2.cshtml", new { bar = "world", x = "good", y = "bye" }));
            }, subpage1Path);
        var subpage2Path = "~/subpage2.cshtml";
        var subpage2 = Utils.CreatePage(
            p =>
            {
                p.Write(p.PageData["foo"] ?? "sub2nullfoo");
                p.Write(" ");
                p.Write(p.PageData["bar"] ?? "sub2nullbar");
                p.Write(" ");
                p.Write(p.PageData["x"] ?? "sub2nullx");
                p.Write(" ");
                p.Write(p.PageData["y"] ?? "sub2nully");
            }, subpage2Path);

        Utils.AssignObjectFactoriesAndDisplayModeProvider(subpage1, subpage2, page);

        var result = Utils.RenderWebPage(page);
        Assert.Equal("null 1 hello sub1nullx sub1nully sub2nullfoo world good bye", result);
    }

我在这里遗漏了什么吗?或者外部处理cshtml分辨率的模型?在任何情况下,我能在哪里找到该代码?

我最初尝试的是SUPER hacky。由于我没有设置HostingEnvironment或HttpRuntime(视图呈现过程使用的静态)的方式,我试图通过查看源代码所需的内容并尽可能地提供它来手动设置它。尽量不要嘲笑

System.Threading.Thread.GetDomain().SetData(".appDomain", "*");
        System.Threading.Thread.GetDomain().SetData(".appVPath", "/");
        FieldInfo info = typeof(HttpRuntime).GetField("_theRuntime", BindingFlags.NonPublic | BindingFlags.Static);
        object value = info.GetValue(null);
        MethodInfo dynMethod = typeof(HttpRuntime).GetMethod("Init", BindingFlags.NonPublic | BindingFlags.Instance);
        dynMethod.Invoke(value, null);


        FieldInfo info2 = typeof(HostingEnvironment).GetField("_theHostingEnvironment", BindingFlags.NonPublic | BindingFlags.Static);
        info2.SetValue(null, new HostingEnvironment());
        object value2 = info2.GetValue(null);
        MethodInfo dynMethod2 = value2.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
            .FirstOrDefault(x => x.GetParameters().Count() == 6 && x.Name == "Initialize");
        dynMethod2.Invoke(value2, new object[] { ApplicationManager.GetApplicationManager(), null, (new ConfigMapPathFactoryMock()) as IConfigMapPathFactory, null, null, null });

        var t = HostingEnvironment.VirtualPathProvider;
        //HostingEnvironment.RegisterVirtualPathProvider(new DbPathProvider());
        var path = @"C:\<path to mvc proj>\MyMVcProj\Views\Report\SomeReport.cshtml";
        HostingEnvironment.MapPath(path);
        var compType = BuildManager.GetCompiledType(path);

我最后用&#34;初始化&#34;击中了一堵砖墙。调用,它给出了一个错误说:

System.Reflection.TargetInvocationException
  HResult=0x80131604
  Message=Exception has been thrown by the target of an invocation.
  Source=mscorlib
  StackTrace:
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at TestProg.Program.Main(String[] args) in C:\<path to console app>\MyConsoleApp\Program.cs:line 165

Inner Exception 1:
InvalidOperationException: The configuration system has already been initialized.

无法在源代码中查明该错误消息,我得出结论,它被其他一些外部工具抛出。由于没有有意义的堆栈跟踪让我继续,它可能是一个或多个事情。所以我开始把注意力更多地转移到

的细节上

我想解决的问题: 我在我的应用程序中部署了一个用于处理大型任务的窗口服务的工作者(执行某些给定任务的东西)基础结构。在我的情况下,我试图生成一个大型报告,并使用工具将该HTML转换为PDF格式。 如果我能以某种方式从那里渲染html,那将是理想的,但它具有挑战性,因为它没有HttpRuntime或HostingEnvironment设置,就像你从web api那样运行时那样。 我想尽量避免使用像RazorEngine这样的工具,因为这会增加太多限制。

1 个答案:

答案 0 :(得分:0)

在MVC之前,有许多创建HTML的方法,它们仍然存在。

例如,HtmlTable类为<table>元素生成HTML。该文档包含许多类似类的链接,因此您可以进行探索。

This question显示了使用HtmlTable的示例。

它不像Razor那么容易使用,但你想要它很难: - )