Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/34.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP.NET MVC 3视图层次结构之间的数据传递 动机_C#_Asp.net_Asp.net Mvc_Asp.net Mvc 3_Razor - Fatal编程技术网

C# ASP.NET MVC 3视图层次结构之间的数据传递 动机

C# ASP.NET MVC 3视图层次结构之间的数据传递 动机,c#,asp.net,asp.net-mvc,asp.net-mvc-3,razor,C#,Asp.net,Asp.net Mvc,Asp.net Mvc 3,Razor,我希望能够在Javascript中建立一个树状的对象层次结构,它对应于页面上的ASP.NET MVC 3 Razor视图。计划是在Razor视图和定义其逻辑的Javascript文件之间建立一对一的对应关系(以接受一些初始化参数的构造函数的形式)。简单的例子如下所示: \u Layout.cshtml Global.js SplitterPane.cshtml SplitterPane.js Grid.cshtml Grid.js Tree.cshtml Tree.js 我将使用构造

我希望能够在Javascript中建立一个树状的对象层次结构,它对应于页面上的ASP.NET MVC 3 Razor视图。计划是在Razor视图和定义其逻辑的Javascript文件之间建立一对一的对应关系(以接受一些初始化参数的构造函数的形式)。简单的例子如下所示:

  • \u Layout.cshtml Global.js
    • SplitterPane.cshtml SplitterPane.js
      • Grid.cshtml Grid.js
      • Tree.cshtml Tree.js
我将使用构造函数来构建层次结构,例如

var page = new Global(global_options);
var splitter = new SplitterPane(splitter_options);
var grid = new Grid(grid_options);
var tree = new Tree(tree_options);

page.addChild(splitter);
splitter.addChild(grid);
splitter.addChild(tree);
当然,所有这些代码都应该在根(布局)视图的上下文中根据从局部视图收集的元数据自动构造。视图提供的元数据包含初始化其Javascript对象和要加载的Javascript文件所需的选项

问题 与WebForms不同,MVC视图没有我所知道的任何自然层次结构,在视图及其部分(子)视图之间传递信息似乎相当棘手。如果在视图中使用像
Html.Action
这样的帮助程序,“子视图”的整个处理过程是独立进行的,因此它们甚至不共享
页面
对象。我需要的是某种中心位置,视图可以在呈现时存放元数据,以便在布局视图中使用元数据来组合和输出完整的脚本

解决方案 我能想到的一种方法是使用
HttpContext.Current.Items
临时存储视图元数据对象的集合。所有视图都将元数据存放在那里,布局视图将使用它。执行顺序似乎符合我的期望,但是我仍然无法重建视图的树层次结构。要做到这一点,我需要使用一个堆栈,其中视图将在渲染开始时注册,在渲染结束时取消注册,以便可以在顶部找到父视图

  • 有没有一种方法可以使用一些渲染前/渲染后挂钩来放置此逻辑
  • 这是一个好主意吗
  • 是否有一个完全不同的解决方案,我看不到
    如果只想将视图与Javascript文件关联,请在layout.cshtml中定义一个部分(在关闭body标记之前):

    然后在页面和视图中:

    @section scripts {
    <script type="text/javascript" src="path to script"></script> }
    
    @节脚本{
    }
    

    但是,一旦您开始使用局部视图,这将不起作用。为了处理局部视图,我使用了自定义Html扩展@Html.RenderResource(“{sectionname},~/{path to resource}”)

    您可以编写一个自定义视图引擎:

    public class MyViewEngine : RazorViewEngine
    {
        private class MyRazorView : RazorView
        {
            public MyRazorView(ControllerContext controllerContext, string viewPath, string layoutPath, bool runViewStartPages, IEnumerable<string> viewStartFileExtensions, IViewPageActivator viewPageActivator)
                : base(controllerContext, viewPath, layoutPath, runViewStartPages, viewStartFileExtensions)
            {
            }
    
            protected override void RenderView(ViewContext viewContext, System.IO.TextWriter writer, object instance)
            {
                var stack = viewContext.HttpContext.Items["stack"] as Stack<string>;
                if (stack == null)
                {
                    stack = new Stack<string>();
                    viewContext.HttpContext.Items["stack"] = stack;
                }
                // depending on the required logic you could
                // use a stack of some model and push some additional
                // information about the view (see below)
                stack.Push(this.ViewPath);
                base.RenderView(viewContext, writer, instance);
            }
        }
    
        protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
        {
            return new MyRazorView(controllerContext, viewPath, masterPath, true, base.FileExtensions, base.ViewPageActivator);
        }
    
        protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
        {
            return new MyRazorView(controllerContext, partialPath, null, false, base.FileExtensions, base.ViewPageActivator);
        }
    }
    
    现在,您可以编写一个自定义HTML帮助程序,它将选择存储在HttpContext中的堆栈并执行一些有用的操作:

    public static class HtmlExtensions
    {
        public static IHtmlString BuildTree(this HtmlHelper htmlHelper)
        {
            var stack = htmlHelper.ViewContext.HttpContext.Items["stack"] as Stack<string>;
            if (stack == null)
            {
                return MvcHtmlString.Empty;
            }
    
    
            // TODO: your custom logic to build the tree
            ...
        }
    }
    
    public静态类
    {
    公共静态IHtmlString构建树(此HtmlHelper HtmlHelper)
    {
    var stack=htmlHelper.ViewContext.HttpContext.Items[“stack”]作为堆栈;
    if(stack==null)
    {
    返回MvcHtmlString.Empty;
    }
    //TODO:构建树的自定义逻辑
    ...
    }
    }
    
    在您的_布局的末尾:

        ...
        <script type="text/javascript">
            @Html.BuildTree()
        </script>
    </body>
    
    。。。
    @Html.BuildTree()
    
    正如您所说,分区不适用于局部视图。您提到的扩展使用了类似于我提出的解决方案的方法,因此我提出的三个问题仍然适用:)这是一个非常好和彻底的解决方案!!谢谢,听起来很酷..重建树唯一缺少的是父视图和子视图之间的链接。我我可以通过保持一个平行的“父”堆栈来做到这一点,在调用base.RenderView之前推送一个项,然后在调用之后弹出它。这应该可以,对吧?
    public static class HtmlExtensions
    {
        public static IHtmlString BuildTree(this HtmlHelper htmlHelper)
        {
            var stack = htmlHelper.ViewContext.HttpContext.Items["stack"] as Stack<string>;
            if (stack == null)
            {
                return MvcHtmlString.Empty;
            }
    
    
            // TODO: your custom logic to build the tree
            ...
        }
    }
    
        ...
        <script type="text/javascript">
            @Html.BuildTree()
        </script>
    </body>