无法在ASP.NET MVC3的部分视图中访问ViewBag

60
我有一个控制器调用视图,在视图中有一个名为ViewNamePartialView,代码如下:@Html.Partial("ViewName", model) 这个工作得很好。

但是在控制器中,我希望将一些难以放入传递给视图的模型中的数据加入到ViewBag中。主视图可以轻松访问ViewBag,但是在PartialView中不返回任何信息。

在这种情况下,是否可以使用ViewBag?还是应该将这些数据“hack”到传递给视图(传递给第一个PartialView的模型,传递给嵌套在第一个PartialView中的PartialView的模型)中的模型中?


关于动态语言需要记住的一件事是它区分大小写。 - Buildstarted
我的错误,我在链中使用了@Html.Action,但忘记了它。 - vinczemarton
7
我实际上因为这个非常糟糕的问题获得了金徽章,感觉非常蠢。我有点羞愧。 - vinczemarton
8个回答

63

那应该没有任何问题。在我的HomeController Index操作中,我向ViewBag添加了一条消息:

ViewBag.Message = "Welcome to ASP.NET MVC!";

在索引视图中,我添加了局部视图:

@Html.Partial("ViewName")

我在部分视图上呈现消息:

@ViewBag.Message

从下面的评论中可以看出,在将模型传递给部分视图时存在问题。此时,您可以使用以下代码引用原始的ViewBag:

@ViewContext.Controller.ViewBag.Message

29
如果你使用 @Html.Partial("ViewName", Model),那么视图包(viewbag)的其余部分将无法使用。 - Bryan Legend
2
你确定吗?对我来说,只有在指定显式的viewData时才是这种情况。像这样:@Html.Partial("ViewName", Model, ViewData),否则ViewBag是完全可访问的。 - Krisztián Balla
25
我知道这篇文章有点老了,但是以后参考的话,我是通过使用 ViewContext.Controller.ViewBag.Property 来解决的。当然,这意味着你正在尝试访问的 ViewBag 属性是在控制器中设置的,但我认为这是一个很常见的情况。 - TehOne
我知道我们不应该说谢谢,但在读了TehOne的评论之前,这件事一直让我很苦恼。TehOne,你救了我的命: P!! - The_Butcher
1
这种情况只会在我加载一个局部视图时发生。@TehOne的解决方案对我有用。 - zanderwar
@TehOne,您也能看一下我的问题吗?https://dev59.com/enENtIcB2Jgan1zn-6W8 - Hossein

35
如果您正在使用 Html.Partial() 的一种重载,其中 viewData 是其中一个输入参数,例如:
@Html.Partial("PartialViewName", Model, new ViewDataDictionary(ViewBag))

如果您删除了new ViewDataDictionary(ViewBag),那么您的部分视图将无法看到来自原始ViewBag的数据。

因此,请不要使用new ViewDataDictionary(ViewBag),应该写成

@Html.Partial("PartialViewName", Model)

1
请注意,我已经找到了错误的原因,所以这个答案可能没有任何相关性。 - vinczemarton
11
@SoonDead,但这个答案仍然适用于在这里搜索的谷歌用户 :) - David Levin
@EvgenyLevin 这是真的。 - vinczemarton
2
你应该使用 new ViewDataDictionary(ViewData) 来初始化你的视图数据字典。这将复制所有原始视图数据值,包括 ViewBag,到新的字典中。详情请参见:https://dev59.com/XnPYa4cB1Zd3GeqPmroX#17301370 - o_o

11
在评论中TehOne说:

我知道这有点老了,但供参考,我通过使用ViewContext.Controller.ViewBag.Property解决了这个问题。当然,这意味着您正在尝试访问的ViewBag属性是在控制器中设置的,但我认为这是一个常见的情况。

这对我起作用了。


9

最近我碰到了同样的问题,但这里给出的答案只是一种变通方法,因为它们建议不要使用 Html.Partial 的重载版本,而是使用 viewData。但如果你必须使用这些重载版本,我相信正确的答案是:

@Html.Partial(
     "PartialViewName",
     model_object,
     new ViewDataDictionary() { { "Value1InViewBag", ViewBag.Value1InViewBag }, { "Value2InViewBag", ViewBag.Value2InViewBag } }
)

如果您需要传递不同的 ViewDataDictionary (例如,我将其用于更改 HtmlFieldPrefix),我认为应该使用此答案,并且因为在视图中,您应该知道部分视图将需要哪些参数从 ViewBag 中获取,因此将所有这些参数命名为将复制到新的 ViewBag 中的参数不应该是问题(显然,ViewBag 使用来自 ViewData 的值)。


2

> 通常情况下,当您使用Html.Partial时;

注:Original Answer翻译成“最初的回答”。
Html.Partial("partialViewName");

发送给parentView的模型可以在partialViewName中使用。此外,发送给parentView的ViewData也可以在partialViewName中使用。

> 特殊情况下,当您使用Html.Partial并且想要发送Model时...


注:Original Answer 翻译成“最初的回答”不符合上下文语境,因此未翻译。
Html.Partial("partialViewName", newModel);

你无法访问发送给 parentView 的模型。 因此,现在活跃在 partialViewName 中的模型是 newModel。 发送给 parentView 的 viewData 也可以用于 partialViewName。

> 特殊情况下,当使用 Html.Partial 并且想要发送 ViewDataDictionary 时...

可以将发送给 parentView 的模型用于 partialViewName。

I.

@Html.Partial("partialViewName", new ViewDataDictionary { { "key", value }, { "key2", value2 }  })

这里,通过“new ViewDataDictionary”覆盖了发送给parentView的ViewData。

如果存在一个针对parentView的ViewBag,则无法通过上述代码访问它。

II.

最初的回答中,通过使用“new ViewDataDictionary”来覆盖发送给parentView的ViewData。如果存在一个针对parentView的ViewBag,则无法通过上述代码访问它。

ViewDataDictionary viewDataDictionary =  new ViewDataDictionary();
viewDataDictionary.Add("key", value);
viewDataDictionary.Add("key2", value2);
@Html.Partial("partialViewName", viewDataDictionary)

"最初的回答" 翻译成英文是 "Original Answer"。这段内容与第一部分相同。 III. 的意思是第三部分。
ViewDataDictionary viewDataDictionary = ViewData; //If you use this code block,  ViewBag which is sent for parent View is not lost.
viewDataDictionary.Add("key", value);
viewDataDictionary.Add("key2", value2);
@Html.Partial("partialViewName", viewDataDictionary)

使用此代码块,您可以访问在partialViewName中发送给parentView的ViewData和ViewBag。"Original Answer"翻译成"最初的回答"。

1

我也遇到了一个非常基本的页面的同样问题:

@Html.Partial("_AppIntro")

<div class="form-group row">
    <div class="col-md-10">
        <a href="/Ag/Application/1" class="btn btn-default btn-primary">Next</a>
    </div>
</div>

这个局部视图只包含一些文本,其中引用了ViewBag来获取从控制器传递的一些动态值。结果发现,局部视图的名称很重要。将局部页面删除并使用Add -> View -> MVC 5 View重新创建它,但将页面命名为_AppIntro.cshtml可以解决问题。


0

我的情境是,我有一個帶有模型 IEnumerable<SampleModel> 的部分視圖。然而,我必須使用傳遞,因為 Model.SampleModelList 可能為 null

@Html.Partial("PartialViewName", Model.SampleModelList, new ViewDataDictionary())

简单的解决方案是因为PartialView现在也是View的一部分,所以可以通过PartialView访问View上的每个元素,因此我将ViewBag数据设置为View HTML上的data-element,而不是ViewBag本身。
<div class="showcase-heading" id="dvValue" data-id="@Model.ContentId">@Model.Name</div>

0
在我的情况下,@ViewContext.Controller.ViewBag.Message同样无法工作。 我有一个局部视图,它从不同的控制器引用不同的模型,并从一个基础模型类继承。在这种情况下,Controller.ViewBag 为空。 我的解决方案是:
@{
var dummy = ViewContext.Controller.ViewData.TryGetValue("CommonRules", out object rules);
}
...
@Html.Raw(rules)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接