WCF Troubleshooting Quickstart
This topic uses a question-and-answer format to describe some of the most common issues that occur, what you can do to solve them, and where to locate more information about the issue.
Questions
Question: Sometimes I receive a MessageSecurityException on the second request if my client is idle for a while after the first request. What is happening?
The second request can fail primarily for two reasons: (1) the session has timed out or (2) the Web server that is hosting the service is recycled. In the first case, the session is valid until the service times out. When the service does not receive a request from the client within the period of time specified in the service's binding (ReceiveTimeout), the service terminates the security session. Subsequent client messages result in the MessageSecurityException. The client must re-establish a secure session with the service to send future messages or use a stateful security context token. Stateful security context tokens also allow a secure session to survive a Web server being recycled. For more information about using stateful secure context tokens in a secure session, see How to: Create a Stateful Security Context Token for a Secure Session. Alternatively, you can disable secure sessions. When you use the WsHttpBinding binding, you can set the establishSecurityContext property to false to disable secure sessions. To disable secure sessions for other bindings, you must create a custom binding. For details about creating a custom binding, see How to: Create a Custom Binding Using the SecurityBindingElement. Before you apply any of these options, you must understand your application's security requirements.
Question: My service starts to reject new clients after about 10 clients are interacting with it. What is happening?
By default, services can have only 10 concurrent sessions. Therefore, if the service bindings use sessions, the service accepts new client connections until it reaches that number, after which it refuses new client connections until one of the current sessions ends. You can support more clients in a number of ways. If your service does not require sessions, do not use a sessionful binding. (For more information, see Using Sessions.) Another option is to increase the session limit by changing the value of the MaxConcurrentSessions property to the number appropriate to your circumstance.
Question: Can I load my service configuration from somewhere other than the WCF application’s configuration file?
Yes, however, you have to create a custom ServiceHost class that overrides the ApplyConfiguration method. Inside that method, you can call the base to load configuration first (if you want to load the standard configuration information as well) but you can also entirely replace the configuration loading system. Note that if you want to load configuration from a configuration file that is different from the application configuration file, you must parse the configuration file yourself and load the configuration.
The following code example shows how to override the ApplyConfiguration method and directly configure an endpoint.
public class MyServiceHost : ServiceHost
{
public MyServiceHost(Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{ Console.WriteLine("MyServiceHost Constructor"); }
protected override void ApplyConfiguration()
{
string straddress = GetAddress();
Uri address = new Uri(straddress);
Binding binding = GetBinding();
base.AddServiceEndpoint(typeof(IData), binding, address);
}
string GetAddress()
{ return "http://MyMachine:7777/MyEndpointAddress/"; }
Binding GetBinding()
{
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.None;
return binding;
}
}
Question: My service and client work great, but I can’t get them to work when the client is on another computer? What’s happening?
Depending upon the exception, there may be several issues:
You might need to change the client endpoint addresses to the host name and not "localhost".
You might need to open the port to the application. For details, see Firewall Instructions from the SDK samples.
For other possible issues, see the samples topic, Running the Samples in a Workgroup and Across Machines.
If your client is using Windows credentials and the exception is a SecurityNegotiationException, configure Kerberos as follows.
Add the identity credentials to the endpoint element in the client’s App.config file:
<endpoint address="http://MyServer:8000/MyService/" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IServiceExample" contract="IServiceExample" behaviorConfiguration="ClientCredBehavior" name="WSHttpBinding_IServiceExample"> <identity> <userPrincipalName value="name@corp.contoso.com"/> </identity> </endpoint>
Run the self-hosted service under the System or NetworkService account. You can run this command to create a command window under the System account:
at 12:36 /interactive "cmd.exe"
Host the service under Internet Information Services (IIS), which, by default, uses the service principal name (SPN) account.
Register a new SPN with the domain using SetSPN. Note that you will need to be a domain administrator in order to do this.
For more information about the Kerberos protocol, see Security Concepts Used in WCF and:
Question: When I throw a FaultException<Exception> where the type is an exception, I always receive a general FaultException type on the client and not the generic type. What’s happening?
It is highly recommended that you create your own custom error data type and declare that as the detail type in your fault contract. The reason is that using system-provided exception types:
Creates a type dependency that removes one of the biggest strengths of service-oriented applications.
Cannot depend upon exceptions serializing in a standard way. Some—like SecurityException—may not be serializable at all.
Exposes internal implementation details to clients. For more information, see Specifying and Handling Faults in Contracts and Services.
If you are debugging an application, however, you can serialize exception information and return it to the client by using the ServiceDebugBehavior class.
Question: It seems like one-way and request-reply operations return at roughly the same speed when the reply contains no data. What's happening?
Specifying that an operation is one way means only that the operation contract accepts an input message and does not return an output message. In WCF, all client invocations return when the outbound data has been written to the wire or an exception is thrown. One-way operations work the same way, and they can throw if the service cannot be located or block if the service is not prepared to accept the data from the network. Typically in WCF, this results in one-way calls returning to the client more quickly than request-reply; but any condition that slows the sending of the outbound data over the network slows one-way operations as well as request-reply operations. For more information, see One-Way Services and Accessing Services Using a Client.
Question: I’m using an X.509 certificate with my service and I get a System.Security.Cryptography.CryptographicException. What’s happening?
This commonly occurs after changing the user account under which the IIS worker process runs. For example, in Windows XP, if you change the default user account that the Aspnet_wp.exe runs under from ASPNET to a custom user account, you may see this error. If using a private key, the process that uses it will need to have permissions to access the file storing that key.
If this is the case, you must give read access privileges to the process's account for the file containing the private key. For example, if the IIS worker process is running under the Bob account, then you will need to give Bob read access to the file containing the private key.
For more information about how to give the correct user account access to the file that contains the private key for a specific X.509 certificate, see How to: Make X.509 Certificates Accessible to WCF.
Question: I changed the first parameter of an operation from uppercase to lowercase; now my client throws an exception. What's happening?
The value of the parameter names in the operation signature are part of the contract and are case-sensitive. Use the System.ServiceModel.MessageParameterAttribute attribute when you need to distinguish between the local parameter name and the metadata that describes the operation for client applications.
Question: I’m using one of my tracing tools and I get an EndpointNotFoundException. What’s happening?
If you are using a tracing tool that is not the system-provided WCF tracing mechanism and you receive an EndpointNotFoundException that indicates that there was an address filter mismatch, you need to use the ClientViaBehavior class to direct the messages to the tracing utility and have the utility redirect those messages to the service address. The ClientViaBehavior class alters the Via addressing header to specify the next network address separately from the ultimate receiver, indicated by the To addressing header. When doing this, however, do not change the endpoint address, which is used to establish the To value.
The following code example shows an example client configuration file.
<endpoint
address=https://localhost:8000/MyServer/
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IMyContract"
behaviorConfiguration="MyClient"
contract="IMyContract"
name="WSHttpBinding_IMyContract">
</endpoint>
<behaviors>
<endpointBehaviors>
<behavior name="MyClient">
<clientVia viaUri="https://localhost:8001/MyServer/"/>
</behavior>
</endpointBehaviors>
</behaviors>
Question: What is the base address? How does it relate to an endpoint address?
A base address is the root address for a ServiceHost class. By default, if you add a ServiceMetadataBehavior class into your service configuration, the Web Services Description Language (WSDL) for all endpoints the host publishes are retrieved from the HTTP base address, plus any relative address provided to the metadata behavior, plus "?wsdl". If you are familiar with ASP.NET and IIS, the base address is equivalent to the virtual directory.
Question: How do I expose multiple endpoints for one service?
You do this by adding <endpoint> elements to the <service> element in an application configuration file or by performing the equivalent steps programmatically. For more information, see Specifying an Endpoint Address, How to: Create a Service Endpoint in Configuration, and How to: Create a Service Endpoint in Code.
Question: How do I know which bindings support different behaviors?
For more information about system-provided bindings and the features they support, see System-Provided Bindings.
Question: How do I configure a standard binding with different values for any of the attributes?
For more information, see Configuring Bindings for Windows Communication Foundation Services.
Question: Do I need to deploy my service to an HTTP server if I want to use HTTP as the transport?
No. The system-provided bindings include several that support HTTP transports when used from any host application type. For more information about system-provided bindings and the features they support, see System-Provided Bindings.
Question: What is the default behavior for a service that uses standard bindings?
This depends upon the standard binding chosen. In general, the default behavior for bindings that use sessions is to create a new service instance for each new client, and subsequent calls from a particular client are routed to the associated service instance. For more information about system-provided bindings and the features they support, see System-Provided Bindings.
Question: Is there an easy way to see the mapping of features to bindings? For example, how can I tell which bindings support transactions, security, etc.?
Yes. See System-Provided Bindings.
Question: How do I pass custom data types from a service to a client?
Data types passed between two endpoints must be serializable, and the easiest and most interoperable serialization mechanism for services is to use the DataContractAttribute and DataMemberAttribute classes. For more information about this and other supported serialization mechanisms, see Specifying Data Transfer in Service Contracts.
Question: When should I configure something using a configuration file and when should I configure it in code?
Because an application configuration file enables the developer to place decisions about run-time configuration in the hands of the deployer, decisions that deployers should never make are good candidates for configuration in the product code. Deployers can be individuals installing programs on their own machines, or enterprise administrators using enterprise group policies to modify machine configuration files and locking them down against local modification. For an example of the latter, see How to: Lock Down Endpoints in the Enterprise.
Question: What should I know about designing a well-behaved service?
See Designing and Implementing Services.
Question: What is all this stuff in the generated client code?
To find your way around the generated client code, see Understanding Generated Client Code. For more information about the client architecture, see Client Architecture.
Question: Why should I call the Close method on the WCF client object?
Calling Close on the WCF client object enables the client and service to gracefully conclude the conversation and recycle resources associated with it. In addition, if you are using sessions, calling Close may be the quickest way to determine whether the session has faulted since the last call, a scenario that can have meaning for your client application. For more information, see Accessing Services Using a WCF Client and the sample Expected Exceptions.
Question: Why does my service not run as I expect it to even when the code looks fine?
If your service application is configured using an application configuration file, you should examine that file to determine whether some configuration element or attribute is altering execution behavior in an unexpected way. In particular, run-time behavior depends quite a bit on the binding that implements the contract in an endpoint. Confirm that the binding in the configuration file supports the features that you wanted and in a way that you expect.
If the configuration file looks fine, you can continue to examine your application's run-time behavior by using diagnostics features such as logging and tracing. For more information, see WCF Administration and Diagnostics.
Question: What is the best way to tell a client that something went wrong on the service?
The best way to do this is by adding a FaultContractAttribute class with a custom serializable error data type to your operation. Then, when your operation encounters an error condition that it can detect, it throws a new FaultException where the type parameter is the serializable error type. For more information, see Specifying and Handling Faults in Contracts and Services.
Question: What information is okay to pass back to the client?
Return only that information that clients of your service need to know. As the designer of the service, you should provide only that amount of information and no more to minimize the exposure of internal implementation details to unauthorized clients. This is why it is strongly recommended that you do not return Exception objects in your SOAP faults. For more information, see Specifying and Handling Faults in Contracts and Services.
Question: How does my client application detect that a connection to a service has closed?
You can handle the client channel's CommunicationObject state change events; however, when you are notified of the closing or faulting of a channel depends upon the channel implementation. For example, a NetTcpBinding class notifies you fairly quickly that the channel is closed or faulted because the lifetime of its session is associated with the lifetime of the underlying socket.
However, a sessionful binding that is designed to protect the application against small network disturbances, like the session provided by the ReliableSessionBindingElement class, may not notify you for some time while it attempts to reestablish the session. Because this is the case, it is recommended that you do not attempt to detect the disconnection directly.
Instead, treat the session as a conversation. If you open the channel, make several operation calls and close the channel successfully, then you can assume that the channel did not close unexpectedly. For more information about clients and sessions, see Using Sessions. For more information about handling channel-related exceptions on the client, see Accessing Services Using a Client. For information about exception handling in general, see Specifying and Handling Faults in Contracts and Services.
Question: How do I configure a Secure Sockets Layer certificate for WCF service security?
See How to: Configure a Port with an SSL Certificate.
Question: How do I use message inspectors to log or modify the message?
See the following topics:
Question: How do I add an endpoint address that has extra information?
When you want to attach programmatically complex endpoint addresses (for example, if you need to programmatically specify an EndpointAddress class that contains a specific header or identity), you must do the following, where relativeOrAbsoluteAddress
is a relative or absolute Uniform Resource Identifier (URI):
// Do this:
ServiceEndpoint e = myServiceHost.AddServiceEndpoint(c,b,"relativeOrAbsoluteAddress");
e.Address = new EndpointAddress(e.Address.Uri, /*other info like headers */);
Question: I am trying to build a web-hosted sample and the build fails because a make directory, copy or delete command fails. Why is this happening?
As part of the build process, some web-hosted samples attempt to copy compiled WCF service binaries to the %SystemDrive%\inetpub\wwwroot\ServiceModelSamples folder. This effectively deploys the service in IIS. If the account under which the SDK command prompt or Visual Studio is running does not have permission to modify the folder, the build will break. To correct this you can do one of the following
Grant modify permission for %SystemDrive%\inetpub\wwwroot to the account under which you are building the sample
or
Run the SDK command prompt or Visual Studio as an Administrator.