Welcome to Windows Communication Foundation (WCF)
Top Tasks :

WCF Team Bloggers

Browse by Tags

All Tags » Contracts   (RSS)

  • Pointing to External Metadata

    I've previously talked about using WSDL extensions to provide custom modifications to the WSDL import and export process. Making modifications to an existing WSDL document or to the existing WSDL processing is a great way to make small changes when the default behavior almost gets you to where you want. However, you may have noticed that these mechanisms are a little cumbersome for providing a complete overhaul of metadata; that's because a WSDL extension is primarily a hook to supply user extensibility before or after certain steps in the WSDL import or export process. When making large-scale modifications, another tool in your toolbox is to entirely jump out of the built-in WSDL processing. The ExternalMetadataLocation property on the ServiceMetadataBehavior is one of the ways that you can opt out of the standard process. By supplying an external metadata location, you provide to clients a reference to an independent location for retrieving metadata. You might base the contents of that external metadata on the metadata files normally generated by the service (the disco.exe tool in the Windows SDK is a good way to generate all of those metadata files at once) or you might go completely wild and make the external metadata have no relationship at all to the normally generated metadata files. Next time: Avoid Exceptions in Faults 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...
  • 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...
  • Configuring Protection Level

    Is it possible to configure the protection level for message parts at runtime? Only certain configurations make doing this particularly easy. When using transport security with Windows credentials, the WindowsStreamSecurityBindingElement allows you to directly set the protection level (changing the protection level when using SSL doesn't make as much sense due to the way SSL works). On the other hand, there's no equivalent facility for message security, which will always give you both encryption and signing if you haven't explicitly set the protection level on the contract. There are a few ways to attack this lack of configurability: configure a custom service host to override the contract description during ApplyConfiguration configure a behavior to modify the contract description when behaviors are applied configure a behavior to modify the channel protection requirements when the security channel is instantiated The first approach is a very indiscriminate way to get the job done. Modifying the entire service is almost certainly not what you want to do, so you'd need some way to describe the scope of specific message parts that you want to modify. Behaviors can be much more targeted. The second approach has the hidden downside that modifying the contract description at one endpoint can potentially (depending on order of execution) modify the contract description for other endpoints. This also is almost certainly not what you want to do. Finally, both the second and third approaches have downsides due to being implemented with behaviors. User behaviors are executed after the security validation behavior that is run as part of the service start up. This means that you're unable to declare a protection level on the contract and then later reduce it in the behavior unless the binding is capable of supporting the originally specified protection level. Also, the results of modifying a contract in a behavior don't get reflected in metadata, which makes a variety of tasks harder. In short, none of these options are particularly good. The third approach is probably the most workable although it does suffer a number of downsides. You can base this approach on the following bit of code. public class ProtectionLevelEndpointBehavior : IEndpointBehavior { public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { ChannelProtectionRequirements requirements = bindingParameters.Find<ChannelProtectionRequirements>(); // Read More...
  • DataMember Best Practices

    I was asked to share a list of best practices I wrote for data contracts and data members so here it is: Do apply the DataMember attribute only to properties rather than the corresponding fields. Do not use type inheritance to version a data contract. Either modify the existing type or create an entirely new type. Do not add or remove enumeration members between versions. Do not change the name or namespace of a data contract or data members between versions. Do not change the order of data members between versions. Do set the IsRequired property to false on data members added in later versions. Do not remove data members in later versions even if they are marked as not required. Do support IExtensibleDataObject on data contracts to support future compatibility with extended types. Do apply the DataMember attribute only to public members. Serialization of private data members is not supported for partial trust environments. Do not rely on constructor visibility, constructor link demands, constructor security actions, or validation checks in the constructor to make a DataContract type safe for partially trusted callers. DataContractSerializer does not invoke the constructor when initializing an object. Next time: Using Call Context Initializers for Cleanup Read More...
  • Scopes of Encryption

    This article is primarily an introduction on protecting message data since the topic overall seems to cause some confusion. The source of confusion is what it means for a service to define a contract for protecting data. Data protection flows from two different directions and at a variety of different scopes. The service can define a minimum standard of protection at various contract scopes. Service contracts cover all of the application data exchanged by the service Operation contracts cover all of the application data exchanged for that particular operation Message and fault contracts cover all of the application data contained in those particular messages Message body and message header contracts cover those particular parts of the message This minimum standard appears as the ProtectionLevel on a contract and comes in three flavors: no protection, protected by digital signing, and protected by encryption (the use of encryption implies a signature as well). Signing prevents people from tampering with the messages while encryption prevents people from reading the messages. These contracts define the application messages that are exchanged. Depending on the protocols you make use of, any number of infrastructure headers or messages may need to be inserted into the data stream to facilitate the exchange of your application messages. This infrastructure data can have its own independent rules for protection. The ProtectionLevel truly is a minimum standard. It is ok for your application to receive messages that are protected better than the minimum standard defines. You may even send messages that are protected better than the minimum standard due to the other direction for flowing data protection. Data can be protected at the wire level by using security integrated with the network transport. For example, if you send data using HTTPS, then there is a level of protection that HTTPS must apply to your messages to transport them even if your contract specified a lower standard. The net protection level is the maximum of that provided by the service and provided by the transport. As long as for every piece of data at every scope that maximum is greater than your minimum standard, then everything works. If that maximum fails to meet your minimum standard, then the service will refuse to send or receive those messages. Next time: Embedding Arbitrary XML in Faults Read More...
  • Differences in Guid Serialization

    Why do the guids in my contract turn into strings when generating a client? You're probably mixing different types of serializers between the client and service. There's nothing wrong with this and the generated client will work correctly but you don't get the user-friendly types. To see why, let's look at the metadata. A guid in a contract with the DataContractSerializer generates a type in the http://schemas.microsoft.com/2003/10/Serialization/ namespace that looks like this: < xs:element name ="guid" nillable ="true" type ="tns:guid" /> < xs:simpleType name ="guid" > < xs:restriction base ="xs:string" > < xs:pattern value ="[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}" /> </ xs:restriction > </ xs:simpleType > On the other hand, a guid in a contract with the XmlSerializer generates a type in the http://microsoft.com/wsdl/types/ namespace that looks like this: < xs:simpleType name ="guid" > < xs:restriction base ="xs:string" > < xs:pattern value ="[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}" /> </ xs:restriction > </ xs:simpleType > These generated types are needed because a guid is not a primitive type. DataContractSerializer came after XmlSerializer so it recognizes both definitions but XmlSerializer has to rely on the schema when it sees a DataContractSerializer guid. Since the schema is based on a string type, the generated client field is a string. The same thing happens with other serializers that don't know how to map a particular schema pattern to a user-friendly type. Next time: TCP Throttling Read More...
  • Importing and Exporting WSDL Annotations

    How do I add custom annotations to the contracts that are generated from WSDL? You first need to start with an IWsdlImportExtension. Your extension gets called each time a contract is discovered during import. Processing happens in multiple passes so we aren't quite ready to mess with generated contract yet. Instead, this is the opportunity to setup some deferred work that can be run once the contract is fully resolved. class MyWsdlImporter : IWsdlImportExtension { public void BeforeImport(ServiceDescriptionCollection wsdlDocuments, XmlSchemaSet xmlSchemas, ICollection<XmlElement> policy) { } public void ImportContract(WsdlImporter importer, WsdlContractConversionContext context) { context.Contract.Behaviors.Add( new MyServiceContractGenerator()); foreach (Operation operation in context.WsdlPortType.Operations) { OperationDescription description = context.Contract.Operations.Find(operation.Name); if (description != null ) { description.Behaviors.Add( new MyOperationContractGenerator()); } } } public void ImportEndpoint(WsdlImporter importer, WsdlEndpointConversionContext context) { } } You'd probably want to be a little bit more discriminating about which contracts you attach to and you'd probably want to actually pass some data to the contract generator so that it knows how to modify the contracts. Let's ignore those little problems and look at the contract generators. The contract generator gets invoked once it's time to actually mess with the generated contract. class MyServiceContractGenerator : IServiceContractGenerationExtension, IContractBehavior { public void GenerateContract(ServiceContractGenerationContext context) { // muck with generated service contract } #region IContractBehavior Members ... #endregion } class MyOperationContractGenerator : IOperationContractGenerationExtension, IOperationBehavior { public void GenerateOperation(OperationContractGenerationContext context) { // muck with generated operation contract } #region IOperationBehavior Members ... #endregion } The IWsdlImportExtension plugs in through the configuration file of the WSDL importer (typically svcutil.exe). < client > < metadata > < wsdlImporters > < extension type =" ... " /> </ policyImporters > </ metadata > </ client > You should be able to figure out how the reverse process works starting from some strategic examination of IWsdlExportExtension. Next time: A Proxy Proxy Factory Read More...
  • Detecting Metadata

    How do I figure out during dispatch whether a request is destined to be a metadata request or a normal application request? The reason you might care whether a request in flight is for metadata or not is because of security policy. You might want to permit lots of people to access your metadata but be very strict about who can call application methods. If you're a security routine that intercepts all sorts of different calls, then you need to know what type of call is currently happening to make the right decision. Otherwise, you don't know who to apply scrutiny to and who to just let in. In the context of the currently in flight operation, there are three pieces of data that will help you figure this out. If you see all three signs, then you know that the request is going to be for metadata retrieval. Check the contract name of the endpoint that the current operation is being dispatched to. It should be IMetadataExchange. Just in case someone defines a different contract with the same name, also check the contract namespace. It should be http://schemas.microsoft.com/2006/04/mex. Finally, check the action of the operation. If it's an operation that does metadata transfer, then the action should be http://schemas.xmlsoap.org/ws/2004/09/transfer/Get/. Next time: Silent Security Failures Read More...
  • Policy Primer Finalized

    After six weeks of comments and editing the primer on WS-Policy 1.5 that I mentioned earlier has been published by the working group. The primer is an explanation of how to use policy with web services along with best practice guidelines for policy authors. These are published as two separate documents on the W3C web site: Web Services Policy 1.5 - Primer Web Services Policy 1.5 - Guidelines for Policy Assertion Authors I'd recommend reading these if you are writing policy expressions by hand, writing software that deals with policy expressions, or defining your own policy assertions for other people to use. Read More...
  • Ignoring Bad Requests

    I have a one-way operation that processes requests and can sometimes fail. When the operation fails, the client receives a fault notification. How can I make the operation ignore the bad requests and not send back a fault notification? This question indicates some confusion over what it means to be a one-way operation. There are actually several different concepts that you could label as one-way. An operation contract with a void return type is one-way in the sense that there is no normal application data to be sent back as part of the operation response. An operation contract declared as IsOneWay is one-way in the sense that execution of the operation does not result in an application message. An operation contract instantiated over a binding offering up IInputChannel is one-way in the sense that there is no path for communicating an operation response back to the client. As you get further down the list, the definition of one-way becomes more encompassing. The first type of one-way prevents sending normal application data but permits sending an operation response and infrastructure messages. The second type of one-way prevents sending any type of application-level response but permits sending infrastructure messages. The third type of one-way prevents sending any kind of message. If a fault notification is getting back to the client, then we know that the question is implying the first type of one-way operation. That's the only type that permits returning an exceptional application response. Changing the service to use one of the later types of one-way operations would prevent those fault notifications from being returned. Next time: Detecting ASP.NET Compatibility Read More...
  • ContractNamespaceAttribute

    Back when I did an overview of custom namespaces , I omitted any namespace declarations that wouldn't appear in the final metadata. One of those declarations is the default namespace for data contracts. I had two example data contracts, one for faults and one for normal messages, although they actually work exactly the same in practice. [DataContract(Namespace = "http://example.com/faultcontract/datacontract" )] public class MyFault { [DataMember] public string detail; } [DataContract(Namespace = "http://example.com/datacontract" )] public class MyData { [DataMember] public string data; } These data contracts include an explicitly declared XML namespace. However, you can modify the test program in the earlier article to see what happens when those namespace declarations are removed. What you end up with is an ugly looking namespace based on a fixed prefix http://schemas.datacontract.org/2004/07/ and a suffix that is the CLR namespace. If you want to get rid of that default namespace for every data contract you define, then you can add a ContractNamespaceAttribute to the assembly. This attribute defines the default XML namespace for data contracts that are located in a particular CLR namespace. You can retrieve a ContractNamespaceAttribute in the standard way for assembly attributes by calling GetCustomAttributes on the assembly with the ContractNamespaceAttribute type. Next time: Configuring SSL Certificates for Vista Read More...
  • Help for Policy Authors

    The W3C Web Services Policy Working Group is putting together a pair of documents to help policy users and authors with the new version of WS-Policy. This includes an explanation of how policy works and best practices for policy authors. There's currently a three week period for collecting comments, which runs through October 19th. You can get both of these documents from the W3C web site: Web Services Policy 1.5 - Primer Web Services Policy 1.5 - Guidelines for Policy Assertion Authors Copies of the standard itself are linked from the earlier announcement I made . Read More...
  • WS-Addressing Metadata and WS-Policy Completed

    Two new standards were published yesterday by W3C that cover various aspects of web service metadata. WS-Policy is one of the family of general mechanisms used to describe service requirements and capabilities. Policy attachments supplement the general mechanism to describe how policy is specifically tied to a service description language, such as WSDL. Finally, WS-Addressing Metadata explains how addressing concepts should appear in WSDL, how WSDL should appear in addresses, and how addressing is described through policy. Look for these standards to be supported in the upcoming Orcas release. You can get all of these specifications at the W3C site. Web Services Addressing 1.0 - Metadata Web Services Policy 1.5 - Framework Web Services Policy 1.5 - Attachment Read More...
  • Metadata is Locked

    Why aren't the changes that I programmatically make to the service contract reflected in the downloaded metadata? This is another common question around the confusion between the design time behavior and run time behavior of the system. The configuration of the system can be altered during design time. During run time it cannot. At the lower levels, design time and run time are very formally separated. There are a small number of distinguished methods, which as an effect of being called switch the object from design time mode to run time mode. At the service level, design time and run time are separated by a murky boundary. Starting the service is a single action that switches many objects from design time to run time, and the order of the switchover can be difficult to guess. At one point, the metadata representing the various contracts is switched from design time to run time and can no longer be altered. At another point, your code may be invoked in the process of switching a separate component from design time to run time. There's clearly a dependency on the order of execution because your code needs to be run first in order for the changes to become visible. The most straightforward way of dealing with this problem is to move the code that changes the contract so that it executes before the contract switches to run time. You can be absolutely guaranteed that things will be visible if you modify them before any attempt to start the service. Next time: Don't Run as Administrator Read More...
More Posts Next page »

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