|
|
Browse by Tags
All Tags » Bindings » Indigo » Answers (RSS)
-
What channels can be used in a context binding? The primary limitation for building a context binding is that the channel stack has to have the right shape. The context exchange protocol used by a context binding requires that the first invoked operation be a request-reply operation. This is so that the initial context can be established. In order to support a request-reply operation, the channel stack needs to support one of a particular set of shapes. There are currently five channel shapes allowed when using a context binding: IRequestChannel IRequestSessionChannel IReplyChannel IReplySessionChannel IDuplexSessionChannel The request and reply channel shapes are paired for the client and server so on any particular endpoint there are three valid channel shapes. Conditions are limited further if you want to use HTTP cookies as your context exchange mechanism rather than the default of SOAP headers. In that case it's no longer possible to use a duplex channel so you're limited to variations on the request-reply message exchange pattern. Next time: Manual Context Management Read More...
|
-
When packaging up a collection of settings, how do I know whether to use a CustomBinding, extend the Binding class, or extend one of the standard binding classes? In most cases this should be easily decidable by asking at most two questions. The first question is used to decide between creating a custom binding instance and creating a new class for your binding. Is your binding generally reusable such that you'd expect it to be dropped into other applications with few changes? If your binding is not generally reusable or you don't care to make it so, then use a custom binding. Otherwise, create a binding class by extending Binding or by extending one of the standard bindings. The second question is used to decide between those two alternatives when creating a new class for your binding. Can your binding be expressed as a simple derivative of one of the existing standard bindings? If you're changing some of the default settings of the standard binding, then your binding is probably a derivative. If you’re changing or exposing some of the settings of binding elements that the standard binding doesn't normally expose, then your binding is probably a derivative. If you're adding a layered channel that doesn't have any protocol impact, such as logging, then your binding is probably a derivative. If you're adding or removing layered or transport channels that do have an impact on the protocol, then your binding is probably not a derivative. A derivative of one of the standard bindings should be made by subclassing the standard binding class. A new binding is made by subclassing the base Binding class. Next time: Resolving Conflicts in Serialization Read More...
|
-
How do I write a service that gives clients the option to choose between different security mechanisms for protecting a service call? For example, how can I allow clients to choose between certificates and passwords? I think that if the example choice had been between message security and transport security, then many people would have immediately suggested having two bindings for the different security mechanisms hosted on two different endpoints of the same service. There's no reason why you couldn't use the same strategy in this case where the alternatives are two different kinds of message security. The binding configuration process involves a series of choices, including choosing from enumerations of security mechanisms. It's difficult to craft configurations that accept a wide range of valid formats at the same time. This choice of configurations can of course also be made less apparent by moving the choice farther away from the service endpoint. If you create an abstraction by defining an intermediate credential type, then the service endpoint is simplified by only accepting the intermediate credentials and the choice is offered by giving multiple mechanisms to obtain those intermediate credentials. Next time: Trace Transfer Read More...
|
-
I've done a bit of grouping for the remaining binding elements as there are fourteen non-transport binding elements that I'm covering in this list. I've pointed out the ones that respond to a type with GetProperty on the base class as opposed to repeating the same code in each subclass. Our standard message encoders respond to two types, although only one is on the base class. These two interfaces will override the ones given by the transport if a message encoder is in the binding. The transport delegates to the message encoder before giving its useless default response. MessageVersion (on the message encoder base class) XmlDictionaryReaderQuotas (on the Text, MTOM, and Binary encoders) The one-way and transaction channels both support just a single interface. ChannelProtectionRequirements All of the security binding elements support a pair of interfaces and the actual security channels add an additional type. ISecurityCapabilities (on the security base class and on the Windows and SSL stream upgrades) IdentityVerifier (on the security base class and on the Windows and SSL stream upgrades) ChannelProtectionRequirements (on the asymmetric, symmetric, and transport security binding elements) The reliable message binding element supports a pair of interfaces as well. ChannelProtectionRequirements IBindingDeliveryCapabilities Finally, the composite duplex binding element has a pair of types. If you're curious why composite duplex is interacting with a security interface, then you should read the earlier article on layering between composite duplex and security . ISecurityCapabilities ChannelProtectionRequirements Next time: Starting a Hosted Service Read More...
|
-
This is more of a reference than anything else. People have asked me what interfaces do something when used with GetProperty on a binding element. Of course, a custom implementation can do whatever it wishes in its GetProperty, so I can only tell you what the standard implementations have done. Also, GetProperty is chained from one place to another. For example, if a property is not found on a channel binding element, it is likely to go off looking at lower binding elements in the channel stack, the message encoder, and so on. What's listed here is just what is specifically handled in a given implementation. I've split this list into "transports" and "everything else". The base class for transport responds to three types. ChannelProtectionRequirements (this just give the default values) MessageVersion (SOAP 1.2, WS-Addressing 1.0) XmlDictionaryQuotas (this just gives the default values) The HTTP and HTTPS transports respond to three additional types. Also, these transports automatically check against the properties of a text message encoder if you didn't specify any encoder at all. None of the other transports do this for you. ISecurityCapabilities IBindingDeliveryCapabilities TransferMode The TCP and Named Pipes transports respond to only two additional types. IBindingDeliveryCapabilities TransferMode The Peer transport responds to three additional types. IBindingMulticastCapabilities ISecurityCapabilities IBindingDeliveryCapabilities The MSMQ transports respond to three additional types. The last one only occurs for the Integration mode of MSMQ. ISecurityCapabilities IBindingDeliveryCapabilities MessageVersion (always set to None for Integration mode) Next time: Interfaces for GetProperty, Part 2 Read More...
|
-
How do I prevent clients from accessing my service anonymously? I've changed the settings in IIS from Anonymous Access to Integrated Windows Authentication. However, now I'm getting the error message: "Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service." Disabling anonymous access requires coordinating the settings in IIS and in your service configuration. Those two sources must be in agreement about whether anonymous access is expected. IIS is already using Windows authentication in this case, so let's look at what needs to happen to the service configuration file. I'm assuming that this is IIS6 so the only network transport we're talking about here is HTTP. There are two cases depending on whether you want the protocol that gets exposed to be HTTP or HTTPS. The simplest is to keep using HTTP since that's probably what you were using if anonymous access was allowed in the past. To switch off anonymous access with HTTP, you need to set the security mode to TransportCredentialOnly. < basicHttpBinding > < binding > < security mode ="TransportCredentialOnly" > < transport clientCredentialType ="Windows" /> </ security > </ binding > </ basicHttpBinding > Note that TransportCredentialOnly is not supported for every binding (in this case we're using BasicHttp). For WSHttp, the only choice is going to be to use HTTPS. To switch off anonymous access with HTTPS, you need to set the security mode to Transport. < wsHttpBinding > < binding > < security mode ="Transport" > < transport clientCredentialType ="Windows" /> </ security > </ binding > </ wsHttpBinding > Other bindings can be made to work in this situation as well, including custom bindings. I'm just showing you the most common examples. The key in both cases though is that we're getting transport security with the right kind of credentials associated. Next time: Writing Binding Element Essentials Read More...
|
-
I've created a custom implementation of GetProperty for my binding but now I'm getting errors when I go to use the channels. Why is the validation for these channels failing? This is an implementation problem that I've talked about in the past. There is a requirement that the values queried from design time objects, such as bindings and binding elements, match the values queried from runtime objects, such as a channels. If the two don't agree on a property value, then you can experience problems ranging from an error creating the channel to mysterious failures sending and receiving messages. This problem most commonly happens when you override an existing property value on the binding but forget to override the property in the same way on the channels. Use this picture illustrating GetProperty to follow the chain of property values. However, this problem can also happen even when you're not overriding an existing value. If you write a GetProperty implementation but forget to delegate to the inner channel or binding element, then the chain of GetProperty calls terminates right there. Any further channels or binding elements do not get to contribute to GetProperty evaluations. This can easily cause a discrepancy between the design time and runtime values of a property despite the fact that you didn't explicitly modify that property. In most cases, this is a severe enough problem to fail very quickly. If you've written a GetProperty method and are suddenly seeing property value mismatches for properties that you didn't touch though, then make sure that your GetProperty method is delegating any unhandled properties to the right place. Next time: Preventing Anonymous Access Read More...
|
-
What's the fastest binding for securely communicating over an intranet? How about if the client and server don't share a domain? A lot of attention gets paid to Internet configurations, where HTTP rules the world. HTTP is so dominant in that environment because it is a very open and standardized protocol. Servers that support HTTP as their primary network transport protocol have a lot of reach. It's easy to write clients that connect to these servers, which means a lot more clients will get written than would be the case if the server used some obscure network transport protocol. The world is completely different on an intranet because suddenly reach is no longer a critical factor for adoption. It is possible to use both political and technical means to control the technology that the client and server commonly share. This sharing is helpful in a lot of ways because it allows the use of specialized network transport protocols that are faster and more efficient than the standardized protocols. By removing the requirement of reach, it is possible to do better at meeting other requirements, such as performance. In the general case, the fastest transport in WCF for communicating between machines is the TCP transport. The fastest encoding in WCF is the binary message encoder. Since we control the technology in this scenario, we can enforce support for these protocols. That combination is the default setting for the NetTcpBinding. However, NetTcp has other features turned on by default that take back some of these performance advantages. For example, leaving security enabled is going to roughly cut the network transfer performance of TCP in half. Security is an example of a desirable feature with significant cost, but allows you to get away with not paying if you don't need the feature. That's the essence of the "pay as you go" model. We need security in this case, but we can go with the lightest strategy for securing the connection. Without a trust relationship between the client and server, we can't rely on a third-party service to broker trust between us. The simple and direct approach in this case is to use NetTcp with transport security and rely on the plain old Windows NTLM authentication. NTLM is pretty cheap and allows us to use the basic username and password model for transferring data to a remote machine. Next time: Actions for FaultExceptions Read More...
|
-
I'm trying to use a metadata resolver but the metadata endpoint requires a custom binding. How do I override the binding used by MetadataResolver? The overloads on MetadataResolver are pretty strange, but you can pick any of the ones that take an instance of MetadataExchangeClient. public static IAsyncResult BeginResolve(IEnumerable<ContractDescription> contracts, EndpointAddress address, MetadataExchangeClient client, AsyncCallback callback, object asyncState); public static IAsyncResult BeginResolve(IEnumerable<ContractDescription> contracts, Uri address, MetadataExchangeClientMode mode, MetadataExchangeClient client, AsyncCallback callback, object asyncState); public static ServiceEndpointCollection Resolve(IEnumerable<ContractDescription> contracts, EndpointAddress address, MetadataExchangeClient client); public static ServiceEndpointCollection Resolve(IEnumerable<ContractDescription> contracts, Uri address, MetadataExchangeClientMode mode, MetadataExchangeClient client); Let's take the following ServiceHost as an example. It uses BasicHttpBinding for metadata exchange instead of one of the normal metadata endpoint bindings. ServiceHost host = new ServiceHost( typeof (Service), new Uri( "http://localhost:8080" )); host.AddServiceEndpoint( typeof (IService), new WSHttpBinding(), "servicedir/service" ); host.Description.Behaviors.Add( new ServiceMetadataBehavior()); host.AddServiceEndpoint( typeof (IMetadataExchange), new BasicHttpBinding(), "mex" ); host.Open(); Now, let's look at some code using MetadataResolver against this endpoint. We'll need to create a collection of contracts that includes IService. Also, we'll need to match the address and binding from the earlier service description. EndpointAddress address = new EndpointAddress( "http://localhost:8080/mex" ); MetadataExchangeClient client = new MetadataExchangeClient( new BasicHttpBinding()); List<ContractDescription> contracts = new List<ContractDescription>(); contracts.Add(ContractDescription.GetContract( typeof (IService))); ServiceEndpointCollection endpoints = MetadataResolver.Resolve(contracts, address, client); Console.WriteLine(endpoints[0].Address); Console.WriteLine(endpoints[0].Binding); Console.WriteLine(endpoints[0].Contract.Name); You can run this to see what the metadata resolver is getting back from the endpoint. Next time: Restarting a Failed Service Read More...
|
-
Why are there two MSMQ bindings? This is an easy question to answer: there are two bindings for MSMQ because they do different things. Go ahead and take a look at each of the bindings. The NetMsmqBinding looks like a normal binding with an MSMQ transport, binary message encoder, and all of the normal features that you'd expect to find on a binding. On top of that, there a whole bunch of features that are specific to configuring a queue, like dead letter handling. The MsmqIntegrationBinding on the other hand looks totally different. Ok, the integration binding doesn't actually look all that different. All of the queue-specific features are shared between the two and that makes up a large portion of each of the bindings. However, the rest of the integration binding looks quite unusual compared to all of the standard bindings. For instance, everything is wrapped into a single MSMQ integration binding element. There's no message encoder or configuration of message features. Addressing for messages with this binding element uses a very particular syntax. There's no support for message security. Actually, there's almost no support for composing the MSMQ integration binding element with any other type of protocol channel binding element, not just security channels. You'll find that services using this binding are very limited in terms of contracts. The MsmqIntegrationBinding is intended for use with existing, already-written native MSMQ applications. The NetMsmqBinding is a lot better to use but only works if you have WCF on both ends of the queue. Therefore, one of these is always the clear choice for your queuing scenario depending on what's on the other side. There's nothing stopping you from hosting separate endpoints for each of these bindings at the same time if you need communication with both native and WCF clients. However, the two endpoints need to be kept with separate queues because the messages are not compatible. Next time: Serialization of Client Calls Read More...
|
-
The story from yesterday: there is an important setting for composite duplex that is only settable through the binding context. Unfortunately, proxy clients automatically create and use their own binding context so there is no convenient time to poke in a replacement value for the setting. What kind of a workaround can we come up with? Since there is no convenient way to intercept the binding context at the producer, we'll instead need to intercept the binding context at the consumer. The consumer of the binding context is the channel construction process of the binding. In particular, we need to modify the ListenUri setting before we reach the BuildChannelListener method of the composite duplex binding element. That means our opportunities for interception are going to be in methods such as CanBuildChannelFactory, CanBuildChannelListener, BuildChannelFactory, and BuildChannelListener. The binding context instance gets passed along from binding element to binding element so it is safe to modify the setting at any opportunity along the way. We don't have to worry about finding the correct instance of the binding context. Every instance that we see is one that we want to modify. The solution that I came up with for this problem was to write a binding element that modified the ListenUri as the binding context went by. Other than this change, the binding element simply delegates every method to the next binding element down. You can position the binding element in the channel stack so that your customization is always reached before the composite duplex binding element. The binding context that composite duplex receives contains your modifications, giving you full control over the ListenUri setting that was otherwise hidden. This solution is generally reusable for other situations where you need to modify the binding context or channel construction process. I won't say that there are many such situations, but it is a tool for you to use. An interesting coincidence about this problem was that two different people on consecutive days with different scenarios were looking for a solution. Mike Taulty was the second person and he's done a write up of why he was interested in composite duplex and the code I gave him for the ListenUri modifying binding element . Mike added configuration support, which I hadn't bothered with. From configuration, you'll need to build out a complete custom binding. From code, it's simpler because you can start with an existing binding and Read More...
|
-
I'm getting this error message even though I have security enabled for my service: Unhandled Exception: System.InvalidOperationException: The response message must be protected. This is required by an operation of the contract ('ICalculator', 'http://Microsoft.ServiceModel.Samples'). The protection must be provided by the binding ('CustomBinding', 'http://tempuri.org/'). This is sometimes a symptom of incorrect layering between security and composite duplex. Composite duplex correlates two channels together. If the security binding element is below composite duplex in the channel stack, then you'll get this error message because the security channel that is protecting the requests is not able to protect the responses that come in along the back channel. The solution is to reverse the ordering and put security on top of the composite duplex channel. Additionally, you need to specify the use of SecureConversation for that security channel. The security method that you are actually using (user name/password, certificates, Kerberos, whatever) should be specified as the bootstrapping method for the secure conversation. Here's an example of a server with the right layering. CustomBinding binding = new CustomBinding(); SecurityBindingElement security = SecurityBindingElement.CreateAnonymousForCertificateBindingElement(); binding.Elements.Add(SecurityBindingElement.CreateSecureConversationBindingElement(security)); binding.Elements.Add( new CompositeDuplexBindingElement()); binding.Elements.Add( new OneWayBindingElement()); binding.Elements.Add( new TextMessageEncodingBindingElement()); binding.Elements.Add( new HttpTransportBindingElement()); ServiceHost host = new ServiceHost( typeof (CalculatorService), new Uri( "http://localhost:8000/" )); host.Credentials.ServiceCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "localhost" ); host.AddServiceEndpoint( typeof (ICalculator), binding, "" ); host.Open(); Console.WriteLine( "Press <ENTER> to terminate service." ); Console.ReadLine(); host.Close(); Next time: Getting the Client's Password Read More...
|
-
It's occasionally useful to be able to replace the binding being used for an existing service host. For example, if the binding was loaded from configuration, you may then want to have your code examine the binding and modify some of the settings. This lets you use the configuration system without any extensions, while still having control over the settings used from the configuration file. Access to the service binding is available through the service description. The binding for an endpoint can be changed as long as you haven't started using the service by opening it. This example shows picking out the endpoint to modify using the contract type. There are several other options you can use to identify an endpoint. ServiceEndpoint endpoint = host.Description.Endpoints.Find( typeof (IService)); BindingElementCollection elements = endpoint.Binding.CreateBindingElements(); elements.Find<TransportBindingElement>().MaxReceivedMessageSize = 5000; endpoint.Binding = new CustomBinding(elements); It's important to notice here that we aren't just altering the binding that is already present. The setting in this example is one that will be regenerated every time the binding creates a new set of binding elements. That means that we have to capture a snapshot of the binding, modify the snapshot, and then set that as a custom binding for the endpoint. Read More...
|
-
I’m trying to use a Certificate credential with security mode TransportWithMessageCredential. Certificate credentials were working with transport security but now my clients can’t connect. Why isn’t this working? This one is fairly quick to diagnose if you look at what your service is telling you. I’ve set up a service with the WSHttpBinding and the security mode set to TransportWithMessageCredential. What’s probably gone wrong is that the configuration is setting the transport client credential type to Certificate. binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate; Let’s look at what the service metadata says that is doing. < wsHttpBinding > < binding name ="WSHttpBinding_Service" closeTimeout ="00:01:00" openTimeout ="00:01:00" receiveTimeout ="00:10:00" sendTimeout ="00:01:00" bypassProxyOnLocal ="false" transactionFlow ="false" hostNameComparisonMode ="StrongWildcard" maxBufferPoolSize ="524288" maxReceivedMessageSize ="65536" messageEncoding ="Text" textEncoding ="utf-8" useDefaultWebProxy ="true" allowCookies ="false" > < readerQuotas maxDepth ="32" maxStringContentLength ="8192" maxArrayLength ="16384" maxBytesPerRead ="4096" maxNameTableCharCount ="16384" /> < reliableSession ordered ="true" inactivityTimeout ="00:10:00" enabled ="false" /> < security mode ="TransportWithMessageCredential" > < transport clientCredentialType ="None" proxyCredentialType ="None" realm ="" /> < message clientCredentialType ="Windows" negotiateServiceCredential ="true" algorithmSuite ="Default" establishSecurityContext ="true" /> </ security > </ binding > </ wsHttpBinding > Hmm, the transport client credential type seems to be ignoring the setting and the message client credential type is Windows. What’s going on is that TransportWithMessageCredential only uses the message security credentials. The transport (HTTPS in this case) is locked to anonymous authentication and the message credentials are using Windows because that’s the default if you don’t change any of the settings. The mismatch between Windows and Certificate credentials are why the clients are failing. We can fix this by changing the client credential type line to set the message security credentials instead. binding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate; Now, the security block in the metadata gives us exactly what we want. < security mode ="TransportWithMessageCredential" Read More...
|
|
|
|