Skip to content

Commit aafd91a

Browse files
authored
Expose IErrorHandler and add test case. (#5593)
* Expose IErrorHandler and add test case. * Update: only add to the netcoreapp ref assembly. * Remove INTERNAL EnableFaults from ClientRuntime in the ref project.
1 parent 906a323 commit aafd91a

File tree

9 files changed

+204
-0
lines changed

9 files changed

+204
-0
lines changed

src/System.Private.ServiceModel/tests/Common/Scenarios/Endpoints.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,11 @@ public static string DuplexCallbackDebugBehavior_Address
766766
{
767767
get { return GetEndpointAddress("DuplexCallbackDebugBehavior.svc/tcp", protocol: "net.tcp"); }
768768
}
769+
770+
public static string DuplexCallbackErrorHandler_Address
771+
{
772+
get { return GetEndpointAddress("DuplexCallbackErrorHandler.svc/tcp", protocol: "net.tcp"); }
773+
}
769774
#endregion net.tcp Addresses
770775

771776
#region net.pipe Addresses

src/System.Private.ServiceModel/tests/Common/Scenarios/ScenarioTestTypes.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using System.ServiceModel;
1414
using System.ServiceModel.Channels;
1515
using System.ServiceModel.Description;
16+
using System.ServiceModel.Dispatcher;
1617
using System.Text;
1718
using System.Threading;
1819
using System.Threading.Tasks;
@@ -287,6 +288,11 @@ public static void Run(Func<Task> asyncMethod)
287288
}
288289
}
289290

291+
[DataContract]
292+
public class CustomMessage
293+
{
294+
}
295+
290296
[DataContract(Namespace = "http://www.contoso.com/wcfnamespace")]
291297
public class CompositeType
292298
{
@@ -705,6 +711,53 @@ public void ReplyThrow(string input)
705711
}
706712
}
707713

714+
[CallbackBehavior(UseSynchronizationContext = false)]
715+
public class WcfDuplexService_CallbackErrorHandler_Callback : IWcfDuplexService_CallbackErrorHandler_Callback, IEndpointBehavior, IErrorHandler
716+
{
717+
public void ReplyThrow(string input)
718+
{
719+
throw new FaultException<ArgumentException>(new ArgumentException());
720+
}
721+
722+
void IEndpointBehavior.AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
723+
{
724+
return;
725+
}
726+
727+
void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
728+
{
729+
clientRuntime.CallbackDispatchRuntime.ChannelDispatcher.ErrorHandlers.Add(this);
730+
}
731+
732+
void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
733+
{
734+
return;
735+
}
736+
737+
void IEndpointBehavior.Validate(ServiceEndpoint endpoint)
738+
{
739+
return;
740+
}
741+
742+
#region IErrorHandler Members
743+
public bool HandleError(Exception error)
744+
{
745+
return true;
746+
}
747+
748+
public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
749+
{
750+
if (error is FaultException<ArgumentException>)
751+
{
752+
//overriding the given fault to CustomMessage fault
753+
var faultObj = new FaultException<CustomMessage>(new CustomMessage(), "custom fault reason", new FaultCode("custom fault code"));
754+
MessageFault fault = faultObj.CreateMessageFault();
755+
msg = Message.CreateMessage(version, fault, "http://tempuri.org/IWcfDuplexService_CallbackErrorHandler/ReplyThrowCustomMessageFault");
756+
}
757+
}
758+
#endregion
759+
}
760+
708761
public class DuplexTaskReturnServiceCallback : IWcfDuplexTaskReturnCallback
709762
{
710763
private bool _wrapExceptionInTask;

src/System.Private.ServiceModel/tests/Common/Scenarios/ServiceInterfaces.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,19 @@ public interface IWcfDuplexService_CallbackDebugBehavior_Callback
352352
void ReplyThrow(string input);
353353
}
354354

355+
[ServiceContract(CallbackContract = typeof(IWcfDuplexService_CallbackErrorHandler_Callback))]
356+
public interface IWcfDuplexService_CallbackErrorHandler
357+
{
358+
[OperationContract]
359+
bool Hello(string greeting);
360+
}
361+
362+
public interface IWcfDuplexService_CallbackErrorHandler_Callback
363+
{
364+
[OperationContract]
365+
void ReplyThrow(string input);
366+
}
367+
355368
[ServiceContract(CallbackContract = typeof(IWcfDuplexTaskReturnCallback))]
356369
public interface IWcfDuplexTaskReturnService
357370
{
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
6+
using System.ServiceModel;
7+
using Infrastructure.Common;
8+
using Xunit;
9+
10+
public partial class CallbackErrorHandlerTests : ConditionalWcfTest
11+
{
12+
[WcfFact]
13+
public static void DuplexCallbackErrorHandlerTest()
14+
{
15+
bool result;
16+
InstanceContext context;
17+
string testString="";
18+
NetTcpBinding binding;
19+
EndpointAddress endpointAddress;
20+
DuplexChannelFactory<IWcfDuplexService_CallbackErrorHandler> factory;
21+
IWcfDuplexService_CallbackErrorHandler serviceProxy;
22+
WcfDuplexService_CallbackErrorHandler_Callback callbackService;
23+
24+
// *** SETUP *** \\
25+
binding = new NetTcpBinding();
26+
binding.Security.Mode = SecurityMode.None;
27+
callbackService = new WcfDuplexService_CallbackErrorHandler_Callback();
28+
context = new InstanceContext(callbackService);
29+
endpointAddress = new EndpointAddress(Endpoints.DuplexCallbackErrorHandler_Address);
30+
factory = new DuplexChannelFactory<IWcfDuplexService_CallbackErrorHandler>(context, binding, endpointAddress);
31+
serviceProxy = factory.CreateChannel();
32+
33+
try
34+
{
35+
// *** EXECUTE *** \\
36+
result = serviceProxy.Hello(testString);
37+
38+
// *** CLEANUP *** \\
39+
((ICommunicationObject)serviceProxy).Close();
40+
factory.Close();
41+
}
42+
finally
43+
{
44+
// *** ENSURE CLEANUP *** \\
45+
ScenarioTestHelpers.CloseCommunicationObjects((ICommunicationObject)serviceProxy, factory);
46+
}
47+
48+
// *** ADDITIONAL VALIDATION *** \\
49+
Assert.True(result);
50+
}
51+
}

src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/CompositeType.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,3 +372,8 @@ public PingEncodedRequest(string pinginfo)
372372
this.Pinginfo = pinginfo;
373373
}
374374
}
375+
376+
[DataContract]
377+
public class CustomMessage
378+
{
379+
}

src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/IWcfDuplexService.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,18 @@ public interface IWcfDuplexService_CallbackDebugBehavior_Callback
115115
[OperationContract]
116116
void ReplyThrow(string input);
117117
}
118+
119+
[ServiceContract(CallbackContract = typeof(IWcfDuplexService_CallbackErrorHandler_Callback))]
120+
public interface IWcfDuplexService_CallbackErrorHandler
121+
{
122+
[OperationContract]
123+
bool Hello(string greeting);
124+
}
125+
126+
public interface IWcfDuplexService_CallbackErrorHandler_Callback
127+
{
128+
[OperationContract]
129+
[FaultContract(typeof(CustomMessage))]
130+
void ReplyThrow(string input);
131+
}
118132
}

src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/WcfDuplexService.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,37 @@ public IWcfDuplexService_CallbackDebugBehavior_Callback Callback
149149
}
150150
}
151151
}
152+
153+
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
154+
public class WcfDuplexService_CallbackErrorHandler : IWcfDuplexService_CallbackErrorHandler
155+
{
156+
public bool Hello(string greeting)
157+
{
158+
bool result = false;
159+
try
160+
{
161+
Callback.ReplyThrow(greeting);
162+
}
163+
catch (FaultException<CustomMessage> fex)
164+
{
165+
if(fex.Message.Equals("custom fault reason") && fex.Code.Name.Equals("custom fault code"))
166+
{
167+
result = true;
168+
}
169+
}
170+
catch (Exception)
171+
{
172+
}
173+
174+
return result;
175+
}
176+
177+
public IWcfDuplexService_CallbackErrorHandler_Callback Callback
178+
{
179+
get
180+
{
181+
return OperationContext.Current.GetCallbackChannel<IWcfDuplexService_CallbackErrorHandler_Callback>();
182+
}
183+
}
184+
}
152185
}

src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/testhosts/DuplexTestServiceHosts.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,20 @@ public DuplexCallbackDebugBahaviorServiceHost(params Uri[] baseAddresses)
152152
{
153153
}
154154
}
155+
156+
[TestServiceDefinition(Schema = ServiceSchema.NETTCP, BasePath = "DuplexCallbackErrorHandler.svc")]
157+
public class DuplexCallbackErrorHandlerServiceHost : TestServiceHostBase<IWcfDuplexService_CallbackErrorHandler>
158+
{
159+
protected override string Address { get { return "tcp"; } }
160+
161+
protected override Binding GetBinding()
162+
{
163+
return new NetTcpBinding(SecurityMode.None) { PortSharingEnabled = false };
164+
}
165+
166+
public DuplexCallbackErrorHandlerServiceHost(params Uri[] baseAddresses)
167+
: base(typeof(WcfDuplexService_CallbackErrorHandler), baseAddresses)
168+
{
169+
}
170+
}
155171
}

src/System.ServiceModel.Primitives/ref/System.ServiceModel.Primitives.Netcoreapp.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
// Changes to this file must follow the http://aka.ms/api-review process.
55
// ------------------------------------------------------------------------------
66

7+
using System.Collections.ObjectModel;
8+
79
namespace System.ServiceModel
810
{
911
public abstract partial class ChannelFactory : System.IAsyncDisposable
@@ -49,3 +51,15 @@ public abstract partial class SecurityTokenProvider
4951
protected virtual System.Threading.Tasks.Task CancelTokenCoreAsync(System.TimeSpan timeout, System.IdentityModel.Tokens.SecurityToken token) { return default; }
5052
}
5153
}
54+
namespace System.ServiceModel.Dispatcher
55+
{
56+
public partial class ChannelDispatcher
57+
{
58+
public Collection<IErrorHandler> ErrorHandlers { get { return default; } }
59+
}
60+
public interface IErrorHandler
61+
{
62+
void ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault);
63+
bool HandleError(Exception error);
64+
}
65+
}

0 commit comments

Comments
 (0)