如何将自定义WebViewPage属性从视图传递到布局?

时间:2016-06-22 22:48:09

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

我已经定义了一个自定义WebViewPage类型,其中包含我们网站使用的自定义属性:

  public abstract class BasePage : WebViewPage
  {
        public string OmniPageName { get; set; }
  }

  public abstract class BasePage<TModel> : WebViewPage<TModel> where TModel: class
  {
        public string OmniPageName { get; set; }
  }

在我看来,我将此属性设置为:

Index.cshtml:

@{
    OmniPageName = "Home";
}

这在视图中设置得很好并且可用,但我还需要在布局中访问此值。我希望我可以从布局的InitializePage()覆盖中访问视图实例,但我无法弄清楚如何。类似的东西:

protected override void InitializePage()
{
   //  this.OmniPageName = (expr:child view).OmniPageName
   base.InitializePage();
}

然后使用:

Layout.cshtml:

<!-- render value from Index.cshtml -->
<div class="pagelet" data-omnipage="@OmniPageName"></div> 

目前,此属性的布局值为null。我可以使用ViewBag但是还有其他属性并不简单,标量值,我想利用IDE执行强类型来防止错误。

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:3)

你没有理由不像你所写的那样完全这样做。

但是,您需要确保将web.Config设置为从自定义视图页面继承的所有视图。 (不确定这是否已经完成)。

web.config找到~/Views/web.config文件夹中,将pageBaseType设置为您的视图类型。如

<system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="YourNameSpace.BasePage"> <!-- Edit This line -->
        <namespaces>
          <add namespace="System.Web.Mvc" />
          <add namespace="System.Web.Mvc.Ajax" />
          <add namespace="System.Web.Mvc.Html" />
          <add namespace="System.Web.Routing" />
          <!-- ommited -->
        </namespaces>
    </pages>
</system.web.webPages.razor>

现在我们可以看到,通过继承WebViewPage,您只能为Typed模型设置自定义WebViewPage<TModel>。但是,通常不会键入布局页面。因此,您应该创建另一个继承自BaseViewPage的类,例如

public class BaseViewPage : BaseViewPage<dynamic>
{
     //functionality is inherited from BaseViewPage<T>
}

这将继承您键入的BaseViewPage的所有功能,并允许非类型化视图。

修改 现在,如果你测试这个,你仍然不会将数据传递给Layout页面,因为你会发现(设置一个构造函数断点),并为每个呈现的View创建一个新的BaseViewPage实例。因此,您需要找到一种在实例之间传递共享对象中数据的方法。幸运的是,有许多不同的共享对象可用。

public string OmniPageName
{
    get
    {
        return (ViewBag._OmniPageName ?? "").ToString();
    }
    set
    {
        ViewBag._OmniPageName = value;
    }
}

这是一个使用ViewBag<dynamic>)来共享名称的简单示例。我们可以使用:

  1. ViewData:基本上与ViewBag相同,但是Dictionary
  2. TempData:这与ViewData类似,但可以在请求之间保留。