为什么ViewBag中的项目不会传播到_Layout页面?

时间:2012-04-11 22:09:31

标签: asp.net-mvc-3

我有一个SiteNavigation类正在我的基本控制器的Initialize事件中更新,例如

[Serializable]
public class SiteNavigation
{

    public SiteNavigation()
    {
        IsSummarySelected = true;
    }

    public Model.Dtos.Folder[] Folders { get; set; }


    public bool IsSummarySelected { get; set; }

}

protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
    base.Initialize(requestContext);

    var siteNavigation = new SiteNavigation();

    siteNavigation.Folders = GetMeMyFolders() as Folder[];

    ViewBag.SiteNavigation = siteNavigation;

}

并且在控制器中,IsSummarySelected属性更改为此值。

ViewBag.SiteNavigation.IsSummarySelected = false;

当我使用这行代码访问_Layout文件中的属性时,该值始终为true。这就好像导航对象再次被New'd up并且构造函数将其设置为true。

 @if (ViewBag.SiteNavigation.IsSummarySelected)

我已经尝试将nav对象强制转换为变量并将该属性设置为也没有骰子。任何帮助将不胜感激。

让我感到困惑!

谢谢你, 斯蒂芬

2 个答案:

答案 0 :(得分:1)

我只是将您的代码粘贴到我的示例mvc项目中,并且在我的操作中正确更改IsSummarySelected反映在_Layout文件中。你确定你的控制器的任务受到了打击,而你之后没有在其他地方重新分配它吗?

编辑:您的问题就是为什么我认为将ViewBag用于除本地化快速修复之外的任何其他内容的一个不错的主意。调试动态全局对象并不好玩。重构建议:在基本控制器中创建站点导航属性

SiteNavigation siteNavigation;
public SiteNavigation SiteNavigation
{
    get
    {
       return siteNavigation;
    }
    set
    {
        siteNavigation = value;
    }
}

并用此替换对ViewBag.SiteNavigation的所有引用。然后创建一个自定义WebViewPage并放入其中。

public SiteNavigation SiteNavigation
{
    get
    {
        return ((BaseController)ViewContext.Controller).SiteNavigation;
    }
}

这不会解决您的问题,但现在您可以在SiteNavigation的get和set属性上添加断点,现在调试问题应该非常容易。

答案 1 :(得分:0)

过滤器被调用然后通过 OnResultExecuting 方法填充我的 TempData [" SplitterIsCollapsed"] 时。另外,我从我的 UserContext 类中获取属性状态,每个会话只注册一次: builder.RegisterType()。As()。CacheInSession(); 。 基本信息:我使用 DependcyInjection

将过滤器分配给控制器:

<强>控制器:

[LayoutTempData]
public class HomeController : Controller
{
    //....
}

FilterAttribute类:

namespace MyProject.Web.Infrastructure.Filters
{
    public class LayoutTempDataAttribute : ActionFilterAttribute
    {
        private readonly IUserContext _userContext;
        public LayoutTempDataAttribute()
        {
            _userContext = DependencyResolver.Current.GetService<IUserContext>();
        }

        public override void OnResultExecuting(ResultExecutingContext context)
        {
            if (context.Controller.TempData.ContainsKey("SplitterIsCollapsed"))
                context.Controller.TempData["SplitterIsCollapsed"] = _userContext.LayoutInformation.SplitterIsCollapsed;
            else
                context.Controller.TempData.Add("SplitterIsCollapsed", _userContext.LayoutInformation.SplitterIsCollapsed);
        }
    }
}

_Layout.cshtml 的Splitter部分如下所示:

@{Html.Telerik().Splitter().Name("Splitter1")
    .Panes(panes =>
        {
            panes.Add()
                .Size("300px")
                .Collapsible(true)
                .Collapsed((bool)TempData["SplitterIsCollapsed"])
                .Content(<div>asdfasdf</div>);
            panes.Add()
                .Collapsible(false)
                .Scrollable(false)
                .Content(<div>content2</div>);
        })
     .Render();
 }