CallbackBehaviorAttribute.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel
  5. {
  6. using System.ServiceModel.Administration;
  7. using System.ServiceModel.Channels;
  8. using System.ServiceModel.Dispatcher;
  9. using System.ServiceModel.Description;
  10. using System.ServiceModel.Configuration;
  11. using System.Runtime.Serialization;
  12. using System.Collections.ObjectModel;
  13. using System.Collections.Generic;
  14. using System.Threading;
  15. using System.Transactions;
  16. using System.Runtime.CompilerServices;
  17. using System.Globalization;
  18. [AttributeUsage(ServiceModelAttributeTargets.CallbackBehavior)]
  19. public sealed class CallbackBehaviorAttribute : Attribute, IEndpointBehavior
  20. {
  21. ConcurrencyMode concurrencyMode = ConcurrencyMode.Single;
  22. bool includeExceptionDetailInFaults = false;
  23. bool validateMustUnderstand = true;
  24. bool ignoreExtensionDataObject = DataContractSerializerDefaults.IgnoreExtensionDataObject;
  25. int maxItemsInObjectGraph = DataContractSerializerDefaults.MaxItemsInObjectGraph;
  26. bool automaticSessionShutdown = true;
  27. bool useSynchronizationContext = true;
  28. internal static IsolationLevel DefaultIsolationLevel = IsolationLevel.Unspecified;
  29. IsolationLevel transactionIsolationLevel = DefaultIsolationLevel;
  30. bool isolationLevelSet = false;
  31. TimeSpan transactionTimeout = TimeSpan.Zero;
  32. string transactionTimeoutString;
  33. bool transactionTimeoutSet = false;
  34. public bool AutomaticSessionShutdown
  35. {
  36. get { return this.automaticSessionShutdown; }
  37. set { this.automaticSessionShutdown = value; }
  38. }
  39. public IsolationLevel TransactionIsolationLevel
  40. {
  41. get { return this.transactionIsolationLevel; }
  42. set
  43. {
  44. switch (value)
  45. {
  46. case IsolationLevel.Serializable:
  47. case IsolationLevel.RepeatableRead:
  48. case IsolationLevel.ReadCommitted:
  49. case IsolationLevel.ReadUncommitted:
  50. case IsolationLevel.Unspecified:
  51. case IsolationLevel.Chaos:
  52. case IsolationLevel.Snapshot:
  53. break;
  54. default:
  55. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value"));
  56. }
  57. this.transactionIsolationLevel = value;
  58. isolationLevelSet = true;
  59. }
  60. }
  61. internal bool IsolationLevelSet
  62. {
  63. get { return this.isolationLevelSet; }
  64. }
  65. public bool IncludeExceptionDetailInFaults
  66. {
  67. get { return this.includeExceptionDetailInFaults; }
  68. set { this.includeExceptionDetailInFaults = value; }
  69. }
  70. public ConcurrencyMode ConcurrencyMode
  71. {
  72. get { return this.concurrencyMode; }
  73. set
  74. {
  75. if (!ConcurrencyModeHelper.IsDefined(value))
  76. {
  77. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value"));
  78. }
  79. this.concurrencyMode = value;
  80. }
  81. }
  82. public string TransactionTimeout
  83. {
  84. get { return transactionTimeoutString; }
  85. set
  86. {
  87. if (value == null)
  88. {
  89. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value"));
  90. }
  91. try
  92. {
  93. TimeSpan timeout = TimeSpan.Parse(value, CultureInfo.InvariantCulture);
  94. if (timeout < TimeSpan.Zero)
  95. {
  96. string message = SR.GetString(SR.SFxTimeoutOutOfRange0);
  97. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value, message));
  98. }
  99. this.transactionTimeout = timeout;
  100. this.transactionTimeoutString = value;
  101. this.transactionTimeoutSet = true;
  102. }
  103. catch (FormatException e)
  104. {
  105. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.SFxTimeoutInvalidStringFormat), "value", e));
  106. }
  107. catch (OverflowException)
  108. {
  109. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value"));
  110. }
  111. }
  112. }
  113. internal bool TransactionTimeoutSet
  114. {
  115. get { return this.transactionTimeoutSet; }
  116. }
  117. public bool UseSynchronizationContext
  118. {
  119. get { return this.useSynchronizationContext; }
  120. set { this.useSynchronizationContext = value; }
  121. }
  122. public bool ValidateMustUnderstand
  123. {
  124. get { return validateMustUnderstand; }
  125. set { validateMustUnderstand = value; }
  126. }
  127. public bool IgnoreExtensionDataObject
  128. {
  129. get { return ignoreExtensionDataObject; }
  130. set { ignoreExtensionDataObject = value; }
  131. }
  132. public int MaxItemsInObjectGraph
  133. {
  134. get { return maxItemsInObjectGraph; }
  135. set { maxItemsInObjectGraph = value; }
  136. }
  137. [MethodImpl(MethodImplOptions.NoInlining)]
  138. void SetIsolationLevel(ChannelDispatcher channelDispatcher)
  139. {
  140. if (channelDispatcher == null)
  141. {
  142. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("channelDispatcher");
  143. }
  144. channelDispatcher.TransactionIsolationLevel = this.transactionIsolationLevel;
  145. }
  146. void IEndpointBehavior.Validate(ServiceEndpoint serviceEndpoint)
  147. {
  148. }
  149. void IEndpointBehavior.AddBindingParameters(ServiceEndpoint serviceEndpoint, BindingParameterCollection parameters)
  150. {
  151. }
  152. void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime clientRuntime)
  153. {
  154. if (!serviceEndpoint.Contract.IsDuplex())
  155. {
  156. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(
  157. SR.SFxCallbackBehaviorAttributeOnlyOnDuplex, serviceEndpoint.Contract.Name)));
  158. }
  159. DispatchRuntime dispatchRuntime = clientRuntime.DispatchRuntime;
  160. dispatchRuntime.ValidateMustUnderstand = validateMustUnderstand;
  161. dispatchRuntime.ConcurrencyMode = this.concurrencyMode;
  162. dispatchRuntime.ChannelDispatcher.IncludeExceptionDetailInFaults = this.includeExceptionDetailInFaults;
  163. dispatchRuntime.AutomaticInputSessionShutdown = this.automaticSessionShutdown;
  164. if (!this.useSynchronizationContext)
  165. {
  166. dispatchRuntime.SynchronizationContext = null;
  167. }
  168. dispatchRuntime.ChannelDispatcher.TransactionTimeout = transactionTimeout;
  169. if (isolationLevelSet)
  170. {
  171. SetIsolationLevel(dispatchRuntime.ChannelDispatcher);
  172. }
  173. DataContractSerializerServiceBehavior.ApplySerializationSettings(serviceEndpoint, this.ignoreExtensionDataObject, this.maxItemsInObjectGraph);
  174. }
  175. void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher)
  176. {
  177. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  178. SR.GetString(SR.SFXEndpointBehaviorUsedOnWrongSide, typeof(CallbackBehaviorAttribute).Name)));
  179. }
  180. }
  181. }