Welcome to Windows Communication Foundation (WCF)
Top Tasks :

WCF Team Bloggers

Browse by Tags

All Tags » Service Model » Indigo » Answers   (RSS)

  • No Choice for Data Contracts

    I have a schema file that describes a choice between multiple layout formats for a type. How do I build a proxy that matches this schema? The reason that this is probably not working is because DataContractSerializer for the most part does not support ambiguous, optional, or multiply-described sections of types. Using svcutil and specifying the serializer to be XmlSerializer is more likely to generate the expected proxy type. Here's a rough guide to what DataContractSerializer does not support for complex type content. If you're using any of these features in your schema, then it's likely that you'll need to use XmlSerializer instead. Attributes (pretty much everything related to attributes including groups and wildcards) Group, all, or choice selections Extensions or restrictions of simple content (except for restrictions from anySimpleType) Sequences that are optional or repeating (minOccurs or maxOccurs not equal to 1) Sequences that contain other sequences or wildcard content Next time: Using ETW Tracing Read More...
  • Read Only Data Members

    How do I specify that the client proxy should not have a setter for a particular data member? It doesn't make sense for the service to be able to dictate what the client can do with a piece of data. Once data has been put on the wire, you can't stop the other side that is receiving the message from doing whatever they want with that data. Schema and metadata don't have any notion of access modifiers, but let's say that they did. You might say in the metadata that a certain piece of data has restricted access. First, there's nothing requiring me to use the same metadata and tools that you are, so I may not even know about your access modifiers. The representation that gets written to the wire is the truth about how your service works, not the metadata. Second, even if I am using the same metadata and tools as you are, I can always change the client after it's created because the generated code is something that I own rather than you as the service author. If the client author and the service author are the same person, then there are much more effective ways of providing a preferred programming model than trying to describe those preferences through some aspect of the service description. Instead, just change the client library directly to do what you want and give people that. Next time: Certificate Stores Read More...
  • Waiting for Ready Channels

    When I create a channel to a service, how do I know when the service is ready to process the data for that channel? A channel doesn't really know what the service is doing. The service might be actively processing the data being sent over the channel. Or, the service might not. There is a constant tension in the system between components that want to push data and components that want to pull data. Components that push data actively work as long as there is data available until a back pressure builds up in the system that resists their ability to push. This back pressure is typically the result of some queue or buffer that has filled up and is no longer able to accept the things being pushed into it. Components that push include several transport and protocol channels, as well as the service dispatcher that pushes messages to the service implementation. Components that pull data remain quiescent even if data is available until there is someone that actually wants to consume some data. Many transport and protocol channels pull messages rather than push. A single implementation may feature both push and pull modes. For example, the TCP channel has a small portion that works in a push mode for connection establishment and transferring some initial data while the application portion of TCP works in a pull mode. Depending on the visibility of these push and pull modes, you might be able to tell from the behavior of a particular protocol what the service is doing. For example, if you're using just TCP, then the initial transmissions needed to open a connection can only be completed once a little bit of pulling has been done on the receiving application side, thus telling you that the service is doing some active processing. On the other hand, if you're using a ReliableMessaging channel or a OneWay channel, then those protocols have a visible running state where they are in push mode. You can't actually tell whether the service is working until you fill up some of the buffers in the protocol stack and start getting push back in the form of rejected messages. That means the service is not working as fast as you're sending data. A queued channel would be an extreme example of push mode. A message queue allows you to push large amounts of data when the service is not even running. Therefore, to know in the general case whether the service is ready to process for you, you need to be able to ask that question to the service rather than to the channel. Next time: Composing Read More...
  • Streaming Web Content

    How do I deliver content from a WCF service as part of a web page? Web page content in this case typically refers to HTML, images, or other data that is directly consumed by the web browser rather than an application running in the web browser. There are a few things you need to do to make your web service serve up content in a way that's indistinguishable from an ordinary web server. I'll serve up a static image at a fixed location for this example but you can get as fancy as you'd like. The first thing you need is the right contract. The initial page load is ordinarily retrieved using the HTTP GET verb rather than the HTTP POST verb assumed by web services. I'll set that up as part of my contract using the WebGet attribute to set the verb and a URI template to set the address. [ServiceContract] public interface IService { [OperationContract] [WebGet(UriTemplate = "/image" )] Stream GetImage(); } The second thing you need is the right content type. Although web browsers can try to autodetect content, you should specify the content type if it is known. This allows the web browser to process the content correctly inline. public class Service : IService { public Stream GetImage() { WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg" ; return new FileStream( "c:\\test.jpg" , FileMode.Open, FileAccess.Read); } } Finally, you may notice that while I've done everything needed in the service implementation to enable streaming, content can only be streamed if the binding supports this as well. When using WebServiceHost, the default bindings do not support streamed content. This may be hard to spot because the typical files are small and a test program running on the same machine completes the transfers before streaming would make a difference. I've wrapped the service implementation in this example to intentionally slow down the transfer to make the difference more apparent. The following code demonstrates enabling streaming on the binding. You can change the transfer mode back to Buffered to observe the difference. Streaming requires support in the receiving application as well to make a difference. Using a large, progressive encoded image will demonstrate this. using System; using System.IO; using System.ServiceModel; using System.ServiceModel.Web; using System.Threading; public class SlowStream : Stream { Stream innerStream; public SlowStream(Stream innerStream) { this .innerStream = innerStream; } public override bool CanRead { get { return Read More...
  • Getting Rid of Namespaces

    How do I write a contract for a wrapped message in the default namespace? I've written a quick sample to demonstrate what happens when you write the contract without taking any namespaces into account. [ServiceContract] public interface IService { [OperationContract] [WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "/" )] void ProcessRequest( string data); } public class Service : IService { public void ProcessRequest( string data) { Console.WriteLine(OperationContext.Current.RequestContext.RequestMessage); } } class Program { static void Main( string [] args) { string address = "http://localhost:8000/" ; WebServiceHost host = new WebServiceHost( typeof (Service), new Uri(address)); host.Open(); ChannelFactory<IService> factory = new ChannelFactory<IService>( new WebHttpBinding()); factory.Open(); IService proxy = factory.CreateChannel( new EndpointAddress(address)); using ( new OperationContextScope((IContextChannel)proxy)) { OperationContext.Current.OutgoingMessageHeaders.To = new Uri(address); proxy.ProcessRequest( "data" ); } factory.Close(); host.Close(); Console.ReadLine(); } } Running the sample reveals that the message wrapper gets an unpleasant namespace instead of the default namespace. < ProcessRequest xmlns ="http://tempuri.org/" > < data > data </ data > </ ProcessRequest > By looking at the metadata, you could figure out where this namespace was coming from using the custom namespace sample I published earlier. In this case the problem is with the operation wrapper, which comes from the service contract. Setting the service contract to have a namespace of "" gets us the desired default namespace. Next time: Using Faults with Untyped Messages Read More...
  • Finding a Client Channel

    Where can I get the IContextChannel that OperationContextScope requires? OperationContextScope allows you to create a temporary scope in which context for a service operation can build up before and after the operation is actually called. The constructor for OperationContextScope takes an instance of IContextChannel, which is a type that you've probably never seen before. Why are you expected to have this unknown type? It's because you have instances of it floating around all the time even though there's no particular hint of this. There are different ways to get an IContextChannel depending on whether you're using a proxy generated by svcutil or a proxy generated at runtime. In either case, pretend that I've got service contract called IService with a single method called Foo. When I generate a service client using svcutil, the client object has a member called InnerChannel that works as an IContextChannel. ServiceClient client = new ServiceClient(binding, new EndpointAddress(address)); using ( new OperationContextScope(client.InnerChannel)) { WebOperationContext.Current.OutgoingRequest.Headers[ "X" ] = "from compiled proxy" ; client.Foo(); } client.Close(); Otherwise, if I'm using a ChannelFactory to create the proxy at runtime, the channel that I get back happens to be an IContextChannel as well. ChannelFactory<IService> factory = new ChannelFactory<IService>(binding); factory.Open(); IService proxy = factory.CreateChannel( new EndpointAddress(address)); using ( new OperationContextScope((IContextChannel)proxy)) { WebOperationContext.Current.OutgoingRequest.Headers[ "X" ] = "from runtime proxy" ; proxy.Foo(); } factory.Close(); Next time: Standards Guide Read More...
  • Adding Headers to a Call

    How do I add SOAP headers to an outgoing request? There are a few different ways to add headers to a message depending on how you need to control the header content and where you need to insert the header. I like to think of these methods as being split among the application, the proxy, and the protocol. In your application code you can create an OperationContextScope around the request in order to change some of the request properties. Inside an OperationContextScope, you have a valid instance of OperationContext.Current, which allows manipulation of the message headers through the OutgoingMessageHeaders collection. Use of this method deeply bakes control of the headers into the application code. You would have to be responsible for copying the appropriate code wherever it was needed. Now, assume that you want the header to be present whenever you're talking to a particular service and the header value can be determined consistently. Rather than having to put the same code at each call site, you can centralize the code in the proxy or in a protocol. The simplest way to centralize header manipulation in the proxy is to create an instance of the IClientMessageInspector and attach that to the proxy. This gives you a hook for every message going through the proxy to modify the message headers. An instance of IChannel similarly gives you a hook for every message going through the channel stack to modify the message headers. Using the Message Interceptor sample gives you an extensibility point in the binding that is similar in spirit to the extensibility point provided by a message inspector. The primary difference from your perspective of a message inspector and a channel is a matter of timing. A message inspector always runs before any of the protocols in the binding while a channel can be positioned precisely in the protocol stack. In most cases you don't need precise positioning, so you should go with the simpler approach. Next time: Adding Headers to a Call (HTTP Version) Read More...
  • Setting the Configuration Name

    What's the difference between the Name and ConfigurationName on service contracts and behaviors? The Name property sets the name of the service in metadata while the ConfigurationName property sets the name of the service in configuration. Metadata is the part of the service description that is transmitted to others when they interrogate your service. Configuration is the purely local settings for controlling the service. Since Name is more commonly used, I'll just run through a quick example focusing on setting ConfigurationName instead. Here I've got a service contract and implementation setting both the Name and ConfigurationName properties. [ServiceContract(Name= "NotIService" , ConfigurationName= "IService" )] public interface IMyService { [OperationContract] void DoNothing(); } [ServiceBehavior(Name = "NotService" , ConfigurationName = "Service" )] public class MyService : IMyService { public void DoNothing() { } } In my app.config file, the way I'd refer to that service and service endpoint is by the ConfigurationName. < service name ="Service" > < endpoint address ="http://localhost:8000/" binding ="basicHttpBinding" bindingConfiguration ="myBindingConfiguration" contract ="IService" /> </ service > On the other hand, everywhere in the metadata, generated proxy, and even the generated proxy configuration file the service will appear as NotIService and NotService. Next time: Disabling the Visual Studio Service Host Read More...
  • Generating Types with Lists

    I have a data contract that contains a collection type but the generated proxy appears as an array. How can I make the proxy use a collection type as well? I've talked in the past about how the representation of a type in metadata is decoupled from the CLR representation of a type in the service. For example, if I have a data contract that uses a List: [DataContract] class Data { [DataMember] public List< string > data; } Then, the metadata representation of this data contract is actually described as an array because arrays are the only primitive type for collections in schema. < xs:schema xmlns:tns ="http://schemas.datacontract.org/2004/07/" elementformdefault ="qualified" targetnamespace ="http://schemas.datacontract.org/2004/07/" xmlns:xs ="http://www.w3.org/2001/XMLSchema" > < xs:import namespace ="http://schemas.microsoft.com/2003/10/Serialization/Arrays" > < xs:complexType name ="Data" > < xs:sequence > < xs:element xmlns:q1 ="http://schemas.microsoft.com/2003/10/Serialization/Arrays" minoccurs ="0" name ="data" nillable ="true" type ="q1:ArrayOfstring" > </ xs:element > </ xs:sequence > < xs:element name ="Data" nillable ="true" type ="tns:Data" > </ xs:element > </ xs:complexType ></ xs:import ></ xs:schema > However, just as the metadata representation isn't coupled to the service, the metadata representation also isn't coupled to the client. You can on the client generate proxies with any type for this collection that similarly can be serialized or deserialized to an array. The mechanism for doing this with svcutil.exe is the /ct switch. The /ct switch, which stands for collectionType, allows you to give a qualified type name that is used for collection data types when generating a proxy. As an example, to get back to the original collection class used by the server, the proxy would need to be constructed using /ct:System.Collections.Generic.List`1 as the option passed to svcutil.exe. However, you could leave the proxy using arrays or provide a different collection class such as /ct:System.Collections.ObjectModel.Collection`1 and with any of these configurations the proxy would be able to exchange messages with the server. Next time: Setting the Configuration Name Read More...
  • Private Data Members

    Why does a data contract with private or internal members generate a proxy with public fields? The obvious answer is that the representation for data contracts doesn't contain information about member visibility but that just leads to the question of why the information isn't preserved by the representation. If we take a data contract that contains both public and private members, [DataContract] class Data { [DataMember] public int i; [DataMember] private string s; } Then, the type representation used to generate a proxy is based on an XML schema. < xs:schema xmlns:tns ="http://schemas.datacontract.org/2004/07/" elementFormDefault ="qualified" targetNamespace ="http://schemas.datacontract.org/2004/07/" xmlns:xs ="http://www.w3.org/2001/XMLSchema" > < xs:complexType name ="Data" > < xs:sequence > < xs:element minOccurs ="0" name ="i" type ="xs:int" /> < xs:element minOccurs ="0" name ="s" nillable ="true" type ="xs:string" /> </ xs:sequence > </ xs:complexType > < xs:element name ="Data" nillable ="true" type ="tns:Data" /> </ xs:schema > A schema is a type system that is independent of the type system used by the proxy and has no concept of member visibility. However, by saying that a member is part of the data contract, you've effectively said that that member is as intrinsically part of the data as any other public facing member. Member visibility is a facet of information hiding to suppress details that are not needed by other parts of the system, but a data member by definition is needed by other parts of the system. Therefore, regardless of how one of the parties has chosen to represent that data, it's more likely than not that the other side will need to manipulate that data to uphold the contract. Next time: Generating Types with Lists Read More...
  • Manual Context Management

    How do I manually manage the context when sharing a client object? The default mode when using a context binding is for the context to be managed internally by the context channel underneath the client proxy. This is similar to how by default cookies are managed by an HTTP channel to send and receive cookie context. With an HTTP channel you can disable automatic cookie management and control the context yourself. There is a similar process that you can use to take control for a context binding. Here's a comparison of the two processes. You can get the code for HTTP by using the link above and with the further details on custom cookie handling so I won't print it again. With HTTP, you first need to turn off automatic cookie handling by setting the AllowCookies property on the HTTP transport binding element to false. With a context binding, you first need to turn off automatic context handling by setting the Enabled property on the context manager to false. IContextManager contextManager = channel.GetProperty<IContextManager>(); contextManager.Enabled = false ; Then, for HTTP you attach an HttpRequestMessageProperty that contains the desired cookies to a message using an OperationContextScope. With a context binding, you use the same OperationContextScope approach but attach the appropriate ContextMessageProperty instead. using ( new OperationContextScope(client.InnerChannel)) { ContextMessageProperty contextProperty = new ContextMessageProperty(contextData); OperationContext.Current.OutgoingMessageProperties[ContextMessageProperty.Name] = contextProperty; client.DoOperation(); } Next time: Messaging Additions in Orcas Read More...
  • One Shot Serialization

    Why do some serialization errors when sending a response not result in a fault being returned to the client? In the typical service operation, sending a response is comprised of returning the appropriate information from the service method to construct a message. You might think of that response as a single operation but performing the response is divided up into many different acts. As an example of a division you could make, one way to split a response into separate acts is to say that there is an act of thinking about whether to respond and what the response contains, an act of constructing the response, and an act of transmitting the response. There is a moment in time during those acts in which the system moves from thinking about a response to actually carrying out the response. Because there are many different ways to divide the operation into a series of acts, that moment in time does not always make up a clear line separating one part of the system from another. However, if you get to the point where you've started carrying out the response, then you've attempted to respond. As an example in WCF terms, RequestContext.Reply is one key point at which the act of responding is realized. There are a variety of different messaging patterns; the ones that you should be familiar with are the one-way, request-reply, and duplex patterns. One-way patterns don't have a response so we can ignore those in this discussion. Request-reply patterns have the property that for any given request there can only ever be one response. If you think about the act of responding now, then there is a point at which your single attempt to respond has fail. This point is totally divorced from what takes place on the wire. It instead is an internal artifact of how the particular system divides the response into acts. A failure before that point would permit an error response to be sent instead while a failure after that point means that no response can ever be sent. Next time: Hosting Identity Read More...
  • Passing Around Endpoints

    Can I construct a proxy object on one machine and pass it to another? No, there's no concept in WCF of sending a fully constructed proxy object from one place to another. Consider that there are two different things that "passing" a proxy object could mean: passing a reference to the object or passing a value by constructing an equivalent object in another location. If you passed a proxy by reference, then what you really would be doing is sending messages from your local machine to the remote machine on each invocation, to be sent by the real proxy. However, that's just a service that forwards messages between the two proxies, and that's something that you can build yourself. If you passed a proxy by value, then what you really would be doing is sending some description of the proxy to be created locally. Again though, that is something that you can build yourself by passing the endpoint description for the proxy you want to recreate and constructing a local proxy factory. Next time: One Shot Serialization Read More...
  • Single Reader for MSMQ

    My application needs to process messages from a queue in-order but multiple messages are being read at once. How do I make the service only use a single reader? There are two modes that control how many requests a service can process at once. InstanceContextMode controls when a new instance of your service is created; ConcurrencyMode controls the threading model for the service. When the InstanceContextMode is PerCall (or PerSession- the two are the same if you don't actually have a session), multiple instances of your service will be created with their own reader thread, up to a limit on the number of simultaneous instances. When the ConcurrencyMode is Multiple, multiple reader threads will be passing messages to a service instance, up to a limit on the number of simultaneous calls. If you want your service to be sequentially invoked with each of the messages in the queue, then you need to set both InstanceContextMode and ConcurrencyMode to Single. Next time: Getting Caught by Loopback Read More...
  • Using Call Context Initializers for Cleanup

    I'm using framework features that have thread-local settings. These settings then get leaked to other client calls. How can I stop this from happening? The problem here is that WCF doesn't know about these thread-local setting changes that you've made and so doesn't know that they need to be cleaned up. WCF by default is more frugal than other stacks, such as ASP.NET, when it comes to protecting state. Saving and restoring lots of thread-local settings takes time regardless of whether you actually did something with those settings or not. WCF tries not to do as much on your behalf so that you don't have to pay for cleanup unless you're using those features. It does however give you the hooks necessary to arrange for this cleanup to take place at the appropriate time. The ICallContextInitializer interface lets you hook the beginning and end of operation calls. Hooking the end of the call allows you to cleanup these setting changes. It's easiest to insert an ICallContextInitializer by applying an endpoint behavior to your application endpoints. class MyInitializer : ICallContextInitializer { public void AfterInvoke( object correlationState) { // Clean up thread-local settings here } public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message) { return null ; } } class MyInitializerBehavior : IEndpointBehavior { public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { // Add instances of your call context initializer to the CallContextInitializers collection // of the appropriate operations located at endpointDispatcher.DispatchRuntime.Operations. } public void Validate(ServiceEndpoint endpoint) { } } Next time we'll look at a more complete example of using ICallContextInitializer to solve a problem with setting up thread-local settings as well. Next time: Using Call Context Initializers for Culture Read More...
More Posts Next page »

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