1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
|
//------------------------------------------------------------------------------
// <copyright file="MasterPage.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
/*
* MasterPage class definition
*
* Copyright (c) 1998 Microsoft Corporation
*/
namespace System.Web.UI {
using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Globalization;
using System.Security.Permissions;
using System.Reflection;
using System.Web.Hosting;
using System.Web.Compilation;
using System.Web.UI.WebControls;
using System.Web.Util;
public class MasterPageControlBuilder : UserControlControlBuilder {
internal static readonly String AutoTemplatePrefix = "Template_";
}
/// <devdoc>
/// Default ControlBuilder used to parse master page files. Note that this class inherits from FileLevelPageControlBuilder
/// to reuse masterpage handling code.
/// </devdoc>
public class FileLevelMasterPageControlBuilder: FileLevelPageControlBuilder {
internal override void AddContentTemplate(object obj, string templateName, ITemplate template) {
MasterPage master = (MasterPage)obj;
master.AddContentTemplate(templateName, template);
}
}
/// <devdoc>
/// <para>This class is not marked as abstract, because the VS designer
/// needs to instantiate it when opening .master files</para>
/// </devdoc>
[
Designer("Microsoft.VisualStudio.Web.WebForms.MasterPageWebFormDesigner, " + AssemblyRef.MicrosoftVisualStudioWeb, typeof(IRootDesigner)),
ControlBuilder(typeof(MasterPageControlBuilder)),
ParseChildren(false)
]
public class MasterPage : UserControl {
private VirtualPath _masterPageFile;
private MasterPage _master;
// The collection used to store the templates created on the content page.
private IDictionary _contentTemplates;
// The collection used to store the content templates defined in MasterPage.
private IDictionary _contentTemplateCollection;
private IList _contentPlaceHolders;
private bool _masterPageApplied;
// The page or masterpage that hosts this masterPage.
internal TemplateControl _ownerControl;
public MasterPage() {
}
/// <devdoc>
/// <para>Dictionary used to store the content templates that are passed in from the content pages.</para>
/// </devdoc>
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected internal IDictionary ContentTemplates {
get {
return _contentTemplates;
}
}
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected internal IList ContentPlaceHolders {
get {
if (_contentPlaceHolders == null) {
_contentPlaceHolders = new ArrayList();
}
return _contentPlaceHolders;
}
}
/// <devdoc>
/// <para>The MasterPage used by this nested MasterPage control.</para>
/// </devdoc>
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.MasterPage_MasterPage)
]
public MasterPage Master {
get {
if (_master == null && !_masterPageApplied) {
_master = MasterPage.CreateMaster(this, Context, _masterPageFile, _contentTemplateCollection);
}
return _master;
}
}
/// <devdoc>
/// <para>Gets and sets the masterPageFile of this control.</para>
/// </devdoc>
[
DefaultValue(""),
WebCategory("Behavior"),
WebSysDescription(SR.MasterPage_MasterPageFile)
]
public string MasterPageFile {
get {
return VirtualPath.GetVirtualPathString(_masterPageFile);
}
set {
if (_masterPageApplied) {
throw new InvalidOperationException(SR.GetString(SR.PropertySetBeforePageEvent, "MasterPageFile", "Page_PreInit"));
}
if (value != VirtualPath.GetVirtualPathString(_masterPageFile)) {
_masterPageFile = VirtualPath.CreateAllowNull(value);
if (_master != null && Controls.Contains(_master)) {
Controls.Remove(_master);
}
_master = null;
}
}
}
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected internal void AddContentTemplate(string templateName, ITemplate template) {
if (_contentTemplateCollection == null) {
_contentTemplateCollection = new Hashtable(10, StringComparer.OrdinalIgnoreCase);
}
try {
_contentTemplateCollection.Add(templateName, template);
}
catch (ArgumentException) {
throw new HttpException(SR.GetString(SR.MasterPage_Multiple_content, templateName));
}
}
internal static MasterPage CreateMaster(TemplateControl owner, HttpContext context,
VirtualPath masterPageFile, IDictionary contentTemplateCollection) {
Debug.Assert(owner is MasterPage || owner is Page);
MasterPage master = null;
if (masterPageFile == null) {
if (contentTemplateCollection != null && contentTemplateCollection.Count > 0) {
throw new HttpException(SR.GetString(SR.Content_only_allowed_in_content_page));
}
return null;
}
// If it's relative, make it *app* relative. Treat is as relative to this
// user control (ASURT 55513)
VirtualPath virtualPath = VirtualPathProvider.CombineVirtualPathsInternal(
owner.TemplateControlVirtualPath, masterPageFile);
// Compile the declarative control and get its Type
ITypedWebObjectFactory result = (ITypedWebObjectFactory)BuildManager.GetVPathBuildResult(
context, virtualPath);
// Make sure it has the correct base type
if (!typeof(MasterPage).IsAssignableFrom(result.InstantiatedType)) {
throw new HttpException(SR.GetString(SR.Invalid_master_base,
masterPageFile));
}
master = (MasterPage)result.CreateInstance();
master.TemplateControlVirtualPath = virtualPath;
if (owner.HasControls()) {
foreach (Control control in owner.Controls) {
LiteralControl literal = control as LiteralControl;
if (literal == null || Util.FirstNonWhiteSpaceIndex(literal.Text) >= 0) {
throw new HttpException(SR.GetString(SR.Content_allowed_in_top_level_only));
}
}
// Remove existing controls.
owner.Controls.Clear();
}
// Make sure the control collection is writable.
if (owner.Controls.IsReadOnly) {
throw new HttpException(SR.GetString(SR.MasterPage_Cannot_ApplyTo_ReadOnly_Collection));
}
if (contentTemplateCollection != null) {
foreach(String contentName in contentTemplateCollection.Keys) {
if (!master.ContentPlaceHolders.Contains(contentName.ToLower(CultureInfo.InvariantCulture))) {
throw new HttpException(SR.GetString(SR.MasterPage_doesnt_have_contentplaceholder, contentName, masterPageFile));
}
}
master._contentTemplates = contentTemplateCollection;
}
master._ownerControl = owner;
master.InitializeAsUserControl(owner.Page);
owner.Controls.Add(master);
return master;
}
internal static void ApplyMasterRecursive(MasterPage master, IList appliedMasterFilePaths) {
Debug.Assert(appliedMasterFilePaths != null);
// Recursively apply master pages to the nested masterpages.
if (master.Master != null) {
string pageFile = master._masterPageFile.VirtualPathString.ToLower(CultureInfo.InvariantCulture);
if (appliedMasterFilePaths.Contains(pageFile)) {
throw new InvalidOperationException(SR.GetString(SR.MasterPage_Circular_Master_Not_Allowed, master._masterPageFile));
}
appliedMasterFilePaths.Add(pageFile);
ApplyMasterRecursive(master.Master, appliedMasterFilePaths);
}
master._masterPageApplied = true;
}
public void InstantiateInContentPlaceHolder(Control contentPlaceHolder, ITemplate template) {
HttpContext context = HttpContext.Current;
// Remember the old TemplateControl
TemplateControl oldControl = context.TemplateControl;
// Storing the template control into the context
// since each thread needs to set it differently.
context.TemplateControl = _ownerControl;
try {
// Instantiate the template using the correct TemplateControl
template.InstantiateIn(contentPlaceHolder);
}
finally {
// Revert back to the old templateControl
context.TemplateControl = oldControl;
}
}
}
}
|