|
|
Browse by Tags
All Tags » Messages » Indigo (RSS)
-
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...
|
-
Inside of a service method, how do I know where the message was delivered? Without defining what distinguishes a location it's hard to explain where 'here' is. I've got a few guesses though based on the most common variations of this question: OperationContext.Current.IncomingMessageHeaders.To OperationContext.Current.IncomingMessageProperties.Via HostingEnvironment.ApplicationVirtualPath Assembly.GetExecutingAssembly().Location HostingEnvironment.ApplicationPhysicalPath Next time: Serialization Temporary Assemblies Read More...
|
-
Is it possible to copy a very large message? The CreateBufferedCopy method of Message requires a quota parameter that is only integer sized. There has always been a direct way around the problem of copying messages, which is that any message allows you to run it through an XmlReader or XmlWriter, depending on the convenience of your perspective. The XML APIs allow you to synchronously pull limitless amounts of content at your leisure, although they optionally can enforce quotas as well. The XML approach is somewhat painful though as running a message through a null loop to create a new copy requires much more careful coding than a method that is directly designed to stamp out copies. The XML approach also, while not implying any performance disadvantage, negates any potential performance advantage that might be gained by cleverly optimizing the copy operation for a specific implementation of message. However, I'm willing to take the interpretation that the quota of CreateBufferedCopy refers to the largest buffer that the copy may allocate rather than the largest message that the copy may represent. This is an important distinction because I may be able to represent a message that is much larger than I could hold in memory. For example, the message may be backed by a non-memory store or be algorithmically generated. The essence of a streamed message is that the message object in memory is much smaller than the message itself. Of course, none of the message implementations that I know of today decouple the representation size and message buffer size, but that doesn’t preclude an implementation like that existing in the future. Next time: Forwarding Transactions Read More...
|
-
Today wraps up the series on detailed messaging changes in Orcas. You can get the whole series here as well as the previous high-level overview of new Orcas features I did. Messaging Additions in Orcas Messaging Additions in Orcas, Part 2 Messaging Additions in Orcas, Part 3 Now, let's go on with the list. I've got one last feature to cover and then some of the more notable bug fixes that were reported by customers. If you need one of the bug fixes, you can get them by either installing Orcas or the .NET framework 3.0 service pack. Enhancements for web programming . RSS and ATOM syndication, partial trust, JSON, AJAX, and HTTP application programming are all covered reasonably well in the high-level overview so I didn't break them out this time. We no longer make shutdown slow. It took a somewhat rare machine configuration but the various services we run for port sharing and activation could prevent the machine from shutting down until they timed out. Copying a POX message. There aren't any standard channels that buffer messages and are used with HTTP under MessageVersion.None. However, if you write a message inspector, then you need to copy the message before reading it and that now works. Starting a listener while hosted in IIS. I don't recommend starting an independent web service from inside of a web service hosted in IIS. We've made the threading work in this service-within-service case but you're still at the mercy of IIS deciding when to deactivate the outermost service. Emptier messages. When doing POX we have to surface messages even when the HTTP payload is empty so that you have an object to get your HTTP message properties from. Until now though, when we did that conversion those messages would stop reporting that they were empty. Next time: Private Data Members Read More...
|
-
How do typed messages get created from an object that has a message contract? There seem to be a lot of examples that talk about how messages get produced when they're described by data contracts but relatively few descriptions of the equivalent process for message contracts. There's really nothing complicated or magical here so let's go through it. I'll start with a message that I want to describe with a message contract and then build the contract class. < s:Envelope xmlns:s ="http://www.w3.org/2003/05/soap-envelope" > < s:Header > < h:version xmlns:h ="http://mycorp.com" > 1 </ h:version > </ s:Header > < s:Body > < name xmlns ="http://mycorp.com" > Microsoft </ name > < address xmlns ="http://mycorp.com" > 1 Microsoft Way </ address > </ s:Body > </ s:Envelope > There's a message header whose type is an integer and two body members whose types are strings. This is a pretty easy message to describe although I have to change the settings for the wrapper and namespaces to get the structure to match. I apply an order to the body members because the default would reverse them. [MessageContract(IsWrapped= false )] class MyMessage { [MessageHeader(Namespace = "http://mycorp.com" )] public int version { get; set; } [MessageBodyMember(Namespace = "http://mycorp.com" , Order = 1)] public string name { get; set; } [MessageBodyMember(Namespace = "http://mycorp.com" , Order = 2)] public string address { get; set; } } Now I can use the TypedMessageConverter class to go between the message contract and a Message object. MyMessage record = new MyMessage(); record.version = 1; record.name = "Microsoft" ; record.address = "1 Microsoft Way" ; TypedMessageConverter converter = TypedMessageConverter.Create( typeof (MyMessage), null ); Message message = converter.ToMessage(record, MessageVersion.Soap12); Console.WriteLine(message.ToString()); message.Headers.Clear(); message.Headers.Add(MessageHeader.CreateHeader( "version" , "http://mycorp.com" , 2)); MyMessage record2 = (MyMessage)converter.FromMessage(message); Console.WriteLine(record2.version); Console.WriteLine(record2.name); Console.WriteLine(record2.address); I changed the version header for the return trip just to prove that there's no cheating going on. I gave an explicit message version when creating the message because otherwise I would have gotten SOAP 1.2 with WS-Addressing 1.0. My sample message didn't have any addressing information so I Read More...
|
-
How do I perform XML validation against an entire message? There is a method to read the body of the message but it's only possible to read headers one at a time. Although it sounds more complicated than it really is, a straightforward way to read an entire message is to write it instead. With the Message interface, you have more flexibility when writing a message to an XmlWriter than when reading from a generated XmlReader. Exchanging the roles of readers and writers is a common trick used in XML processing. Here's a really short example of using an XmlWriter with some seekable storage. I've replaced the validation step with dumping out the contents of the message. Message message = Message.CreateMessage(MessageVersion.Soap12WSAddressing10, "action!" , "body" ); MemoryStream stream = new MemoryStream(); using (message) { using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(stream, Encoding.UTF8, false )) { writer.WriteStartDocument(); message.WriteMessage(writer); writer.WriteEndDocument(); } } stream.Seek(0L, SeekOrigin.Begin); Console.WriteLine( new StreamReader(stream).ReadToEnd()); Obviously I'm leaving out more details here than just the validation step. For example, you'd probably want to harvest the original message for things like the message version and message properties so that you could reconstruct the message on the other side, rather than just throwing everything away. Next time: Importing and Exporting WSDL Annotations Read More...
|
-
Why doesn't a message start with an XML declaration? The XML declaration is a processing instruction at the beginning of an XML document that gives information about the format and logical structure of the document. You've probably seen the most commonly used XML declaration on many documents. <? xml version ="1.0" encoding ="UTF-8" ? > Both the version and the encoding in this example declaration are the default values. XML documents aren't required to start with a declaration because default values are assumed. Processors that are sensitive to the size of the produced document omit the declaration to avoid transmitting redundant information. The text encoder is an example of an XML processor that can recognize when the default values are being used and omit the declaration to save space. In some cases you want the XML declaration even when it's unnecessary because the receiver is expecting the document to start with a particular sequence of characters. Since the optimization in the text encoder isn't the result of a configuration setting, some amount of manual work is required to produce messages that contain unnecessary processing instructions. You can recreate this effect using a custom message encoder that is even simpler than the sample custom text encoder . You don't need to support a custom content type or to do any special processing when reading a message. You do need the shell for a message encoder and message encoder factory plus the logic in WriteMessage to insert the processing instruction. The sample writes the processing instruction using XmlWriterSettings although you can choose any method you wish. Next time: Flowing Additional Identity Information Read More...
|
-
How do I use a field in the message to answer an authorization request in ServiceAuthorizationManager? There are two ways to go about doing this. The first makes use of a new feature in Orcas while the other is potentially more flexible and definitely requires more work. There’s a new overload for CheckAccess in ServiceAuthorizationManager that gives you a Message instance for the current request. This allows you to access the body contents by reading the message. Reading the message consumes it so you’ll need to replace the message when you’re done. You should be aware that this is going to be a significant speed bump unless you were already buffering messages. Even so, touching the body contents is almost guaranteed to take noticeably longer than you’re used to for performing authorization checks. public virtual bool CheckAccess(OperationContext operationContext, ref Message message); The other option is to insert a transformation step prior to ServiceAuthorizationManager being invoked. The transformation step takes the contents of the message and extracts the information needed for the authorization decision into a message header or property. This allows you to use ServiceAuthorizationManager exactly as before. Adding the transformation is a lot harder than overriding a method but you can potentially be doing other protocol work at the same time that also uses the contents of the message. You may be able to amortize some of the overhead of touching the message body in this way although in the worst case you’re no better off than with CheckAccess. Next time: Demanding Permissions Read More...
|
-
The MustUnderstand attribute is frequently misunderstood because people assume that it must be much more complex and powerful than it really is. I explained the mechanics of using MustUnderstand last year but today's article is about some of the misconceptions for how the attribute is used. Annotating a message header with MustUnderstand creates a contract from the client to the service that the operation must fail if that part of the message is not able to be processed. This is not the same as validation because the service can understand what the header means even if the value of the header is wrong. For example, if a header is supposed to contain a certificate, then a service that knows about that header understands the message even if the client passes a certificate that is expired or malformed. Another key point of the description is that MustUnderstand is a contract from a client to a service. Decorating message contracts with MustUnderstand doesn't do anything on the service and doesn't show up in the metadata. You don't push understanding from the service to the client. The client chooses to decorate the message with a MustUnderstand attribute because the client knows in the message it is sending that a particular message header semantically affects other headers or content in the message. Some of the corollaries of that idea are that message headers with nil or null content can nevertheless have a MustUnderstand requirement and that the MustUnderstand mechanism only is useful if the message header actually gets written into the message. You can't require a service to support a specific capability with MustUnderstand unless that capability is actually being exercised. Next time: Concurrent Channel Performance Read More...
|
-
When a message header supports multiple representations, which version is used when the message header is printed? A message header is a piece of data about the message that's carried on the wire somewhere apart from the message contents. When using an enveloped message format like SOAP, there's typically an explicit container for message headers and rules for what those message headers should look like. For other message formats, the message header may look different depending on the type of data that the message header represents and how the message header is transmitted. The same message header may have a different way of being expressed on the wire depending on the format of the message in which the header is contained. If the message header is printed together with a message, then the message header obviously should just use the same format as was used by the message. However, since message headers are independent objects, you can pull out a message header on its own and try to look at it. When you do that, the message header is queried for all of the message formats that it could be used with, and one of those message formats needs to be picked. Here's the order of preference for picking among the available message formats: SOAP 1.2 with WS-Addressing 1.0 SOAP 1.2 with WS-Addressing August 2004 SOAP 1.1 with WS-Addressing 1.0 SOAP 1.1 with WS-Addressing August 2004 SOAP 1.2 without addressing SOAP 1.1 without addressing No envelope or addressing Next time: Understanding MustUnderstand Read More...
|
-
I've answered this question before but it continues to keep being asked so I'll answer it again. This comes up most often when someone is trying to log messages, either through the official message logging feature or on their own by calling ToString. Why do I get this text rather than the body of the message? <s:Body>... stream ...</s:Body> Logging can only display the data that is actually present for a message. Message headers and properties are always buffered but the body content of a message can be either buffered or streamed. If the body content is buffered, then it can easily be played multiple times and so it is displayed while logging. If the body content is streamed, then the data may not be present and it may not be possible to replay the data again in the future. Streamed messages do not attempt to display the body contents to avoid these problems. If you want to guarantee that you are reading the complete contents of a message, then you have to suck all of the message contents out using a reader or writer yourself. I've seen people recommend calling CreateBufferedCopy as a workaround but this just happens to work with the common implementations of Message today. There's no guarantee that the messages you create from a MessageBuffer are going to be buffered rather than streamed. Next time: Controlling HTTP Caching Read More...
|
-
What kinds of XML do messages support? This isn't a simple question because, like many parts of a framework, it's important to distinguish what could possibly be done given enough time versus what could easily be done given the components that ship in the box. With the components that ship in the box, you can read and write XML 1.0 documents plus the binary XML format that we include as well. All of this support is through classes for defining XML readers and writers. You can define your own readers and writers with this model. For example, it should be possible to build a message implementation that supports XML 1.1 documents, although I have never tried this to see if it would work. You can even work with documents that are not recognizable as XML in any form using the same approach as long as there is some way to project that external document to an XML InfoSet temporarily during message processing. Next time: Security and Streaming Read More...
|
-
My service operation has an untyped contract and I'm trying to save the messages that it receives for processing later. However, the messages always say that they are closed before I can read them. Why are the messages closed? Messages are good for a single use, which means that once someone has finished with the message, no one else can read it even if there are multiple references pointing to the same message object. Most commonly, the service is responsible for reading and closing the messages. If you have a typed contract, then the service has to read the message to produce the types. If you have an untyped contract though, the service can hand the message to you without having read it. In either case, the service takes responsibility for closing the message after the service operation completes. This prevents you from having to think about the messages and clean up after them. When you intend to process a message later, it's clearly not a good thing for the service to think that it is responsible for closing the message after the service operation completes. You can tell the service that you want to take control of cleaning up messages so that the service does not have this responsibility. To mark service operations for manual cleanup, add an OperationBehavior attribute to the service operation implementation that sets AutoDisposeParameters to false. It is now entirely your responsibility to clean up messages after processing is complete. Next time: Configuration Quick Reference Read More...
|
-
I have an existing web service that I need to replace with a WCF web service. How do I choose between using a data contract and a message contract? There are actually three choices to consider for describing the messages that your service uses: data contracts, message contracts, and XML serialization. You will be forced to use XML serialization in some cases because you have an existing message format with precise specification of XML elements and attributes that you need to replicate. In these cases, it may simply be impossible to duplicate this exact XML schema with a message or data contract-based description, forcing you to use XML serialization to describe the messages. However, let's assume that the existing message format is not so unreasonable and you have a choice between the various options for describing messages with contracts. How do you choose between data contracts and message contracts? The choice may not always seem clear if both types of contracts are capable of describing your messages. A rule of thumb though is that data contracts are generally portable between different kinds of XML encodings, making this option preferable if you might choose to project the Infoset differently in the future. Message contracts are more limited in the projections that they can support but are reasonably adept at mimicking the most common types of XML messages produced today. Therefore, there is a preference to use data contract, followed by message contract and XML serialization. However, the ability to adapt to a preset form is ranked in the reverse order. When you're required to conform to an existing message layout, you are more likely to be forced to use message contracts. When you are designing new message layouts, you almost always want to use data contracts. Next time: Message Disposal Read More...
|
-
I have an operation contract that uses untyped messages. When using the message, I get an error telling me to change the quota settings on the XmlReader. Where are these quotas located? I'm not using an XmlReader. A message represents an XML InfoSet. While there are many different ways to access the content of a Message, in a standard implementation, all of these methods are wrappers around the core XmlReader and XmlWriter infrastructure. If there is no obvious XmlReader, then that means that the XmlReader is being used by the internal implementation of the message. Therefore, whoever created the Message must have been the one that knew about the XmlReader and its quotas. Since most of the messages that you deal with inside of a service operation were created by the message encoder of the binding, the first place to look for the quota settings are either on the binding or the binding element. Next time: Sticky Sessions Read More...
|
|
|
|