如何在Umbraco Surface控制器中使用ViewData和ViewBag

时间:2015-01-16 18:14:37

标签: umbraco viewbag viewdata surface-controller

我花了2个小时试图解决为什么当我将一个字符串放入Surface控制器内的View.Bag / ViewData时,当我尝试在视图中获取字符串时我得到null。

最后,我通过将字符串放入一个会话变量insted来解决问题。

想知道为什么它不起作用,以及如何解决它。

提前致谢。

2 个答案:

答案 0 :(得分:3)

更新:您是否正在发布和重定向?刷新表单时是否会提示您再次发布?如果没有,那是因为您不小心从表单帖子中遵循了302的最佳做法(阻止用户刷新并重新发布表单数据)。我为登录表面控制器所遵循的示例都使用{I}盲目跟随的return RedirectToCurrentUmbracoPage()。但是,顾名思义,它确实在进行重定向,实际上是两个请求! (在我相信它之前,我固执地必须在Fiddler验证)。 ViewData和ViewBag仅适用于一个请求 - 因此它们在POST 302中基本被破坏。会话适用于多个请求,这就是它为您工作的原因。 TempData也适合你,因为事实证明,TempData是一个构建在会话之上的构造,专门用于在两个帖子之间传递状态(在检索时删除)。我在某处读到TempData的名称RedirectData更好,这有助于它点击我。

因此,当您处理Surface控制器和POST时,您有三个我认识的选项:

  • 会话(你证明有效)
  • TempData(建立在会话上,从我读过的内容是最佳实践,专门针对这种情况而构建)
  • 在表单帖子中使用return CurrentUmbracoPage();。我刚刚在Fiddler中验证了这只是一个请求(在浏览器中刷新提示重新发布警告)。我还验证了ViewData以这种方式工作。但是,因为使用@Html.Action(...)将表面控制器渲染为子操作,您必须使用ParentActionViewContext来获取正确的ViewData(我的第一个答案,我将留给其他发现此问题的人)。

当没有涉及重定向时,原始答案仍然有用(GET或返回CurrentUmbracoPage()的POST)...

在许多情况下,你实际上正在做一个孩子的行动。通常你只有一个级别,但如果你混合使用宏和部分,你实际上可以获得多个级别。每个级别都有一个ViewData,您必须使用ParentActionViewContext向上移动到堆栈,才能到达您在控制器中填充的顶部ViewData

在回答关于表面控制器和视图数据的问题时,请参阅this comment from Shannon(Shannon是总部团队的核心贡献者,并且有很多很棒的内容)。引用这里:

  

如果要访问从主ViewContext渲染的ChildAction上的主ViewContext上设置的ViewData,则需要使用@ ViewContext.ParentActionViewContext.ViewData [“ErrorMessage”]

     

此示例中的ParentActionViewContext是呈现Umbraco模板的ViewContext,而不是ChildAction。这是因为当您POST(无论是在Umbraco内部还是普通MVC中)时,您正在发布一个新的Action并且渲染过程从头开始,当您验证模型,更新ViewData等等...这一切都发生在什么将在视图呈现时成为“主”ViewContext。然后,此视图将呈现您的ChildAction。

答案 1 :(得分:1)

Twamley的回答非常好,此外,我发现使用TempData.Add(key, value)效果很好。

裸露的骨头看起来像:

SurfaceController

public class MyController : Umbraco.Web.Mvc.SurfaceController 
{
    public MyController() 
    {}

    public ActionResult DoSomething() 
    {
        // surface controller does something

        // get a page by it's document/model type alias
        var umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
        var node = umbracoHelper.TypedContentSingleAtXPath("//" + "Home")      

        TempData.Add("Message", "This value will be passed through");
        return redirectToUmbracoPage(node);
    }
}

查看

@inherits UmbracoTemplatePage
@{
    Layout = null;
}
@if (TempData.ContainsKey("Message"))
{
   <p>@TempData["Message"]</p>
}

http://localhost/umbraco/Surface/My/DoSomething

相关问题