【问题标题】:prevent child action from binding to parent ViewData防止子操作绑定到父 ViewData
【发布时间】:2014-10-31 16:42:29
【问题描述】:

我有一个普通视图(NV)和 2 个局部视图(PV1 和 PV2),PV2 嵌套在 PV1 中,而 PV1 在 NV 中。我遇到的问题是 PV1 和 PV2 都有一个名为“isSuccessful”的可选五音表,它被添加到视图包“ViewBag.IsSuccessful = isSuccessful;”中。在动作中,由于某种原因,当 PV1 将其“isSuccessful”设置为 true 时,PV2 的“isSuccessful”也与 true 绑定。这会导致 PV2 过早地运行一些 JavaScript 函数,从而导致其他问题。

代码(结构和示例)

在控制器中

    public ActionResult NV(int id)
    {
        var model = GetNVModel(id);
        return View(model);
    }

    public ActionResult PV1 (int pv1Id = 0, bool isSuccessful = false)
    {
        var model = GetPV1Model(id);
        ViewBag.IsSuccessful = isSuccessful;
        return PartialView(model);
    }

    public ActionResult PV2 (int pv2Id = 0, bool isSuccessful = false)
    {
        var model = GetPV2Model(id);
        if(model == null){model = new PV2Model();}
        ViewBag.IsSuccessful = isSuccessful;
        return PartialView(model);
    }

观点

NV.cshtml

     @model NVModel
     <div>
         @if (Model != null && Model.PV1Id != null && Model.PV1Id > 0)
         {<text>
              @Html.Action("PV1", "ControlerName", new { PV1Id = Model.PV1Id, isSuccessful = true})
         </text>}
     </div>

PV1.cshtml

     @model PV1Model
     @{bool isSuccessful = (ViewBag.IsSuccessful != null ? (bool)ViewBag.IsSuccessful : false);}
     <div>
         @if (Model != null && Model.PV2Id != null && Model.PV2Id > 0)
         {<text>
              @Html.Action("PV2", "ControlerName", new { PV2Id = Model.PV2Id })
         </text>}
     </div>
     <script>
         @if (isSuccessful )
         {<text>
              function sayHello()
              {console.log('Hello PV1');}
         </text>}
     </script>

PV2.cshtml

     @model PV2Model
     @{bool isSuccessful = (ViewBag.IsSuccessful != null ? (bool)ViewBag.IsSuccessful : false);}
     <div>
         @if (Model != null)
         {<text>
              @Html.TextBoxFor(model=> model.Message)
         </text>}
     </div>
     <script>
         @if (isSuccessful )
         {<text>
              $(document).ready(function(){
                 console.log($("#Message").val());
              });
         </text>}
     </script>

我不明白为什么 PV1 的 ViewData/ViewBag 被传递给 PV2。我认为不传递所有父 ViewData/ViewBag 是使用“@Html.Action”而不是“@Html.Partial”的一部分。 我需要知道的是是否有一个参数我需要传递给“@Html.Action”或者一个web.config属性需要翻转,因为上面不是一次性的事情,这是我做大部分页面的方式,以使视图尽可能灵活。

我正在使用 ASP.NET MVC 4、C# 和 .NET 4.5

感谢您对此问题的任何帮助或线索。

【问题讨论】:

    标签: c# .net asp.net-mvc asp.net-mvc-4 asp.net-mvc-partialview


    【解决方案1】:

    ViewBag 不会在动作之间共享,但是路由参数是共享的!如果您在PV2 方法中设置断点并在执行ViewBag.IsSuccessful = isSuccessful; 之前检查 ViewBag,您可以看到这一点。您将看到 ViewBag 为空,但该方法接收到的参数为 true。

    问题是您使用@Html.Action("PV1", "ControlerName", new { PV1Id = Model.PV1Id, isSuccessful = true}) 将路由参数isSuccessful 传递给PV1,因此当您调用PV2 操作时,PV2 的路由属性将与当前属性合并。这意味着 isSuccessful 将被传递给 PV2。

    如果您检查MVC source code 中的Html.Action 助手,您将看到路由属性与当前属性合并。检查内部 ActionHelper 方法,合并发生的地方:

    internal static void ActionHelper(HtmlHelper htmlHelper, string actionName, string controllerName, RouteValueDictionary routeValues, TextWriter textWriter)
    {
        ...
    
        //The route values provided to @Html.Action are merged with the current ones
        RouteValueDictionary additionalRouteValues = routeValues;
        routeValues = MergeDictionaries(routeValues, htmlHelper.ViewContext.RouteData.Values);
    
        ...
    }
    

    如果你想防止这种情况,你可以在调用 PV2 时覆盖路由参数。为此,您可以执行以下操作:

    @Html.Action("PV2", "Home", new { isSuccessful = "" })
    

    您还可以使用RouteValueDictionary 调用该操作,这可以让您将路由参数设置为空:

    @Html.Action("PV2", "Home", new RouteValueDictionary{{"isSuccessful", null}})
    

    【讨论】:

    • 好吧,这很有趣。我想知道我是否可以扩展或编写一个帮助程序以覆盖该功能,或者至少添加一个防止合并的布尔婴儿车或其他东西谢谢
    • 您可以创建自己的HtmlHelper 扩展方法,在调用现有的Action 之前查看htmlHelper.ViewContext.RouteData.Values 中的当前路由值并清除它们(可能保留控制器和操作?)方法
    猜你喜欢
    • 2011-07-20
    • 1970-01-01
    • 1970-01-01
    • 2017-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多