|
|
Browse by Tags
All Tags » Messages » Indigo » Answers (RSS)
-
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...
|
-
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...
|
-
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...
|
-
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...
|
-
How do I change the HTTP status code of the response that is sent back when using a one-way contract? The result of using a one-way contract is to automatically send back an empty HTTP response when the service method is called. Sending back this response is independent of executing your service code. This means that the normal method of attaching a message property to set the HTTP status code and other HTTP headers can't be applied. There is no reply channel waiting for you to set up a message with the appropriate properties. However, there is another mechanism for sending back an empty HTTP response where you do have control over the HTTP headers. When you're using the standard request-reply contract with HTTP, you can manipulate the HTTP message that gets sent back for the reply. On that message you can put an HttpResponseMessageProperty that has SuppressEntityBody set to true. SuppressEntityBody produces equivalent messages to a one-way contract that have HTTP headers but no body contents. You should think of one-way messages and empty messages as having the same appearance but different semantics during processing. The other way around the problem is to find a lower processing layer to apply your HTTP headers. If you get below the processing layer that knows about one-way messaging, then one-way messages and empty messages are not distinguishable. It is the processing layer that recognizes the one-way protocol that creates the distinction. Next time: Binary Encodings and Addressing Read More...
|
-
Creating a copy of a message requires passing the "maximum buffer size" to CreateBufferedCopy. How big should I make this maximum buffer size? In most cases, you can use Int.MaxValue and not worry about the buffer size. Specifying this buffer size is primarily useful when you haven’t previously given a bound to the maximum size of the message. If you received this message using a buffered transfer, then you should have already had a quota applied on the maximum size of the received message. If you received this message using a streamed transfer, then you may want to specify a buffer size if the quota for streaming is larger than the amount you're willing to buffer into memory. If you are creating this message from scratch to send it or for other reasons, then you probably don't want to specify a limit. However, if the message is being built up as the result of several user-driven operations, then you may want to checkpoint the message size during copies to make sure that a malicious user isn't trying to run you out of memory. A malicious user can still make you do a lot of wasted work in this case, but that probably just means that you should require authorization before letting someone tie up your resources. Note that whatever value you pass for the maximum buffer size, the default implementation of CreateBufferedCopy uses the maximum possible values for all of the XML reader quotas. It is just the total size of the message in bytes that is being bounded here. Next time: Optional Interfaces on Binding Elements Read More...
|
-
Can I write a point-to-point router service by setting the Via property for outgoing messages? Like most things, this is going to depend on the specific behavior of the transport channel you're using, but in general the answer is no. The transport channel owns the Via property and it will stomp over whatever you write into the message headers. You do have one opportunity to set the channel's Via, which is during the creation of the channel from the channel factory. After that, the matter is out of your hands. This would imply creating a channel per message or keeping a pool of these channels around to farm out messages if you keep using the same destinations over and over. There is a different story if what you want to route to is the ultimate receiver To address instead of the Via address. You can set the To address on a per-message basis, assuming that the transport channel has implemented the ManualAddressing setting . Next time: Enabling Kerberos in IIS Read More...
|
-
What is the content type of the message returned by a service? The idea of a content MIME type is very popular in HTTP programming, both for communicating the format of the data and the text encoding inside that format. However, content types are not generally used for SOAP processing. If you look at the SOAP specifications, you'll notice that there are fixed content types for describing the message. The message format is SOAP after all. SOAP messaging also generally has a limited choice for text encodings. The application message format inside the SOAP format is more likely what you care about. That information is transmitted out-of-band as part of the service metadata. What this means is that there's no standard object model in WCF for accessing the content type of a message, even when you're not really doing SOAP programming. That's a legacy of being primarily designed for SOAP. There's not a promise here, but there is one spot where the content type can be optionally offered up when supported. If you take your message, one of the message properties is the message encoder. Stamping messages with the message encoder is optional, but if that has been done in the pipeline, then you can query the message encoder for its content type. Note that this isn't the same as the message content type. There's only one message encoder for many messages, so what you're seeing is the default content type for the message rather than the specific content type of the message that was received. Next time: Channel Writing Checklist (Required) Read More...
|
|
|
|