Module 7
Improving WCF Service Quality
All applications have some form of
system quality requirements in addition to their functional requirements. These
quality requirements include the expected response time for operations, the
availability of the application, the number of users or operations that the
application must support, and the usability of the application's interface
(human interface for a user interface or contract for a service). As your
application evolves, you will adjust your design to improve system qualities
such as performance to meet the required standard. Maintaining quality for
different aspects of a system is frequently a balancing act. In particular, you
will often find that the performance requirements are generally in conflict
with almost every other requirement of your system. You must handle changes
carefully to ensure that your system does not suffer unexpected consequences.
This module explores ways in which
you can improve performance and other system qualities by using features provided
by Windows® Communication Foundation (WCF).
- Lesson 1: Managing WCF Service Instances
- Lesson 2: Managing Concurrency Issues
- Lesson 3: Improving WCF Service Quality
- Lesson 4: Improving Data Transfer Throughput
- Lab: Improving WCF Service Quality
·
Lesson 1:
·
Managing WCF Service Instances
·
·
One way to improve
system performance is to ensure that you use resources efficiently and reduce
the scope for resource contention. In a WCF solution, service instances provide
the primary point that you can control to ensure that resources are allocated
efficiently and fairly.
Instance Life Cycle Options
To cope with resource contention and
multithreading issues, you can configure the service host and specify the instance life cycle by
setting the
InstanceContextMode property of the ServiceBehavior applied to the
service.
There are three different modes
available:
·
PerCall. In this mode, each message that is sent to the service from any client causes a new service instance to be created to handle
that message. The service instance is disposed of after the message is
processed. The next message from any client (even the same client) causes a new instance to be created to handle that message; this new instance is also disposed of after the message is
processed.
·
PerSession.
In this mode, the ServiceHost
maintains a service instance for each client
for a specified
duration, referred to as a session. When the first message arrives from a particular client a new service
instance is created to
handle requests from that client.
The message is
delivered to this service instance. The next message that arrives from the same client is sent to the same service instance
as long as the session has not expired. A message from a different client causes a new service instance to be
created to process that message and any subsequent messages from that
client. When a session
expires or is terminated, the service instance is disposed of.
·
Single.
In this mode, a single service
instance handles all requests from every client. The service instance is created when the service host starts instead
of when the first request arrives from a client.
Each
of these instance life cycle models has different implications for issues such as maintaining state and multithreading. These issues are explored later
in this
module.
The default instance life cycle
management mode is PerSession.
Additional Reading
For more information about the
different instance management modes, see "Sessions, Instancing, and Concurrency" on the MSDN Web site.
For more information how to apply
the instance management modes, see "Discover
Mighty Instance Management Techniques For Developing WCF Apps" on the MSDN Web site.
Creating a Service Instance Per-Call
Under the per-call (or
per-message) service instance life cycle mode, the ServiceHost creates a new service instance for every client request. When a service instance has processed the
message, the ServiceHost disposes of
that service instance and any data or resources that it uses. A new service instance
is created to handle subsequent requests even if the call is from
the same client made by using the same proxy as a previous request.
Under this model, there will be as many instances of the
service in existence at any one time as there are concurrent calls to the service. The one-to-one relationship between client requests and service
instances means that there is only ever one thread
active in the instance at any one time; the thread
operates on behalf of the single client call with which this service instance
is associated.
The ServiceHost disposes of the service instance at the end of the call,
so the service cannot maintain internal state for the client between calls. To
maintain server-side state between calls, state information must be written to
a persistent store such as a database.
The advantages of per-call
instance management are:
·
Your service does not have to manage any form of concurrency or multithreading.
·
Your service does not have to maintain state in
the event of a session timeout.
·
Your service minimizes memory
use and other resources
on the host server.
The primary disadvantages of
per-call instance management is that it continually creates and destroys
service instances that can add a significant processing overhead to the host server.
The following code example shows
how to set the instance context mode to PerCall by
using the ServiceBehaviorAttribute.
[Visual
Basic]
<ServiceBehavior(InstanceContextMode
_
:= InstanceContextMode.PerCall)> _
Public
Class BankService
Implements IBank
...
End Class
[Visual
C#]
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
public class
BankService : IBank
{
...
}
Additional Reading
For more information about the
different instance management modes, see "InstanceContextMode
Enumeration" on the MSDN Web site.
For more information how to apply
the instance management modes, see "Discover
Mighty Instance Management Techniques For Developing WCF Apps" on the MSDN Web site.
Creating a Service Instance Per-Client
Under the per-client (or
per-session) service instance life cycle mode, the ServiceHost creates a new service instance for
every client. This service instance is then associated with that
particular client; subsequent requests from the same client are directed to the
same service instance until the session terminates. If a client is
multithreaded or makes asynchronous calls, multiple threads may execute in the
service instance at one time. Therefore, you must ensure that the code in your
service is thread-safe.
A service instance that uses the
per-session instance life cycle mode retains in-memory state between client requests. After a specified period of inactivity—the
session timeout period—the ServiceHost discards the
service instance and any state information associated with this service
instance. The default session time-out period is 10 minutes. At any
one time, there can be potentially as many service instances as there are
clients.
The advantage of per-session
instance management is that there is a lower overhead from the instance creation/destruction/data access cycle compared to per-call instance life cycle management.
The disadvantages of per-session
instance management are as follows:
·
You must be aware of the potential concurrency issues and
mitigate them in your service implementation.
·
You must be prepared to handle the effects of a session timeout in both your
client code and your service code.
·
Your service instance may be idle between
requests but will still use up memory
and other resources on the server.
The following code example shows
how to set the instance context mode to PerSession by
using the ServiceBehaviorAttribute.
[Visual
Basic]
<ServiceBehavior(InstanceContextMode
_
:= InstanceContextMode.PerSession)> _
Public
Class BankService
Implements IBank
...
End Class
[Visual
C#]
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class BankService : IBank
{
...
}
You can also set the ReleaseInstanceMode property of the OperationBehavior attribute for a service operation. This property forces
the service host to release a service instance and recycle it before or after
an operation that runs as part of a session.
Additional Reading
For more information about the
different instance management modes, see "InstanceContextMode Enumeration" on the MSDN Web site.
For more information on how to
apply the instance management modes, see "Discover
Mighty Instance Management Techniques For Developing WCF Apps" on the MSDN Web site.
Creating a Single Service Instance
Under the single (or singleton)
service instance life cycle mode, you can pass a service instance to the ServiceHost when you create it or the ServiceHost can create one itself. In either case, there will only
ever be a single
instance of the service in existence at any
one time. The
same service instance processes all calls from all clients, so it must be able to handle multiple concurrent calls.
A service instance that follows
the single instance life cycle mode will retain in-memory state between requests; this state is accessible to all clients.
The primary advantages of single
instance management is that there is a lower overhead from the instance
creation/destruction/data access cycle compared to per-call or per-session
instance life cycle management.
The disadvantages of single
instance management are as follows:
·
You must be aware of the potential concurrency
issues and address them in your service implementation.
·
The service instance will be idle between calls
but will still use up memory and other resources on the server even when it is
inactive.
·
The clients share the same service instance,
they all have access to the data stored inside it. This can present a security
risk for some applications if clients can not share state or data.
The following code fragment shows
how to set the instance context mode to Single by
using the ServiceBehaviorAttribute.
[Visual
Basic]
<ServiceBehavior(InstanceContextMode
_
:= InstanceContextMode.[Single])> _
Public
Class BankService
Implements IBank
...
End Class
[Visual
C#]
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class BankService : IBank
{
...
}
Additional Reading
For more information about the
different instance management modes, see "InstanceContextMode Enumeration" on the MSDN Web site.
For more information on how to
apply the instance management modes, see "Discover
Mighty Instance Management Techniques For Developing WCF Apps" on the MSDN Web site.
Requiring Session Capability
Subheading (in Heading 4 style)
You can specify that your service
instance should be able to maintain an ongoing relationship with a particular
client. This is referred to as a session. You can use the SessionMode attribute of the service contract to indicate that you
require, permit, or disallow this sort of session relationship between a client
and service instance.
You can specify the SessionMode property for the service and set it to one of the following values:
·
Allowed.
You can use the service as part of an ongoing session or use it per-call.
·
NotAllowed.
Any attempt to send requests to the service in the context of a session will
cause an error.
·
Required.
Any attempt to send requests to the service outside the context of a session
will cause an error.
If
you specify that sessions are Allowed or Required on a single instance service, you can
store and access per-client session state based on the OperationContext.Current.SessionId. If your instance management mode is set to PerSession, the same service instance will work with the same client
instance all the time. If you specify Single or PerCall, the service instance can still store data for a specific
client; it just involves a bit more work. The following table illustrates how
the instance context mode interacts with the session mode.
|
Instance
Context mode
|
Session
mode: Required
|
||
|
PerCall
|
Each call has a distinct session and InstanceContext.
|
Each call has a distinct session and InstanceContext.
|
An exception is thrown.
|
|
PerSession
|
Each channel has a distinct session and InstanceContext.
|
Each channel has a distinct session and InstanceContext.
|
An exception is thrown.
|
|
Single
|
All calls share a single session and InstanceContext.
|
All calls share a single session and InstanceContext.
|
An exception is thrown.
|
If your application relies on
sessions, you must ensure that the binding used will support them. Similarly,
you must ensure that a service that you did not design to be part of an ongoing
session rejects attempts to use it in that way. Bindings that support sessions
include WSHttpBinding, WSDualHttpBinding, NetTcpBinding, and NetNamedPipeBinding.
The client does not have to do anything
special to support a session. The session starts when the client opens a
channel that uses a session-aware binding.
The following code fragment shows
how to set the service contract to require session support.
[Visual
Basic]
<ServiceContract([Namespace]
:= "http://myuri.org/Simple", _
SessionMode := SessionMode.Required)> _
Public
Interface IBank
...
End
Interface
[Visual C#]
[ServiceContract(Namespace="http://myuri.org/Simple",
SessionMode=SessionMode.Required)]
public
interface IBank
{
...
}
Additional Reading
For more information about WCF
sessions, see "WCF sessions, instancing, and reliable messaging".
Demonstration: Instance Management
Lesson 2:
Managing Concurrency Issues
One way to improve
performance and throughput is to use multiple threads to access resources
concurrently. However, implementing concurrency in a WCF service brings its own
set of challenges to address
Concurrency Issues
Using PerSession and Single instancing opens up the
potential for thread-based resource contention and deadlocks. Bugs caused by multithreading issues are among the most
difficult to diagnose and fix because by their
nature they are:
·
Intermittent.
It can be very much a matter of the precise timing of a sequence of calls from
clients.
·
Difficult
to reproduce. It is often difficult to pin down the precise sequence of
events or context that caused the bug.
·
Ccorrupt
due to concurrent resource access. When you find the effects of a
problem, its causes may have occurred some time ago.
You can take two approaches to prevent threading issues:
·
Block concurrent requests and ensure that only a
single thread can run in a service instance at any one time. This simplifies
the code that you must write; however, response time will increase because
potentially concurrent client requests are held in a queue.
·
Protect
sensitive resources
from concurrent access. This will require you to analyze areas of
potential contention and write code to address threading issues.
Additional Reading
For more information about
multithreaded programming under the Microsoft® .NET Framework 2.0, see "What Every
Dev Must Know About Multithreaded Apps" on
the MSDN Web site.
Concurrency in WCF Services
You can set the concurrency
behavior of a service by setting the ConcurrencyMode property of the ServiceBehavior attribute. The three possible settings are:
·
Multiple.
Any number of threads can be active in the service instance at any one time.
·
Reentrant.
Only one thread can be active in the service instance at any one time, but if a
caller's thread leaves the service instance by calling out to another service,
another calling thread can enter the service instance.
·
Single.
Only one caller can access the service instance at one time, even if its thread
of execution leaves the service instance.
You will see more about the
characteristics of these concurrency modes in the next few topics. The default
mode is ConcurrencyMode.Single.
If you decide to use anything
other than single-threaded mode, you should protect resources from concurrent
access by multiple threads. You can do this by using standard .NET Framework threading mechanisms such
as locks, monitors,
mutexes, and interlocking.
Additional Reading
For more information about how
threading works with the different WCF instance management modes, see "Sessions, Instancing, and Concurrency" on the MSDN Web site.
For more information about how to
create and control threads under the .NET Framework, see "Managed
Threading" on the MSDN Web site.
Single Threaded Mode
Under the ConcurrencyMode.Single threading
mode, only one client request can be active at any one time in a service
instance. To fully understand this definition, it is important to distinguish
between client calls and threads.
A client call causes the service
host to allocate a thread that will then execute the service operation and
process the message passed in the call. After that thread comes to the end of
the service operation, the service host either destroys it or, more likely,
places it back into a thread pool from which the service host can reallocate it
to a subsequent call. If there are more callers at any point in time than there
are threads available to the service host, the remaining callers will have to
wait until a thread becomes free. Potentially, a client request may time out
while waiting for a thread to become available.
Setting the ConcurrencyMode.Single threading mode means that the service instance effectively
has only one thread. All other calls to the same
service instance are queued until the current call ends, even if the current call blocks
other callers to make a call to another service (effectively, the current call
leaves the service instance for the amount of time that it is in the other
service). This means that there is no possibility of any other call that
interferes with the state of the service instance before the original call
returns to its client.
Single-threaded mode is the safest
option because there is no potential for deadlock or contention for resources.
However, this mode can have a serious impact on the performance of the overall
system because other calls to that service instance may be blocked and the
client kept waiting. If you have specified ConcurrencyMode.PerCall instancing, a new instance is created for every call, so your choice
of threading mode will not impact service performance. However, if you selected
ConcurrencyMode.PerSession or ConcurrencyMode.Single instancing, the service instance will restrict access and potentially
slow down the system.
The following code example shows
how to set the service behavior to ConcurrencyMode.Single threading mode.
[Visual
Basic]
<ServiceBehavior(ConcurrencyMode
:= ConcurrencyMode.[Single])> _
Public
Class BankService
Implements IBank
...
End Class
[Visual
C#]
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Single)]
public class BankService : IBank
{
...
}
Additional Reading
For more information about the
effects of the concurrency mode setting, see "ConcurrencyMode Enumeration" on the MSDN Web site.
Reentrant Threaded Mode
Reentrant threading mode
is similar in some ways to Single threaded mode. In both cases, only one
thread of execution will be active at any one time in the service instance and
other calls
are queued if a thread is currently active in
the instance. The difference comes when the current thread in the service
instance makes a call out to another service. At this point, the service host
allows the thread associated with the next call on the queue to enter the
service instance. When the original thread returns, it rejoins the queue.
Like Single threaded mode, this mode limits the throughput for a particular service instance, but it
does not limit throughput as much as Single mode
does. Reentrant mode also eases some issues around
distributed blocking on callbacks when calling-out to services.
Reentrant mode is not as
safe as Single threaded mode
because there is some potential for deadlock and corruption that does not exist with Single mode. However,
this risk is a lot lower than with true multithreading.
The following code example shows
how to set the service behavior to Reentrant
threading mode.
[Visual
Basic]
<ServiceBehavior(ConcurrencyMode
:= ConcurrencyMode.Reentrant)> _
Public
Class BankService
Implements IBank
...
End Class
[Visual
C#]
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Reentrant)]
public class BankService : IBank
{
...
}
Additional Reading
For more information about the
effects of the concurrency mode setting, see "ConcurrencyMode Enumeration" on the MSDN Web site.
Multiple Threaded Mode
Under the ConcurrencyMode.Multiple threading
mode, the WCF runtime permits multiple concurrent requests to the same service
instance. The only limit to the number of concurrent threads is the number of
potential callers and the level of available system resources.
For any type of shared service
instance, this threading option will deliver the highest throughput. However, it is also the most dangerous option because there is a lot of potential for deadlock and
corruption due to concurrency conflicts. You
must ensure that the code that defines the operations for the service uses
thread-safe techniques.
The following code fragment shows
how to set the service behavior to ConcurrencyMode.Multiple threading mode.
[Visual
Basic]
<ServiceBehavior(ConcurrencyMode
:= ConcurrencyMode.Multiple)> _
Public
Class BankService
Implements IBank
...
End Class
[Visual
C#]
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)]
public class BankService : IBank
{
...
}
Additional Reading
For more information about the
effects of the concurrency mode setting, see "ConcurrencyMode Enumeration" on the MSDN Web site.
Lesson 3:
Improving WCF Service
Quality
This lesson describes
other WCF features that you can use to improve system qualities such as
availability and some of the issues that surround these features.
Improving Service Quality
Every system architect would like
to serve as
many clients as possible by using as few
resources as possible. System architects deliver strongly on the unwritten
non-functional requirement, namely cost. However, any deployed application has
a limited set of resources at its disposal; the same applies for the services
that constitute the application. Each service is limited in terms of the
available processor
time, memory, number of database connections. A large number of client calls can cause a large number of service
instances to be created (or a large number of
threads in service instances). Each instance or thread requires system
resources; contention for these resources slows down the services, which slows down the overall system.
As the system slows down in the
face of resource contention, all the callers experience poor performance
because the system processes their requests more slowly than when the system is
lightly loaded. In general terms, there are two solutions to this problem:
·
Buy
better hardware to provide more resources that can be shared between the
users of the system. This means more cost in terms of hardware, software, and
the time spent installing and configuring. This is particularly galling for the
stakeholders if the resource subsequently sits idle for large amounts of time
as system usage drops.
·
Limit
the demands made on the
resources. You can restrict the number of calls handled by the system at
one time to a number that means that every caller gets a reasonable amount of
resources allocated to them. The problem with this approach is that after you
hit that number of calls, subsequent calls must either wait or fail. This means
that callers who get through experience a good performance level at the expense
of callers who do not get through. The latter group can consist of some very
unhappy system users! However, the hope is that this is a small subset of callers.
Additional Reading
For more information about the
effects of the concurrency mode setting, see "ConcurrencyMode Enumeration" on the MSDN Web site.
Throttling Service Access
You can limit, or throttle, access
to a service by setting the following properties of the
ServiceThrottling service behavior:
·
MaxConcurrentCalls.
This is the maximum number of client calls that are allowed at one time.
·
MaxConcurrentInstances.
This is the maximum number of service instances that are allowed at one time.
·
MaxConcurrentSessions.
This is the maximum number of sessions that are allowed at any one time.
The basic implications of these settings are relatively straightforward, but you must consider
how the settings will work in combination with instancing and threading modes. In some scenarios, the instancing and threading mode
settings can supersede the throttling setting. In other scenarios, the
throttling setting can supersede the instancing and threading mode settings.
The instancing and threading mode settings requires careful analysis,
monitoring, and collection of performance data to achieve a good balance of
resource usage versus throughput.
Additional Reading
For more information how to set
the service throttling behavior values and their effects, see "ServiceThrottlingBehavior
Class" on the MSDN Web site.
Throttling, Instance Management, and Threading
The effect of a particular
throttling setting varies that depends on the instance mode and threading model
specified for a service. The following table shows how the instance mode and
throttling settings interact.
|
Instance
Mode
|
Throttling
Impact
|
|
Per-call
|
The number of concurrent client calls is throttled by
whichever is the lower of MaxConcurrentCall
and MaxConcurrentInstances.
|
|
Per-session
|
The number of concurrent client calls is throttled by the
lowest of the three settings.
The number of concurrent sessions and concurrent instances
will be the same.
The concurrent call setting is often smaller since sessions
(and hence instances) live longer than the calls.
|
|
Single
|
MaxConcurrentInstances
is irrelevant.
|
If a service has Single or Reentrant threading mode set, this will also alter its throttling
behavior. If the
number of concurrent calls allowed exceeds the number of instances allowed, the number of concurrent calls that the service
will handle at one time will be restricted to the number of instances even
though they can theoretically be serviced if multiple threading is allowed.
The session limits apply to
transport, reliable, and secure sessions.
Additional Reading
For more information about how to
apply service throttling settings, see "Discover
Mighty Instance Management Techniques For Developing WCF Apps" on the MSDN Web site.
Improving Service Availability and Throughput
During
development, it is easy to think of software applications and services as being
hosted on a single hardware server (in many
development environments, this is precisely how they are hosted). However, many applications and services are deployed to high-capability platforms, which frequently employ the
following features:
·
Clustering,
which makes multiple servers
look like a single
server to the client
·
Failover,
which ensures that when one
server fails the client
is serviced by another
one
·
Load-balancing, where the client is directed to the server with the lowest load
All these capabilities help
deliver highly scalable, and available systems. Software developers must be
careful that they do not undermine this type of platform and stop it from working efficiently
by doing the following:
·
Holding state in-memory on a particular server.
·
Maintaining an ongoing connection between client and server.
This type of design leads to server-affinity where a client must communicate with the same server all the time
regardless of availability or load, so it
works against efforts to migrate clients as the server workload increases or
decreases.
Additional Reading
For more information about how to
cluster, load-balancing, and failover, see "Enabling
Highly Available and Scalable Application Services".
Impact of WCF Settings on Load-Balancing and Failover
Sessions or ongoing connections of any form
can reduce the ability to perform load-balancing and
failover. As a WCF developer, you must
consider this when you use the following WCF features:
·
PerSession instance context mode, where the client must talk to the same service instance each time. This mode
creates server affinity because there is no cross-machine session management mechanism available such as that found in Microsoft ASP.NET.
·
Transport
sessions such as those provided by TCP-based bindings, which
require an ongoing connection
between the client and the
service, unlike Hypertext
Transfer Protocol (HTTP)–based
bindings, which do not require this ongoing connection.
·
Single instance context mode, which requires careful consideration in this scenario. You must determine which instance all the clients will
communicate with and which
server hosts it. What happens if that server fails? Also, is there really only
one instance of the
service or will you end up with one
instance per server? If so, is this what you intended?
To avoid this type of problem,
consider the following approaches:
·
Use
per-call instance management so that it is not possible to store
in-memory state between calls.
·
Load or save any client state to or from a common, persistent store such as a
clustered database.
·
Use a type of session that keeps its duration
short to help minimize server-affinity.
Additional Reading
For more information about WCF
services on high-capability platforms, see "Load
Balancing" on the MSDN Web site.
Lesson 4:
Improving Data Transfer
Throughput
One of the great
advantages that Web services have over other distributed communication
mechanisms is their use of XML as an encoding, which makes cross-platform
interoperability a lot easier. However, the requirement to encode all data in
text format reduces the efficiency of the network when it transfers large amounts
of binary data and reduces the performance of the systems that process this
data. WCF provides several ways to improve throughput for exchanges that
involve large amounts of binary data.
Improving Performance for Large Binary Data
Binary data has traditionally been
a problem for Simple Object Access Protocol (SOAP) messaging. To form part of a
SOAP body, you must convert binary data into base64 encoding, which makes it a
lot larger and hence more inefficient to transmit. If there is a large amount of
binary data, this also causes problems for the XML parser that trys to process
it; XML parsers do not work well with large blocks of text because they usually
read it all into memory before parsing it; therefore, they require a lot of
memory to process large messages.
WCF offers two alternatives for
more efficient transmission of large binary messages:
·
MTOM (Message Transmission Optimization Mechanism) encoding
·
Streaming
Additional Reading
For more information about how to
handle large binary data in WCF, see "Large Data
and Streaming" on the MSDN Web site.
Understanding MTOM Encoding
Message
Transmission Optimization Mechanism (MTOM) is
a Word Wide Web Consortium (W3C) standard that evolved
from two previous attempts to deal with large
binary data in SOAP messages: SOAP with Attachments (SwA) and DIME (Direct Internet
Message Encapsulation). MTOM uses the MIME (Multipurpose
Internet Mail Extensions) encoding, which is
the same protocol that is used to attach binary data to e-mail messages. The
MIME protocol defines a message structure that consists of a variable number of
parts. There are delimiters between message parts; each one contains
information about the type of data that it holds.
Under MTOM, the WCF runtime splits
the SOAP
message into text and binary parts. The text
part becomes a standard SOAP message which occupies the first MIME message
part. Any large binary data has its own MIME part so that it can retain an
efficient encoding instead of base64. The SOAP message contains references to
the binary data that indicate where that data was located in the original
message before it was MTOM-encoded. When the MTOM-encoded message arrives at
its destination, the WCF runtime can reconstitute the original message from the
SOAP message and the binary MIME attachments.
Additional Reading
For more information about MTOM
encoding, see "SOAP Message Transmission Optimization Mechanism".
Enabling MTOM Encoding
To enable MTOM encoding for your
messages, you must:
·
Set the messageEncoding property of the binding to Mtom.
·
Set the MaxReceivedMessageSize
and MaxArrayLength
properties of the binding to values larger than the largest message you expect
to process.
When you use MTOM encoding, WCF
will optimize its handling of binary content:
·
If
the binary content of
the message is small,
the WCF runtime base64-encodes the binary data and places it in
the SOAP message body.
·
If
the binary content is
large, the WCF runtime places it in separate MIME message
parts and adds a reference to this MIME part from the SOAP message body.
Binary data of approximately 200 bytes or more is deemed to be large.
In
both cases, the core message is
contained in a
SOAP message envelope in a MIME message.
Implementing Streaming
The first thing you must do to
support streaming is to define one or more operations on your interface that passes or returns a System.IO.Stream. The operation you choose depends on whether you pass data
from client to service or service to client. A service contract can have other
operations with normal parameters and return values alongside operations that
use streams, but the operations do not necessarily sit well together conceptually.
After you define your contract for
passing streamed data, you must select a binding that supports streaming. There
are only three preprovided WCF bindings that support streaming:
·
BasicHttpBinding
·
NetTcpBinding
·
NetNamedPipeBinding
Next, you must enable streaming on the binding by setting the TransferMode
to Streamed, StreamedRequest, or StreamedResponse. You would use the latter two modes if you only intend to
stream data one way through the contact associated with the endpoint such as
only from the service to the client. The default transfer mode is Buffered, which supports normal message-based operation.
Finally, you must set the MaxReceivedMessageSize property of the binding to a value larger than the largest
message that you expect to process. The default value of this property is 64
kilobytes (KB).
Additional Reading
For more information about how to
enable streaming on a service, see "How to:
Enable Streaming" on the MSDN Web site.
Stream Handling
One of the key questions when you
work with streams is whose responsibility it is to open and close the streams.
Good design tends to indicate that the component that opened a stream should be
responsible for closing it again. However, that would link the client and the
service unnecessarily. The following steps list the sequence and rules for
stream handling. Note that the sender of the streamed data can be either the
client or the service.
The sequence is as follows:
1. The
sender obtains a .NET
Framework I/O stream onto the
binary data source. For
example, it may open a FileStream.
2. The
sender passes the stream to the receiver. If the service
passes data to the client, you will typically pass the stream through a return
value from an operation. If the client passes data to the service, the stream
is passed as a parameter to the operation.
The sender should not close the stream; the WCF runtime will do this.
The sender should not close the stream; the WCF runtime will do this.
3. The
receiver starts to read from the
stream representation created
by the WCF runtime.
4. The
receiver must close the stream after it finishes with it.
After WCF hands the stream to the
receiver, the receiver does not have to execute any more WCF-related user code. On the sender side, WCF will close the stream when the receiver has read all the data.
Additional Reading
For more information about how to
enable streaming on a service, see "How to:
Enable Streaming" on the MSDN Web site.
Comparing Streaming and MTOM
You have two mechanisms that pass
large binary data, so which one should you choose? Consider the following
points when you decide between them:
·
For very large binary data, streaming will be
faster and more efficient. MTOM will still have to load the data into memory to
turn it into a message, which can use a lot of memory or can even be infeasible
in some scenarios. On the other hand, streaming links the source and
destination; this enables direct transfer. Streaming will start to transfer
faster and will have far less memory overhead.
·
For relatively small binary data (but still
above the MTOM threshold), MTOM will be more efficient because it lacks the
setup overhead of streaming.
·
If you can split the data into multiple blocks,
it is usually better to send it as multiple MTOM messages instead of with
streaming. However, all the data may not be available when the transfer starts;
if this is the case, streaming is the only option.
·
The use of MTOM is largely transparent to the
interface and the service implementation. This means that it places minimal
restrictions on contract design and binding selection. However, streaming
places restrictions on the form of operations in the interface. In fact, you probably want to have streaming
operations in their own
contracts to support alternative bindings that you configure specifically for streaming.
Additional Reading
For more information about how to
handle large binary data in WCF, see "Large Data
and Streaming" on the MSDN Web site.
Demonstration: Passing Large Binary Data in WCF
Lab: Improving Service Quality
Scenario
You must determine the best instance management and threading
approach for the Contoso, Ltd Clinic Management System. Opinion is divided on
whether to have a single service instance or multiple instances. You have been
asked to demonstrate some of the issues to the development manager and some of
the more technically-aware stakeholders. To do this, you must show how problems
such as lost or corrupt data can occur if the wrong option is selected.
Exercise 1: Managing WCF Service Instances
In this exercise, you will replace
the appointment service implementation with one that stores appointments on a
linked list. You will then set the state management style so that multiple
clients can access the appointments and load the service until it clearly
demonstrates concurrency issues.
The main tasks for this exercise
are as follows:
1. Start
the 6461A-LON-DEV-07
virtual machine and log on as Student.
2. Replace
the Appointment service implementation with one based on an in-memory linked
list.
3. Set
the instance context mode to share the appointment data between clients.
Task 1: Start the 6461A-LON-DEV-07
virtual machine and log on as Student
1. Open
the Virtual Server Remote Control Client, and then double-click 6461A-LON-DEV-07.
2. Log
on to 6461A-LON-DEV-07 as Student
by using the password Pa$$w0rd.
Task 2: Replace the appointment service
implementation with one based on an in-memory linked list
1. Start
Microsoft® Visual Studio® 2008 development system as ADMINISTRATOR.
2. Open
the starter solution ConnectedWCF.sln:
- If
you are using Microsoft Visual Basic® development system, browse to the E:\Labfiles\Starter\VB\InstanceManagement\ConnectedWCF
folder, and then double-click ConnectedWCF.sln.
- If
you are using Microsoft Visual C#® development tool, browse to the E:\Labfiles\Starter\CS\InstanceManagement\ConnectedWCF
folder, and then double-click ConnectedWCF.sln.
3. In
the AppointmentService project, open the
AppointmentServiceLinkedListImplementation
file, and then examine the code in this file to see how:
- The
constructor creates an instance of the LinkedListAppointmentHelper
class.
- The CreateAppointment and ListTodaysAppointments
methods delegate their functionality to the LinkedListAppointmentHelper
instance.
4. Examine
the code in the LinkedListAppointmentHelper
class to see how:
- The CreateAppointment method
wraps the Appointment
passed in as the parameter in a linked-list wrapper, steps through the
linked list to find the end, and appends the wrapped appointment to the
list.
- The ListTodaysAppointments
method navigates through the linked list and places any appointments that
occur today into a List<Appointment>
that it returns.
5. In
the ContosoServicesSelfHostExtConfig
project, in the ContosoServicesHost file,
in the Main
method, locate the TODO
1 comment, and change the service instance type for the
Appointment service to com.contoso.AppointmentService.AppointmentServiceLinkedListImplementation.
6. In
the ContosoServicesHost
project, open the App.config
file in the WCF Service Configuration Editor window, and change the name of the
com.contoso.AppointmentService.AppointmentServiceImplementation service
implementation to com.contoso.AppointmentService.AppointmentServiceLinkedListImplementation.
7. Build
the 'Connected WCF' solution.
8. Run
the ConnectedWCF solution with
debugging.
9. On
the Clinic
Administration Client form, on the Create Appointment tab,
click Find
Slots, and then verify that a list of available slots is displayed.
This confirms that the linked list form of the appointment service is running
correctly.
10. Stop
debugging.
Task 3: Set the instance management style
to share the appointment data between clients
1. In
the HighSpeedAppointmentMaker project,
open the HighSpeedMainForm file. This
form starts multiple client threads, each of which makes calls to the
appointment service.
Examine the AddAppointments method that each thread calls. This method creates a proxy for the appointment service and then calls the CreateAppointment operation 20 times. This method reports its progress by asking the appointment service for a list of the current appointments. The method then displays the number of appointments currently reported by the service, together with the number of appointments that this thread has added so far.
If you run this application with 4 threads, you would expect 80 (4 x 20) appointments to be made on the service.
Examine the AddAppointments method that each thread calls. This method creates a proxy for the appointment service and then calls the CreateAppointment operation 20 times. This method reports its progress by asking the appointment service for a list of the current appointments. The method then displays the number of appointments currently reported by the service, together with the number of appointments that this thread has added so far.
If you run this application with 4 threads, you would expect 80 (4 x 20) appointments to be made on the service.
2. Configure
the ConnectedWCF solution so that the ContosoServicesSelfHostExtConfig and HighSpeedAppointmentMaker projects start when you start
debugging.
3. Run
the ConnectedWCF solution with
debugging.
4. In
the High Speed Appointment Maker window,
increase the number of client threads to 4, and then click Go.
Each row shows the results from one thread. Verify that each thread has added 20 appointments. At least one of the values reported by the service should be 80 because that would be the last value reported by the service if it had received all 80 appointment requests. The problem is that the default instance management mode is PerSession, so each client thread gets its own instance of the appointment service which is independent of the other appointment service instances. The appointments made by the other client are not visible to the other threads; therefore, the maximum value that you will see reported is 20.
Each row shows the results from one thread. Verify that each thread has added 20 appointments. At least one of the values reported by the service should be 80 because that would be the last value reported by the service if it had received all 80 appointment requests. The problem is that the default instance management mode is PerSession, so each client thread gets its own instance of the appointment service which is independent of the other appointment service instances. The appointments made by the other client are not visible to the other threads; therefore, the maximum value that you will see reported is 20.
5. Stop
debugging.
6. In
the AppointmentService project, edit the
AppointmentServiceLinkedListImplementation class, and then locate the TODO 2 comment.
Add a ServiceBehaviorAttribute
to the AppointmentServiceLinkedListImplementation
class with its InstanceContextMode
property set to InstanceContextMode.Single.
All client threads will now access the same instance of the appointment
service.
7. Run
the ConnectedWCF solution with
debugging.
8. In
the High Speed Appointment Maker window,
increase the number of client threads to 4, and then click Go.
Verify that the service reports that it has received 80 appointment requests (at least one of the lines should report 80 appointments).
Verify that the service reports that it has received 80 appointment requests (at least one of the lines should report 80 appointments).
9. Stop
debugging.
|
Results: After completing this
exercise, you should have seen how to change the instance management mode on
your service and what effect this has.
|
Exercise 1: Answer Key (detailed steps)
Exercise 2: Managing Concurrency Issues
Scenario
You have been asked to demonstrate the problems that can occur
from longer-running methods and resource contention. To do this, you must show
how corruption can occur if the wrong combination of threading and instance
management is selected.
In this exercise, you will
intentionally create a threading problem in the linked-list version of the
appointment service implementation. You will then modify the threading mode so
that multiple clients can access the service without corruption.
The main tasks for this exercise
are as follows:
1. Demonstrate
that the service defaults to a safe threading mode.
2. Show
that attempts to speed up the service can lead to corruption due to
multithreading.
Task 1: Demonstrate that the service
defaults to a safe threading mode
1. In
Microsoft Visual Studio 2008, open the starter ConnectedWCF.sln
solution:
- If
you are using Visual Basic, browse to the E:\Labfiles\Starter\VB\Concurrency\ConnectedWCF
folder, and then double-click ConnectedWCF.sln.
- If
you are using Visual C#, browse to the E:\Labfiles\Starter\CS\Concurrency\ConnectedWCF
folder, and then double-click ConnectedWCF.sln.
2. In
Solution Explorer, in the AppointmentService
project, edit the LinkedListAppointmentHelper file,
and in the CreateAppointment
method, locate the TODO
3 comment. Add a call to the Thread.Sleep method passing a value
of 500 milliseconds. Add a Console.WriteLine
call before the call to Sleep,
and then print the current time (DateTime.Now.ToLongTimeString
method) together with the following properties of the appointment parameter:
- DoctorId
- PatientId
- Id
Add a Console.WriteLine call after
the call to Sleep,
and then print a message that indicates the sleep operation has finished and
displays the current time (DateTime.Now.ToLongTimeString
method).
The call to Sleep should enable any other thread running in the service to obtain a duplicate place in the linked list and so the service should gradually "lose" appointments.
The call to Sleep should enable any other thread running in the service to obtain a duplicate place in the linked list and so the service should gradually "lose" appointments.
3. Run
the ConnectedWCF solution with debugging.
4. In
the High Speed Appointment Maker window,
increase the number of client threads to 4, and then click Go.
Verify that each thread reports that it has added 20 appointments and that at least one of the values reported by the service is 80. Because the instance context mode is Single, you may expect that the Sleep call you that added would cause corruption as described in step 5.
The reason that there is no corruption is because the default threading mode is Single, so this prevents any other calling thread from accessing the service instance even if an earlier caller is sleeping in the service. However, the price that you pay for this safety is a potential reduction in performance.
Verify that each thread reports that it has added 20 appointments and that at least one of the values reported by the service is 80. Because the instance context mode is Single, you may expect that the Sleep call you that added would cause corruption as described in step 5.
The reason that there is no corruption is because the default threading mode is Single, so this prevents any other calling thread from accessing the service instance even if an earlier caller is sleeping in the service. However, the price that you pay for this safety is a potential reduction in performance.
5. Stop
debugging.
Task 2: Show that attempts to speed up
the service can lead to corruption due to multithreading
1. In
Solution Explorer, in the AppointmentService
project, edit the AppointmentServiceLinkedListImplementation
file, and then locate the TODO 2 comment. Amend the ServiceBehaviorAttribute
and set the ConcurrencyMode
property to ConcurrencyMode.Multiple.
All client threads will now be able to access the instance of the appointment
service at the same time.
2. Run
the ConnectedWCF solution with
debugging.
3. In
the High Speed Appointment Maker window,
increase the number of client threads to 4, and then click Go.
Verify that each thread reports that it has added 20 appointments but that the values reported by the service are well below 80. As you can see, in an effort to improve performance, this has opened up potential for corruption due to resource contention (in this case the resource is the linked list).
Verify that each thread reports that it has added 20 appointments but that the values reported by the service are well below 80. As you can see, in an effort to improve performance, this has opened up potential for corruption due to resource contention (in this case the resource is the linked list).
4. Stop
debugging.
|
Results: After completing this
exercise, you should have seen how to control the threading mode of a
service.
|
Exercise 2: Answer Key (detailed steps)
Exercise 3: Throttling Access to a WCF Service
Scenario
The level of load placed on the Contoso Clinic Management System
will vary over time as more family practitioners sign up to the service.
Additionally, the level of load from the family practitioners will be
unpredictable over the course of a week. However, one thing is for certain:
when patients stand at the administrator's desk in the practice waiting for
their appointment, they will not appreciate the system running slowly. Because
you will probably initially deploy the system on a limited amount of hardware,
you must explore how effective throttling the number of clients will be in
terms of maintaining service performance.
In this exercise, you will
investigate how the service throttling setting affects the response time for
successful callers and its overall impact on response times and throughput.
The main tasks for this exercise
are as follows:
1. Take
an initial measure of the response times.
2. Determine
the effect of throttling on overall response times.
3. Determine
the effect of throttling on successful caller response times.
Task 1: Take an initial measure of the
response times
1. In
Microsoft Visual Studio 2008, open the starter ConnectedWCF.sln
solution:
- If
you are using Visual Basic, browse to the E:\Labfiles\Starter\VB\Throttling\ConnectedWCF
folder, and then double-click ConnectedWCF.sln.
- If
you are using Visual C#, browse to the E:\Labfiles\Starter\CS\Throttling\ConnectedWCF
folder, and then double-click ConnectedWCF.sln.
2. In
Solution Explorer, in the HighSpeedAppointmentMaker
project, edit the HighSpeedMainForm file.
This version of the form times the duration of the calls made by each client
thread and provides you with an overall average.
In the AddAppointments method, locate the TODO 4 comment, and then examine the code underneath it. This code takes a timestamp before the calls to the CreateAppointment and ListTodaysAppointments operations and then uses this information to calculate an average timing across the 20 pairs of calls.
Note: Because these timings are taken on the client side, they will include any wait time encountered by the call; for example, they will include the time that the call is blocked if it must wait for a service instance.
In the AddAppointments method, locate the TODO 4 comment, and then examine the code underneath it. This code takes a timestamp before the calls to the CreateAppointment and ListTodaysAppointments operations and then uses this information to calculate an average timing across the 20 pairs of calls.
Note: Because these timings are taken on the client side, they will include any wait time encountered by the call; for example, they will include the time that the call is blocked if it must wait for a service instance.
3. Run
the ConnectedWCF solution with
debugging.
4. In
the High Speed Appointment Maker window,
increase the number of client threads to 10, and then click Go.
After all the threads finish running, you will see a dialog box that contains an average value for the call duration across the 10 threads. Make a note of this value, and then click OK.
After all the threads finish running, you will see a dialog box that contains an average value for the call duration across the 10 threads. Make a note of this value, and then click OK.
5. Stop
debugging.
Task 2: Determine the effect of
throttling on overall response times
1. Edit
the configuration file for the ContosoServicesSelfHostExtConfig
project, add a serviceThrottling
element to the HttpMexAndExceptionDetail
behavior, and then set the value of MaxConcurrentCalls
property to 3.
2. Run
the ConnectedWCF solution with
debugging.
3. In
the High Speed Appointment Maker window,
increase the number of client threads to 10, and then click Go.
After the threads have run, you will see a dialog box that contains an average value for the call duration across the 10 threads. Make a note of this value, and click then OK.
Compare this value with the one that you recorded in Task 1. Has throttling increased or decreased this overall client-side time?
You should find that setting a throttling value of less than the number of calling threads has increased the average time taken per-call when measured from the client side. This is because calling threads wait for other calling threads to leave a service instance so that the number of concurrent calls drops below 3.
After the threads have run, you will see a dialog box that contains an average value for the call duration across the 10 threads. Make a note of this value, and click then OK.
Compare this value with the one that you recorded in Task 1. Has throttling increased or decreased this overall client-side time?
You should find that setting a throttling value of less than the number of calling threads has increased the average time taken per-call when measured from the client side. This is because calling threads wait for other calling threads to leave a service instance so that the number of concurrent calls drops below 3.
4. Stop
debugging.
Task 3: Determine the effect of
throttling on successful caller response times
1. In
Solution Explorer, in the HighSpeedAppointmentMaker
project, edit the HighSpeedMainForm
file, and in the AddAppointments
method, locate the TODO
4 comment. Perform the following steps:
- Remove
the variables startTimestamp and endTimestamp.
- Replace
the call to CreateAppointment
with a call to TimedCreateAppointment.
This is a form of the CreateAppointment
method that times the duration of the call inside the service and returns
this duration as a TimeSpan.
Assign the return value to a variable named callTime of type TimeSpan.
- Replace
the call to ListTodaysAppointments
with a call to TimedListTodaysAppointments.
This is a form of the ListTodaysAppointments
method that times the duration of the call inside the service and returns
this duration as a TimeSpan.
Add the return value to the callTime variable.
- Assign
the Milliseconds
property of the callTime variable to the millisThisCall
variable.
2. Run
the ConnectedWCF solution with
debugging.
3. In
the High Speed Appointment Maker window,
increase the number of client threads to 10, and then click Go.
After all the threads run, you will see a dialog box that contains an average value for the call duration across the 10 threads. Make a note of this value, and then click OK.
Compare this value with the ones that you recorded in Task 2. This new value should be significantly lower because it is recording the duration of calls on the service-side when there are only 3 concurrent calls. This does not include any wait time.
After all the threads run, you will see a dialog box that contains an average value for the call duration across the 10 threads. Make a note of this value, and then click OK.
Compare this value with the ones that you recorded in Task 2. This new value should be significantly lower because it is recording the duration of calls on the service-side when there are only 3 concurrent calls. This does not include any wait time.
4. Stop
debugging.
5. Edit
the configuration file for the ContosoServicesSelfHostExtConfig
project to change the value of MaxConcurrentCalls
to 20.
6. Save
your changes, and then close the WCF Service Configuration Editor window.
7. Run
the ConnectedWCF solution with
debugging.
8. In
the High Speed Appointment Maker window,
increase the number of client threads to 10, and then click Go.
After all the threads run, you will see a dialog box that contains an average value for the call duration across the 10 threads. Make a note of this value, and then click OK.
Compare this value with the one that you recorded earlier in this task. Has removing throttling increased or decreased this overall service-side time?
You should find that setting the throttling value to more than the number of calling threads has increased the average time taken per-call when measured from the service-side. This is because there are now potentially 10 concurrent calling threads contending for service-side resources at the same time, therefore the call time for each thread will increase.
After all the threads run, you will see a dialog box that contains an average value for the call duration across the 10 threads. Make a note of this value, and then click OK.
Compare this value with the one that you recorded earlier in this task. Has removing throttling increased or decreased this overall service-side time?
You should find that setting the throttling value to more than the number of calling threads has increased the average time taken per-call when measured from the service-side. This is because there are now potentially 10 concurrent calling threads contending for service-side resources at the same time, therefore the call time for each thread will increase.
9. Stop
debugging.
|
Results: After completing this
exercise, you should have seen how to use throttling and how it affects the
callers to a service.
|
Exercise 3: Answer Key (detailed steps)
Exercise 4: Passing Bulk Data between a WCF Client and Service
Scenario
The consultants who use the Contoso Clinic Management System will
require access to large amounts of patient data in the form of MRI scan and
X-ray images. These files will be far larger than is reasonable to pass as a
standard parameter, so they will require some form of special handling.
In this exercise, you will pass
large binary data across a WCF service interface by using both MTOM and
streaming.
The main tasks for this exercise
are as follows:
1. Add
an operation to return an image as a byte array to a WCF service.
2. Add
an endpoint for the contract that uses MTOM encoding.
3. Add
code to the client to call the new operation.
4. Configure
and run the client.
5. View
the raw MTOM messages.
6. Add
a streamed method to the contract.
7. Change
the service-side endpoint to support streaming.
8. Change
the client code to call the new operation.
9. Configure
and run the client.
10. View the
raw streamed messages.
Task 1: Add an operation to return an
image as a byte array to a WCF service
1. In
Microsoft Visual Studio 2008, open the starter ConnectedWCF.sln
solution.
- If
you are using Visual Basic, browse to the E:\Labfiles\Starter\VB\BulkData\ConnectedWCF
folder, and then double-click ConnectedWCF.sln.
- If
you are using Visual C#, browse to the E:\Labfiles\Starter\CS\BulkData\ConnectedWCF
folder, and then double-click ConnectedWCF.sln.
2. In
Solution Explorer, in the PatientManagementService
project, edit the PatientManagementServiceImageContract
file, and then locate the TODO
5 comment. Add a WCF operation with the following properties:
- Name:
GetXrayImage
- Return
type: byte[]
- Parameters:
string
patientId, string
type
3. Edit
the PatientManagementServiceImplementation
class, and then locate the TODO
6 comment. Add PatientManagementServiceImageContract
to the list of interfaces implemented by the PatientManagementServiceImplementation class.
4. Implement
the GetXrayImage
method in the implementation class. This method should perform the following
tasks:
- Call
the helper method GetImageAsStream,
passing the image type and getting back a memory stream.
- Convert
the memory stream to a byte array and return this from the method.
Task 2: Add an endpoint for the contract
that uses MTOM encoding
1. Edit
the configuration of the ContosoServicesSelfHostExtConfig
project to add a new endpoint with the following properties:
- Name:
PMIService_WS
- Address:
PatientManagementServiceImages
- Binding:
wsHttpBinding
- Contract:
com.contoso.PatientManagementService.PatientManagementServiceImageContract
2. Add
a new binding configuration of type wsHttpBinding
that has the following properties:
- Name:
WebServiceMtomBindingConfig
- MessageEncoding:
Mtom
3. Apply
the WebServiceMtomBindingConfig
binding configuration to the PMIService_WS
endpoint.
4. Rebuild
the solution.
Task 3: Add code to the client to call
the new operation
1. In
Windows Explorer, browse to the ContosoServicesSelfHostExtConfig.exe file at either of the following locations, and then
run it as ADMINISTRATOR.
- If
you are using Visual Basic, browse to the
E:\Labfiles\Starter\VB\BulkData\ConnectedWCF\ContosoServicesSelfHostExtConfig\bin\Debug
folder.
- If
you are using Visual C#, browse to the
E:\Labfiles\Starter\CS\BulkData\ConnectedWCF\ContosoServicesSelfHostExtConfig\bin\Debug
folder.
2. In
the ConsultantClient
project, update the PatientManagementServiceReference.
3. Close
the ContosoServicesSelfHostExtConfig
application.
4. In
Solution Explorer, under the ConsultantClient
project, edit the ConsultantForm
file, and in the GetImageStreamFromBytes
method, locate the TODO
7 comment. Replace the existing code in this method with
statements that perform the following tasks:
- Create
a new instance of the PatientManagementServiceImageContractClient
proxy class.
- Call
the GetXrayImage
method on the proxy passing PatientId.Text and typeOfXray as parameters.
- Create
a new MemoryStream
by passing the byte array returned from GetXrayImage to the
constructor, and then return this MemoryStream
instance from the method.
5. In
the GetImage_Click
method, locate the TODO
8 comment. Examine the preceding two lines of code, which call
the GetImageStreamFromBytes
method, and display the contents of the returned imageStream variable. Add a line of code to close the imageStream after
it has been displayed.
Note:
It is important to close the image stream on the client. In this tasks, the
stream is created locally in client code. However, when you use streaming later
on, the stream will be created by WCF; you must therefore explicitly close it
in the client code.
Task 4: Configure and run the client
1. Edit
the configuration file for the ConsultantClient
project and examine the PMIService_WS
endpoint. This endpoint already has a binding configuration called PMIService_WS.
2. Open
the PMIService_WS
binding configuration, and then perform the
following steps:
- Examine
the value of the MessageEncoding
and verify that it is already set to Mtom.
- Set
the value of the MaxReceivedMessageSize
property to 12000000
(12 million). The X-ray files passed are 6 MB in size, so this should
enable WCF to pass them successfully. If this buffer size is smaller than
the message, an exception will be thrown.
- Set
the value of the MaxArrayLength
under ReaderQuotasProperties
to 12000000
(12 million) for the same reason. This allocates more space to process the
XML representation of the message.
Note:
If this was a production strength application, it is likely that you would
split the large file into multiple pieces instead of having a very large buffer
size.
3. Switch
to Windows Explorer, and then browse to the E:\LabFiles\logs
folder.
4. In
the logs folder, delete the existing messages.svclog file.
5. Switch
to Visual Studio, and then run the ConnectedWCF solution
with debugging.
6. In
the Consultant Client window, click the Patient Information
tab. On the Patient
Information tab, click Chest,
and then click Get
Image.
You should see an X-ray image displayed on the Patient Information tab.
You should see an X-ray image displayed on the Patient Information tab.
7. Stop
debugging.
Task 5: View the raw MTOM messages
1. Start
the Microsoft Service Trace Viewer,
and then open the E:\LabFiles\logs\messages.svclog file.
2. In
the Service Trace Viewer, in the left pane, click the Message tab, and
then click a message with an action of http://contoso.com/ClinicManagementSystem/2007/10/PatientManagementServiceImageContract/GetXrayImage.
Note:
You will see each message and response listed twice. This is because the
service has been configured to log each message at the message level and the
transport level.
3. In
the lower-right pane, click the Message
tab, and then examine the Hypertext Transfer Protocol (HTTP) request header.
Verify that the WebHeaders
element contains a Content-Type
element that in turn contains a string that starts with multipart/related;type="application/xop+xml".
This confirms that it uses MTOM encoding.
4. Click
a message with an action of http://contoso.com/ClinicManagementSystem/2007/10/PatientManagementServiceImageContract/GetXrayImageResponse.
5. Click
the Message
tab, and then examine the SOAP message. Scroll down to find the SOAP body and
verify that its <s:Body>
element contains an empty GetXrayImageResult
element. This is because the content is in a separate MIME part.
Task 6: Add a streamed method to the
contract
1. In
Solution Explorer, under the PatientManagementService
project, edit the PatientManagementServiceImageContract
file, and then add a WCF operation with the following properties:
- Name:
StreamXrayImage
- Return
type: Stream
- Parameters:
string
patientId, string type
2. Locate
the TODO 9
comment, and then bring the System.IO
namespace into scope.
3. In
Solution Explorer, under the PatientManagementService
project, edit the PatientManagementServiceImplementation
class, and then implement the StreamXrayImage
method:
- Create
a string variable named imagePath by concatenating the string literal "..\..\DataFiles\xray_",
the type parameter passed into the method, and the string literal ".png".
- Call
the static method OpenRead
on the File
class, passing the imagePath variable as its parameter.
Use the value returned from the OpenRead
call as the return value for the StreamXrayImage
method.
Task 7: Change the service-side endpoint
to support streaming
1. Edit
the configuration of the ContosoServicesSelfHostExtConfig
project, and then change the PMIService_WS
endpoint. Configure the endpoint as follows:
- Name:
PMIService_TCP
- Address:
PatientManagementServiceImages
- Binding:
netTcpBinding
- Contract:
com.contoso.PatientManagementService.PatientManagementServiceImageContract
2. Add
a new binding configuration of type netTcpBinding,
and then configure the binding as follows:
- Name:
NetTcpStreamingBindingConfig
- TransferMode:
Streamed
3. Apply
the NetTcpStreamingBindingConfig
binding configuration to the PMIService_TCP
endpoint.
4. Save
your changes, and then close the WCF Service Configuration Editor window.
5. Rebuild
the solution.
Task 8: Change the client code to call
the new operation
1. In
Windows Explorer, browse to the ContosoServicesSelfHostExtConfig.exe file at
either of the following locations, and then run it as ADMINISTRATOR.
- If you
are using Visual Basic, browse to the
E:\Labfiles\Starter\VB\BulkData\ConnectedWCF\ContosoServicesSelfHostExtConfig\bin\Debug
folder.
- If you
are using Visual C#, browse to the
E:\Labfiles\Starter\CS\BulkData\ConnectedWCF\ContosoServicesSelfHostExtConfig\bin\Debug
folder.
2. In
the ConsultantClient
project, update the PatientManagementServiceReference.
3. Close
the ContosoServicesSelfHostExtConfig
application.
4. In
Solution Explorer, in the ConsultantClient
project, edit the ConsultantForm file,
and then locate the TODO
10 comment. Make the following changes to the code:
- Create
a new instance of the PatientManagementServiceImageContractClient
proxy class, passing the value "PMIService_TCP"
to its constructor.
- Call
the StreamXrayImage
method on the proxy, passing PatientId.Text and typeOfXray as parameters.
Use the return value from the StreamXrayImage
method call as the return value from the GetImageStream method.
5. Locate
the TODO 11
comment, and then replace the call to GetImageStreamFromBytes
with a call to GetImageStream.
Task 9: Configure and run the client
1. Edit
the configuration of the ConsultantClient
project.
This file contains a binding configuration called PMIService_TCP.
This file contains a binding configuration called PMIService_TCP.
2. Modify
the PMIService_TCP binding configuration as follows:
- Examine
the value of the TransferMode, and
then verify that it is already set to Streamed.
- Set
the value of the MaxReceivedMessageSize
property to 12000000
(12 million).
3. Run
the ConnectedWCF solution with
debugging.
4. In
the Consultant Client window, click the Patient Information
tab. On the Patient
Information tab, click Chest,
and then click Get
Image.
You should see an X-ray image displayed on the Patient Information tab.
You should see an X-ray image displayed on the Patient Information tab.
5. Stop
debugging.
Task 10: View the raw streamed messages
1. Switch
to the Service Trace Viewer, open
the file E:\LabFiles\logs\messages.svclog, and then click Open.
2. Click
the Message
tab to display a list of messages passed between the client and the service.
3. Click
a message with an action of http://contoso.com/ClinicManagementSystem/2007/10/PatientManagementServiceImageContract/StreamXrayImageResponse.
4. Click
the Message
tab, and then examine the SOAP message. Scroll down to find the SOAP body and
verify that its <s:Body>
element contains …stream….
|
Results: After completing this
exercise, you should have seen how to pass bulk binary data between a WCF
client and service.
|
Great Article
ReplyDeleteOnline WCF Training
WCF Training
Online WCF Training from India
WCF Training in Chennai
C-Sharp Training
Dot Net Training in Chennai
.Net Online Training
ASP.NET Training
After seeing your article I want to say that the presentation is very good and also a well-written article with some very good information which is very useful for the readers....thanks for sharing it and do share more posts like this.
ReplyDeleteData Science training in rajaji nagar
Data Science with Python training in chennai
Data Science training in electronic city
Data Science training in USA
Data science training in pune
yeni perde modelleri
ReplyDeletesms onay
mobil ödeme bozdurma
Nft Nasıl Alinir
ankara evden eve nakliyat
trafik sigortası
DEDEKTÖR
Web Site Kurma
aşk kitapları
smm panel
ReplyDeletesmm panel
İs ilanlari
İnstagram takipçi satın al
hirdavatciburada.com
beyazesyateknikservisi.com.tr
servis
tiktok jeton hilesi