2 // System.Web.UI.TemplateControl.cs
5 // Duncan Mak (duncan@ximian.com)
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // Andreas Nahr (ClassDevelopment@A-SoftTech.com)
9 // (C) 2002 Ximian, Inc. (http://www.ximian.com)
10 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Collections;
33 using System.ComponentModel;
34 using System.Reflection;
35 using System.Security.Permissions;
36 using System.Web.Compilation;
37 using System.Web.Util;
41 namespace System.Web.UI {
44 [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
45 [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
47 public abstract class TemplateControl : Control, INamingContainer, IFilterResolutionService {
49 public abstract class TemplateControl : Control, INamingContainer {
51 static readonly Assembly _System_Web_Assembly = typeof (TemplateControl).Assembly;
52 static object abortTransaction = new object ();
53 static object commitTransaction = new object ();
54 static object error = new object ();
55 static string [] methodNames = { "Page_Init",
60 "Page_PreRenderComplete",
61 "Page_SaveStateComplete",
70 "Page_AbortTransaction",
71 "Page_CommitTransaction"};
73 const BindingFlags bflags = BindingFlags.Public |
74 BindingFlags.NonPublic |
75 BindingFlags.Instance;
78 string _appRelativeVirtualPath;
82 protected TemplateControl ()
85 TemplateControl = this;
93 [EditorBrowsable (EditorBrowsableState.Never)]
97 protected virtual int AutoHandlers {
102 [EditorBrowsable (EditorBrowsableState.Never)]
103 protected virtual bool SupportAutoEvents {
108 public string AppRelativeVirtualPath {
109 get { return _appRelativeVirtualPath; }
110 set { _appRelativeVirtualPath = value; }
118 protected virtual void Construct ()
122 [MonoTODO ("Not implemented")]
123 protected LiteralControl CreateResourceBasedLiteralControl (int offset,
131 public MethodInfo method;
132 public string methodName;
133 public EventInfo evt;
134 public bool noParams;
137 static Hashtable auto_event_info;
138 static object auto_event_info_monitor = new Object ();
140 internal void WireupAutomaticEvents ()
142 if (!SupportAutoEvents || !AutoEventWireup)
145 ArrayList events = null;
147 /* Avoid expensive reflection operations by computing the event info only once */
148 lock (auto_event_info_monitor) {
149 if (auto_event_info == null)
150 auto_event_info = new Hashtable ();
151 events = (ArrayList)auto_event_info [GetType ()];
152 if (events == null) {
153 events = CollectAutomaticEventInfo ();
154 auto_event_info [GetType ()] = events;
158 for (int i = 0; i < events.Count; ++i) {
159 EvtInfo evinfo = (EvtInfo)events [i];
160 if (evinfo.noParams) {
161 NoParamsInvoker npi = new NoParamsInvoker (this, evinfo.method);
162 evinfo.evt.AddEventHandler (this, npi.FakeDelegate);
164 evinfo.evt.AddEventHandler (this, Delegate.CreateDelegate (
166 typeof (EventHandler), this, evinfo.method));
168 typeof (EventHandler), this, evinfo.methodName));
174 private ArrayList CollectAutomaticEventInfo () {
175 ArrayList events = new ArrayList ();
177 foreach (string methodName in methodNames) {
178 MethodInfo method = null;
180 for (type = GetType (); type.Assembly != _System_Web_Assembly; type = type.BaseType) {
181 method = type.GetMethod (methodName, bflags);
188 if (method.DeclaringType != type) {
189 if (!method.IsPublic && !method.IsFamilyOrAssembly &&
190 !method.IsFamilyAndAssembly && !method.IsFamily)
194 if (method.ReturnType != typeof (void))
197 ParameterInfo [] parms = method.GetParameters ();
198 int length = parms.Length;
199 bool noParams = (length == 0);
200 if (!noParams && (length != 2 ||
201 parms [0].ParameterType != typeof (object) ||
202 parms [1].ParameterType != typeof (EventArgs)))
205 int pos = methodName.IndexOf ("_");
206 string eventName = methodName.Substring (pos + 1);
207 EventInfo evt = type.GetEvent (eventName);
209 /* This should never happen */
213 EvtInfo evinfo = new EvtInfo ();
214 evinfo.method = method;
215 evinfo.methodName = methodName;
217 evinfo.noParams = noParams;
225 [EditorBrowsable (EditorBrowsableState.Never)]
226 protected virtual void FrameworkInitialize ()
230 Type GetTypeFromControlPath (string virtualPath)
232 if (virtualPath == null)
233 throw new ArgumentNullException ("virtualPath");
235 string vpath = UrlUtils.Combine (TemplateSourceDirectory, virtualPath);
237 return BuildManager.GetCompiledType (vpath);
239 string realpath = Context.Request.MapPath (vpath);
240 return UserControlParser.GetCompiledType (vpath, realpath, Context);
244 public Control LoadControl (string virtualPath)
247 if (virtualPath == null)
248 throw new ArgumentNullException ("virtualPath");
250 if (virtualPath == null)
251 throw new HttpException ("virtualPath is null");
253 Type type = GetTypeFromControlPath (virtualPath);
255 return LoadControl (type, null);
258 public Control LoadControl (Type type, object[] parameters)
260 object [] attrs = null;
263 type.GetCustomAttributes (typeof (PartialCachingAttribute), true);
264 if (attrs != null && attrs.Length == 1) {
265 PartialCachingAttribute attr = (PartialCachingAttribute) attrs [0];
266 PartialCachingControl ctrl = new PartialCachingControl (type, parameters);
267 ctrl.VaryByParams = attr.VaryByParams;
268 ctrl.VaryByControls = attr.VaryByControls;
269 ctrl.VaryByCustom = attr.VaryByCustom;
273 object control = Activator.CreateInstance (type, parameters);
274 if (control is UserControl)
275 ((UserControl) control).InitializeAsUserControl (Page);
277 return (Control) control;
280 public ITemplate LoadTemplate (string virtualPath)
283 if (virtualPath == null)
284 throw new ArgumentNullException ("virtualPath");
286 if (virtualPath == null)
287 throw new HttpException ("virtualPath is null");
289 Type t = GetTypeFromControlPath (virtualPath);
290 return new SimpleTemplate (t);
293 protected virtual void OnAbortTransaction (EventArgs e)
295 EventHandler eh = Events [abortTransaction] as EventHandler;
300 protected virtual void OnCommitTransaction (EventArgs e)
302 EventHandler eh = Events [commitTransaction] as EventHandler;
307 protected virtual void OnError (EventArgs e)
309 EventHandler eh = Events [error] as EventHandler;
315 [MonoTODO ("Not implemented, always returns null")]
317 public Control ParseControl (string content)
320 throw new ArgumentNullException ("content");
323 // FIXME: This method needs to be rewritten in some sane way - the way it is now,
324 // is a kludge. New version should not use
325 // UserControlParser.GetCompiledType, but instead resort to some other way
326 // of creating the content (template instantiation? BuildManager? TBD)
327 TextReader reader = new StringReader (content);
328 Type control = UserControlParser.GetCompiledType (reader, HttpContext.Current);
332 TemplateControl parsedControl = Activator.CreateInstance (control, null) as TemplateControl;
333 if (parsedControl == null)
336 if (this is System.Web.UI.Page)
337 parsedControl.Page = (System.Web.UI.Page) this;
338 parsedControl.FrameworkInitialize ();
340 Control ret = new Control ();
341 int count = parsedControl.Controls.Count;
342 Control[] parsedControlControls = new Control [count];
343 parsedControl.Controls.CopyTo (parsedControlControls, 0);
345 for (int i = 0; i < count; i++)
346 ret.Controls.Add (parsedControlControls [i]);
348 parsedControl = null;
356 [MonoTODO ("Parser filters not implemented yet. Calls ParseControl (string) for now.")]
357 public Control ParseControl (string content, bool ignoreParserFilter)
359 return ParseControl (content);
363 [EditorBrowsable (EditorBrowsableState.Never)]
368 object ReadStringResource ()
370 throw new NotSupportedException ();
374 protected object GetGlobalResourceObject (string className, string resourceKey)
376 return HttpContext.GetGlobalResourceObject (className, resourceKey);
379 protected object GetGlobalResourceObject (string className, string resourceKey, Type objType, string propName)
381 if (String.IsNullOrEmpty (resourceKey) || String.IsNullOrEmpty (propName) ||
382 String.IsNullOrEmpty (className) || objType == null)
385 object globalObject = GetGlobalResourceObject (className, resourceKey);
386 if (globalObject == null)
389 TypeConverter converter = TypeDescriptor.GetProperties (objType) [propName].Converter;
390 if (converter == null || !converter.CanConvertFrom (globalObject.GetType ()))
393 return converter.ConvertFrom (globalObject);
396 protected object GetLocalResourceObject (string resourceKey)
398 return HttpContext.GetLocalResourceObject (VirtualPathUtility.ToAbsolute (this.AppRelativeVirtualPath),
402 protected object GetLocalResourceObject (string resourceKey, Type objType, string propName)
404 if (String.IsNullOrEmpty (resourceKey) || String.IsNullOrEmpty (propName) || objType == null)
407 object localObject = GetLocalResourceObject (resourceKey);
408 if (localObject == null)
411 TypeConverter converter = TypeDescriptor.GetProperties (objType) [propName].Converter;
412 if (converter == null || !converter.CanConvertFrom (localObject.GetType ()))
415 return converter.ConvertFrom (localObject);
418 internal override TemplateControl TemplateControlInternal {
423 [EditorBrowsable (EditorBrowsableState.Never)]
424 public static object ReadStringResource (Type t)
426 throw new NotSupportedException ();
429 [MonoTODO ("Not implemented, does nothing")]
430 [EditorBrowsable (EditorBrowsableState.Never)]
431 protected void SetStringResourcePointer (object stringResourcePointer,
432 int maxResourceOffset)
436 [MonoTODO ("Not implemented, does nothing")]
437 [EditorBrowsable (EditorBrowsableState.Never)]
438 protected void WriteUTF8ResourceString (HtmlTextWriter output, int offset,
439 int size, bool fAsciiOnly)
447 [WebSysDescription ("Raised when the user aborts a transaction.")]
448 public event EventHandler AbortTransaction {
449 add { Events.AddHandler (abortTransaction, value); }
450 remove { Events.RemoveHandler (abortTransaction, value); }
453 [WebSysDescription ("Raised when the user initiates a transaction.")]
454 public event EventHandler CommitTransaction {
455 add { Events.AddHandler (commitTransaction, value); }
456 remove { Events.RemoveHandler (commitTransaction, value); }
459 [WebSysDescription ("Raised when an exception occurs that cannot be handled.")]
460 public event EventHandler Error {
461 add { Events.AddHandler (error, value); }
462 remove { Events.RemoveHandler (error, value); }
467 class SimpleTemplate : ITemplate
471 public SimpleTemplate (Type type)
476 public void InstantiateIn (Control control)
478 Control template = Activator.CreateInstance (type) as Control;
479 template.SetBindingContainer (false);
480 control.Controls.Add (template);
485 protected internal object Eval (string expression)
487 return DataBinder.Eval (Page.GetDataItem(), expression);
490 protected internal string Eval (string expression, string format)
492 return DataBinder.Eval (Page.GetDataItem(), expression, format);
495 protected internal object XPath (string xpathexpression)
497 return XPathBinder.Eval (Page.GetDataItem(), xpathexpression);
500 protected internal object XPath (string xpathexpression, IXmlNamespaceResolver resolver)
502 return XPathBinder.Eval (Page.GetDataItem (), xpathexpression, null, resolver);
505 protected internal string XPath (string xpathexpression, string format)
507 return XPathBinder.Eval (Page.GetDataItem(), xpathexpression, format);
510 protected internal string XPath (string xpathexpression, string format, IXmlNamespaceResolver resolver)
512 return XPathBinder.Eval (Page.GetDataItem (), xpathexpression, format, resolver);
515 protected internal IEnumerable XPathSelect (string xpathexpression)
517 return XPathBinder.Select (Page.GetDataItem(), xpathexpression);
520 protected internal IEnumerable XPathSelect (string xpathexpression, IXmlNamespaceResolver resolver)
522 return XPathBinder.Select (Page.GetDataItem (), xpathexpression, resolver);
525 // IFilterResolutionService
527 [MonoTODO ("Not implemented")]
528 int IFilterResolutionService.CompareFilters (string filter1, string filter2)
530 throw new NotImplementedException ();
533 [MonoTODO ("Not implemented")]
534 bool IFilterResolutionService.EvaluateFilter (string filterName)
536 throw new NotImplementedException ();