Welcome to Windows Communication Foundation (WCF)
Top Tasks :

WCF Team Bloggers

Browse by Tags

All Tags » Faults » Service Model   (RSS)

  • Using Faults with Untyped Messages

    When using a typed contract, incoming messages on the server are shredded on your behalf to be turned into method calls and parameters. Ordinarily, the particular method call selected for an application messages will have the same parameterized contract as the message. This allows the transformation between messages and parameters to be made with a high degree of fidelity. However, operations also permit fault responses in addition to the normal application response. The parameterized fault contract is going to look nothing like the standard application contract. Therefore, there's really no transformation that will take you from the fault message to the same parameterized contract in a way that makes any sense. The response that comes back from the server is unrepresentable using the standard data structure that the application is expecting to receive for an application response. This is why with a typed contract fault messages have to be expressed as an exceptional condition. Exceptions tend to transform the message with a much lower fidelity to the original content. With an untyped contract, incoming messages on the server are not shredded on your behalf but rather preserved in their entirety. You can think about this as performing the transformation between messages and parameters with perfect fidelity since the parameter is equal to the message. Similarly, any message response, whether it's a fault response or a normal application response, is also going to be representable with perfect fidelity. Both types of responses have the same format with an untyped contract so the application can handle them equally well. This is why with an untyped contract fault messages are preserved as messages. One of the major reasons for using untyped contracts is to have great fidelity with the wire. It wouldn't make sense to force the application to lose that fidelity for a certain class of messages. If you choose to in your application though, you can still run the same exception machinery. For details, read some of the past articles on creating and consuming faults . Next time: Streaming Web Content Read More...
  • Using Call Context Initializers for Culture

    Let's build on a few earlier samples to actually demonstrate a working call context initializer. I'll start with yesterday's skeleton for a call context initializer and behavior . To that skeleton I'll add implementations of BeforeInvoke and AfterInvoke that initialize the operation thread with custom culture information and then clean the thread up once the operation return. class CultureInitializer : ICallContextInitializer { CultureInfo newInfo; public CultureInitializer(CultureInfo newInfo) { this .newInfo = newInfo; } public void AfterInvoke( object correlationState) { Thread.CurrentThread.CurrentCulture = correlationState as CultureInfo; } public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message) { CultureInfo oldInfo = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = newInfo; return oldInfo; } } Then, I'll fill out ApplyDispatchBehavior to apply my call context initializer to every operation on the given endpoint. class CultureInitializerBehavior : IEndpointBehavior { CultureInfo newInfo; public CultureInitializerBehavior(CultureInfo newInfo) { this .newInfo = newInfo; } public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { foreach (DispatchOperation operation in endpointDispatcher.DispatchRuntime.Operations) { operation.CallContextInitializers.Add( new CultureInitializer(newInfo)); } } public void Validate(ServiceEndpoint endpoint) { } } Finally, I'll take last week's custom fault encoding sample and install my behavior. Notice that the only change at the service level is to add the behavior to the endpoint behavior collection. If I had written the code to apply the behavior in an attribute or configuration file, either of those approaches would have worked as well. [ServiceContract] public interface IMyService { [OperationContract] Message Fail(); } public class MyService : IMyService { public Message Fail() { XmlDocument document = new XmlDocument(); document.LoadXml( "<tag attributeName=\"value\"><moretags>blah</moretags></tag>" ); throw new FaultException<XmlElement>(document.FirstChild as XmlElement); } } public class Program { static void Main( string [] args) { string address = "http://localhost:8000/" Read More...
  • Embedding Arbitrary XML in Faults

    How can I directly craft the XML content that goes into a fault detail? Getting control over the detail element doesn't have to mean crafting the fault message yourself. While WCF requires that the fault detail be serializable using a data contract, remember that DataContractSerializer treats XmlElement as a special primitive type. This allows you to construct arbitrary content using XmlElement when your content can be represented as a rooted document. Due to the automatic conversion process of FaultException to a fault message, you don't need to construct a data contract to act as a wrapper. Here's a sample that builds some content in an XmlElement and uses it to construct a fault. I made the method return a Message so that I could look at the response more easily but you can use any contract you want. [ServiceContract] public interface IMyService { [OperationContract] Message Fail(); } public class MyService : IMyService { public Message Fail() { XmlDocument document = new XmlDocument(); XmlElement root = document.CreateElement( "tag" ); root.SetAttribute( "attributeName" , "value" ); XmlElement subtag = document.CreateElement( "moretags" ); subtag.InnerText = "blah" ; root.AppendChild(subtag); throw new FaultException<XmlElement>(root); } } public class Program { static void Main( string [] args) { string address = "http://localhost:8000/" ; BasicHttpBinding binding = new BasicHttpBinding(); ServiceHost host = new ServiceHost( typeof (MyService), new Uri(address)); host.AddServiceEndpoint( typeof (IMyService), binding, "" ); host.Open(); ChannelFactory<IMyService> factory = new ChannelFactory<IMyService>(binding); IMyService proxy = factory.CreateChannel( new EndpointAddress(address)); Message response = proxy.Fail(); Console.WriteLine(response.ToString()); Console.ReadLine(); host.Close(); } } That code produces a fault message that looks like the following. < s:Envelope xmlns:s ="http://schemas.xmlsoap.org/soap/envelope/" > < s:Header /> < s:Body > < s:Fault > < faultcode > s:Client </ faultcode > < faultstring xml:lang ="en-US" > The creator of this fault did not specify a Reason. </ faultstring > < detail > < tag attributeName ="value" > < moretags > blah </ moretags > </ tag > </ detail > </ s:Fault > </ s:Body > </ s:Envelope > Depending on how much hand-crafting you want, XmlDocument lets you simplify the process even further. For Read More...
  • Increasing the Maximum Fault Size

    When the service sends a fault message with a large detail, my client is unable to read the fault. Changing the standard settings for the maximum message size doesn't help. How can I read large fault messages? Fault messages have their own special quota that can be configured on the client proxy. For changing the settings of a proxy, you should immediately think about using a behavior. Luckily, that happens to work in this case. There is a MaxFaultSize property on the ClientRuntime, which we can get access to by supplying an IEndpointBehavior. public class SetMaxFaultSizeBehavior : IEndpointBehavior { int size; public SetMaxFaultSizeBehavior( int size) { this .size = size; } public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { clientRuntime.MaxFaultSize = size; } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { } public void Validate(ServiceEndpoint endpoint) { } } Let's use our new behavior to play with fault sizes. I've got a service that sends back a fault with no content, but we still have to deal with however big the rest of the fault message is. Then, the client will try connecting to the service with different maximum fault sizes to see what sizes work and what sizes don't. [ServiceContract] public interface IService { [OperationContract] void Operation(); } public class Service : IService { public void Operation() { throw new FaultException< string >( "" ); } } class Program { static void Main( string [] args) { Binding binding = new BasicHttpBinding(); string uri = "http://localhost:8000/" ; ServiceHost host = new ServiceHost( typeof (Service)); host.AddServiceEndpoint( typeof (IService), new BasicHttpBinding(), uri); host.Open(); int maxFaultSize = 1; while ( true ) { ChannelFactory<IService> factory = new ChannelFactory<IService>(binding, new EndpointAddress(uri)); factory.Endpoint.Behaviors.Add( new SetMaxFaultSizeBehavior(maxFaultSize)); factory.Open(); IService proxy = factory.CreateChannel(); try { proxy.Operation(); } catch (FaultException fault) { Console.WriteLine( "Received fault with maxFaultSize={0}." , maxFaultSize); break ; } catch (QuotaExceededException exception) { Console.WriteLine( "Exceeded quota with maxFaultSize={0}." , maxFaultSize); } finally { factory.Close(); } maxFaultSize++; } host.Close(); Console.ReadLine(); Read More...

Copyright © 2006 Microsoft Corporation. All Rights Reserved. | Terms of Use | Privacy Statement | Contact Us