1 //------------------------------------------------------------------------------ 2 // <copyright file="AsyncPostBackTrigger.cs" company="Microsoft"> 3 // Copyright (c) Microsoft Corporation. All rights reserved. 4 // </copyright> 5 //------------------------------------------------------------------------------ 6 7 namespace System.Web.UI { 8 using System; 9 using System.ComponentModel; 10 using System.Diagnostics.CodeAnalysis; 11 using System.Globalization; 12 using System.Reflection; 13 using System.Web; 14 using System.Web.UI; 15 using System.Web.Resources; 16 using System.Web.Util; 17 18 public class AsyncPostBackTrigger : UpdatePanelControlTrigger { 19 20 private IScriptManagerInternal _scriptManager; 21 22 private Control _associatedControl; 23 private static MethodInfo _eventHandler; 24 private bool _eventHandled; 25 private string _eventName; 26 AsyncPostBackTrigger()27 public AsyncPostBackTrigger() { 28 } 29 AsyncPostBackTrigger(IScriptManagerInternal scriptManager)30 internal AsyncPostBackTrigger(IScriptManagerInternal scriptManager) { 31 _scriptManager = scriptManager; 32 } 33 34 private static MethodInfo EventHandler { 35 get { 36 if (_eventHandler == null) { 37 _eventHandler = typeof(AsyncPostBackTrigger).GetMethod("OnEvent"); 38 } 39 return _eventHandler; 40 } 41 } 42 43 [ 44 SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "ID"), 45 TypeConverter("System.Web.UI.Design.AsyncPostBackTriggerControlIDConverter, " + 46 AssemblyRef.SystemWebExtensionsDesign) 47 ] 48 public new string ControlID { 49 get { 50 return base.ControlID; 51 } 52 set { 53 base.ControlID = value; 54 } 55 } 56 57 [ 58 DefaultValue(""), 59 Category("Behavior"), 60 ResourceDescription("AsyncPostBackTrigger_EventName"), 61 TypeConverter("System.Web.UI.Design.AsyncPostBackTriggerEventNameConverter, " + 62 AssemblyRef.SystemWebExtensionsDesign), 63 ] 64 public string EventName { 65 get { 66 if (_eventName == null) { 67 return String.Empty; 68 } 69 return _eventName; 70 } 71 set { 72 _eventName = value; 73 } 74 } 75 76 internal IScriptManagerInternal ScriptManager { 77 get { 78 if (_scriptManager == null) { 79 Page page = Owner.Page; 80 if (page == null) { 81 throw new InvalidOperationException(AtlasWeb.Common_PageCannotBeNull); 82 } 83 _scriptManager = UI.ScriptManager.GetCurrent(page); 84 if (_scriptManager == null) { 85 throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, AtlasWeb.Common_ScriptManagerRequired, Owner.ID)); 86 } 87 } 88 return _scriptManager; 89 } 90 } 91 Initialize()92 protected internal override void Initialize() { 93 base.Initialize(); 94 95 _associatedControl = FindTargetControl(true); 96 97 ScriptManager.RegisterAsyncPostBackControl(_associatedControl); 98 99 string eventName = EventName; 100 if (eventName.Length != 0) { 101 // If EventName is specified, attach our event handler to it 102 EventInfo eventInfo = _associatedControl.GetType().GetEvent(eventName, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public); 103 if (eventInfo == null) { 104 throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, AtlasWeb.AsyncPostBackTrigger_CannotFindEvent, eventName, ControlID, Owner.ID)); 105 } 106 107 MethodInfo handlerMethod = eventInfo.EventHandlerType.GetMethod("Invoke"); 108 ParameterInfo[] parameters = handlerMethod.GetParameters(); 109 if (!handlerMethod.ReturnType.Equals(typeof(void)) || 110 (parameters.Length != 2) || 111 (typeof(EventArgs).IsAssignableFrom(parameters[1].ParameterType) == false)) { 112 throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, AtlasWeb.AsyncPostBackTrigger_InvalidEvent, eventName, ControlID, Owner.ID)); 113 } 114 115 Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, this, EventHandler); 116 eventInfo.AddEventHandler(_associatedControl, handler); 117 } 118 } 119 HasTriggered()120 protected internal override bool HasTriggered() { 121 if (!String.IsNullOrEmpty(EventName)) { 122 // If EventName is specified we are triggered if our event was raised 123 return _eventHandled; 124 } 125 else { 126 // If EventName is not specified, check if the control that caused the 127 // postback either has the exact UniqueID we're looking for, or at least 128 // begins with it. 129 string sourceElement = ScriptManager.AsyncPostBackSourceElementID; 130 return 131 (sourceElement == _associatedControl.UniqueID) || 132 (sourceElement.StartsWith(_associatedControl.UniqueID + "$", StringComparison.Ordinal)); 133 } 134 } 135 136 // DevDiv Bugs 127369: This method should be private and the reflection lookup should assert reflection permission 137 // so the private reflection works in medium trust. 138 // However, ASP.NET AJAX 1.0 was released with this method public. Since it would be a breaking change to make it private 139 // now, it was decided to leave it as is. 140 [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", 141 Justification="TODO: This will be fixed in fc_serverfx")] OnEvent(object sender, EventArgs e)142 public void OnEvent(object sender, EventArgs e) { 143 _eventHandled = true; 144 } 145 146 [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")] ToString()147 public override string ToString() { 148 if (String.IsNullOrEmpty(ControlID)) { 149 return "AsyncPostBack"; 150 } 151 else { 152 return "AsyncPostBack: " + ControlID + 153 (String.IsNullOrEmpty(EventName) ? String.Empty : ("." + EventName)); 154 } 155 } 156 } 157 } 158