1
/* ****************************************************************************
3 * Copyright (c) Microsoft Corporation. All rights reserved.
5 * This software is subject to the Microsoft Public License (Ms-PL).
6 * A copy of the license can be found in the license.htm file included
7 * in this distribution.
9 * You must not remove this notice, or any other, from this software.
11 * ***************************************************************************/
13 namespace System
.Web
.Mvc
{
15 using System
.ComponentModel
;
16 using System
.Diagnostics
.CodeAnalysis
;
17 using System
.Globalization
;
18 using System
.Web
.Mvc
.Resources
;
21 [FileLevelControlBuilder(typeof(ViewUserControlControlBuilder
))]
22 public class ViewUserControl
: UserControl
, IViewDataContainer
{
23 private AjaxHelper _ajaxHelper
;
24 private HtmlHelper _htmlHelper
;
25 private ViewContext _viewContext
;
26 private ViewDataDictionary _viewData
;
27 private string _viewDataKey
;
29 public AjaxHelper Ajax
{
31 if (_ajaxHelper
== null) {
32 _ajaxHelper
= new AjaxHelper(ViewContext
, this);
38 public HtmlHelper Html
{
40 if (_htmlHelper
== null) {
41 _htmlHelper
= new HtmlHelper(ViewContext
, this);
49 return ViewData
.Model
;
53 public TempDataDictionary TempData
{
55 return ViewPage
.TempData
;
59 public UrlHelper Url
{
66 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
67 public ViewContext ViewContext
{
69 return _viewContext
?? ViewPage
.ViewContext
;
76 [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly",
77 Justification
= "This is the mechanism by which the ViewUserControl gets its ViewDataDictionary object.")]
79 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
80 public ViewDataDictionary ViewData
{
91 public string ViewDataKey
{
93 return _viewDataKey
?? String
.Empty
;
100 internal ViewPage ViewPage
{
102 ViewPage viewPage
= Page
as ViewPage
;
103 if (viewPage
== null) {
104 throw new InvalidOperationException(MvcResources
.ViewUserControl_RequiresViewPage
);
110 public HtmlTextWriter Writer
{
112 return ViewPage
.Writer
;
116 protected virtual void SetViewData(ViewDataDictionary viewData
) {
117 _viewData
= viewData
;
120 protected void EnsureViewData() {
121 if (_viewData
!= null) {
125 // Get the ViewData for this ViewUserControl, optionally using the specified ViewDataKey
126 IViewDataContainer vdc
= GetViewDataContainer(this);
128 throw new InvalidOperationException(
130 CultureInfo
.CurrentUICulture
,
131 MvcResources
.ViewUserControl_RequiresViewDataProvider
,
132 AppRelativeVirtualPath
));
135 ViewDataDictionary myViewData
= vdc
.ViewData
;
137 // If we have a ViewDataKey, try to extract the ViewData from the dictionary, otherwise
138 // return the container's ViewData.
139 if (!String
.IsNullOrEmpty(ViewDataKey
)) {
140 object target
= myViewData
.Eval(ViewDataKey
);
141 myViewData
= target
as ViewDataDictionary
?? new ViewDataDictionary(myViewData
) { Model = target }
;
144 SetViewData(myViewData
);
147 private static IViewDataContainer
GetViewDataContainer(Control control
) {
148 // Walk up the control hierarchy until we find someone that implements IViewDataContainer
149 while (control
!= null) {
150 control
= control
.Parent
;
151 IViewDataContainer vdc
= control
as IViewDataContainer
;
159 public virtual void RenderView(ViewContext viewContext
) {
160 // TODO: Remove this hack. Without it, the browser appears to always load cached output
161 viewContext
.HttpContext
.Response
.Cache
.SetExpires(DateTime
.Now
);
162 ViewUserControlContainerPage containerPage
= new ViewUserControlContainerPage(this);
163 // Tracing requires Page IDs to be unique.
164 ID
= Guid
.NewGuid().ToString();
166 RenderViewAndRestoreContentType(containerPage
, viewContext
);
169 internal static void RenderViewAndRestoreContentType(ViewPage containerPage
, ViewContext viewContext
) {
170 // We need to restore the Content-Type since Page.SetIntrinsics() will reset it. It's not possible
171 // to work around the call to SetIntrinsics() since the control's render method requires the
172 // containing page's Response property to be non-null, and SetIntrinsics() is the only way to set
174 string savedContentType
= viewContext
.HttpContext
.Response
.ContentType
;
175 containerPage
.RenderView(viewContext
);
176 viewContext
.HttpContext
.Response
.ContentType
= savedContentType
;
179 private sealed class ViewUserControlContainerPage
: ViewPage
{
180 public ViewUserControlContainerPage(ViewUserControl userControl
) {
181 Controls
.Add(userControl
);