WCF
Q: How do I create a test cert for a WCF service?
A: Follow these instructions on the WCF service computer.
1. Run a VS2010 command prompt, elevated if on Vista+.
2. Enter "makecert -sr LocalMachine -ss MY -a sha1 -n CN=<your machine's FQDN> -sky exchang"
3. Run mmc
4. Select File|Add/Remove Snap-In
5. If on XP, click Add.
6. Select Certificates and click Add.
7. Select Computer Account, then Next.
8. Select Local Computer, then Finish.
9. If on XP, click Close.
10. Click OK.
11. Browse to Certificates\Personal\Certificates and select the certificate you created. Generally it is the only one. If in doubt, the Issued To should match the machine's FQDN you specified in step b.
12. Right click the Certificate and select All Tasks|Export.
13. Take all the defaults, specify a export filename, and click Finish when done.
14. Right click Certificates\Trusted People\Certificates and select All Tasks|Import.
15. Click Next and select the filename you entered in step m.
16. Click Next, Next, and Finish.
Repeat steps 14-16 on the WCF client. To automate these steps, use CAPICOM via VBScript or JScript, but note CAPICOM was not bundled with Windows until Windows 7/Server 2008.
Q: When I configure my WCF service for HTTPS, WctTestClient fails. A local browse to the service URI gives the following error:
Could not find a base address that matches scheme https for the endpoint with binding WSHttpBinding. Registered base address schemes are [http].
A: The ASP Net Development Server used by Visual Studio does not support HTTPS. See http://connect.microsoft.com/VisualStudio/feedback/details/354576/add-https-support-to-visual-studio-asp-net-development-server.
Q: When I call a method in a WCF service contract from a WCF client, I get an exception "The underlying connection was closed: The connection was closed unexpectedly." but the server is fine.
A: This is a serialization/deserialization issue - there can be many causes. See the note on how to enable logging to get the exception details. Notes:
1. Polymorphism can cause this. You must provide a KnownType attribute on the base class for each subclass to expose the polymorphic relationship to the SOAP WSDL. Otherwise, each class is considered it's own type and the deserializer always fails (unless you send the base class type). Microsoft also recommends that you specify a unique WSDL name for each subclass by specifying DataContract(Name) on each subclass, but this does not appear necessary for SOAP polymorphism. Note also that if you use polymorphic types in collections in a class used by the WSDL, you must decorate that class with a KnownTypes for each subclass and the collection type(s). See MSDN's Collection Types in Data Contracts (search fo collection types, then data collection subitem) for more information.
2. Returning an Object type or interface also requires KnownType decoration as the client has no idea what to deserialize the type to otherwise. See the WCF article WCF Feature Details\Data Transfer and Serialization\Using Data Contracts\Data Contract Known Types for other scenarios where KnownTypes is needed.
3. If there are enums in the interface contract, decorate them with [DataContract] and each value with [EnumMember].
4. Reduce the number of items passed via array or increase the default max's for the binding used by this interface, such as:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="myBindingForBigArrays"
maxReceivedMessageSize="2147483647">
<readerQuotas
maxDepth="64"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="4096"
maxNameTableCharCount="16384"/>
</binding>
</basicHttpBinding>
</bindings>
If returning very large numbers of items, you must also increase maxItemsInObjectGraph on both server and client.
5. You are using MTOM streaming, returning a stream to a client, and did not set the Stream member in the return value.. To return a 0-byte stream for error returns, use a MemoryStream.
Q: How do I enable logging for my WCF service?
A: Edit the Web.config file and add the following inside <configuration>. When run via DevStudio, the log is a text file stored in the project directory, not bin/Debug. New information is appended to the end. All serialization errors are described explicitly.
<system.diagnostics>
<sources>
<source name="System.ServiceModel.MessageLogging" switchValue="Warning, ActivityTracing" >
<listeners>
<add name="ServiceModelTraceListener"/>
</listeners>
</source>
<source name="System.ServiceModel" switchValue="Verbose,ActivityTracing" >
<listeners>
<add name="ServiceModelTraceListener"/>
</listeners>
</source>
<source name="System.Runtime.Serialization" switchValue="Verbose,ActivityTracing">
<listeners>
<add name="ServiceModelTraceListener"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add initializeData="App_tracelog.svclog"
type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
name="ServiceModelTraceListener" traceOutputOptions="Timestamp"/>
</sharedListeners>
</system.diagnostics>
Q: How do I transfer very large blobs in WCF?
A: Follow these instructions. Without special support, WCF buffers the entire argument in memory before calling the method. This is called chunking or buffering. This method is used when large files are being transferred and consequently the file data should not be entirely buffered in memory before calling the API.
One way to do this is to declare a function to transfer files in chunks of 32k or less as the type byte[], then manually call it repeatedly until the file transfer is complete. This supports sessions and works, but it requires doing everything manually, including error handling, whereas MTOM does all this automatically at client and server.
SOAP has specific support to stream large messages by using MTOM to stream the file to the server. Note that MTOM can be used in what is called buffered mode, the default SOAP transport across http, but this requires the entire message to be buffered in memory. These instructions will detail using MTOM in streamed mode only in a WCF C# service and client.
SERVER
0. Create a new service. Change the binding to basicHttp. To guarantee this works, no interface on this service can use wsHttpBinding or it will fail with SOAP errors stating message body is empty or a content type mismatch.
1. Create a new interface for streaming file transfers. The OperationContract(s) can have at most 1 input and 1 output parameter. Practically, this means the method will take a single struct argument. Also, the struct can contain only ONE Stream.
2. Decorate the struct argument as follows:
[MessageContract()]
public class FileTransferRequest
{
[MessageHeader(MustUnderstand = true)]
public string FileName;
[MessageBodyMember(Order = 1)]
public System.IO.Stream Data;
}
3. For Upload operations, it is a good idea, but not required, to set the OneWay attribute on the operation contract for Upload, as in:
[OperationContract(IsOneWay=true)]
void UploadFileStreamed( UploadFileStreamArgs arguments );
4. Create a new service binding to use Streaming for the endpoint in Web.Config under system.serviceModel\bindings\basicHttpBinding:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="MtomHttpStreaming" messageEncoding="Mtom" transferMode="StreamedResponse" maxBufferSize="65536" maxReceivedMessageSize="67108864">
<security mode="None">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="HttpBinding_MTOM" contract="service.IFileTransferService" />
Here, MaxReceivedMessageSize is the maximum size of the file you can receive (add 200k for message overhead) and maxbufferSize is the size of the Stream buffer to use when receiving the data.
5. Expose the new interface on a new local endpoint address, since it uses a different binding:
<endpoint address="fileTransfer" binding="basicHttpBinding" contract="WcfService2.IFileTransfer" bindingConfiguration="MtomHttpStreaming">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
6. In the method implementing the operation, your stream will be updated each time data arrives. Use it's Read call to retrieve the data blocks, as in:
FileStream fs = null;
try
{
fs = File.Create(filePath);
byte[] buffer = new byte[1024];
int read = 0;
while ((read = arguments.Data.Read(buffer, 0, buffer.Length)) != 0)
{
fs.Write(buffer, 0, read);
}
}
finally
{
if (fs != null)
{
fs.Close();
fs.Dispose();
}
if (arguments.Data != null)
{
arguments.Data.Close();
arguments.Data.Dispose();
}
}
7. Set the service object's Instance Context Mode to PerCall or Concurrency to Multiple, unless this is a singleton interface that will only be used by one client at a time. Streaming doesn't quite work with sessions, even though the underlying config may have them enabled. http://msdn.microsoft.com/en-us/library/ms733742.aspx.
8. Do not use message-level security, use transport level security w/ auth if needed. Alternatively, use mixed-mode combining WS-Security claims with transport security.
9. The non-Data stream arguments (SOAP headers) must not exceed MaxBufferSize as these are always sent buffered.
10. Sessionful service contracts do not compose with transport streaming as the underlying transport class is changed from IDuplexSessionChannel to IRequestChannel and IReplyChannel.
11. Increase the IIS max Request Size to match your maxReceivedMessageSize. It defaults to 4MB and will override the service setting.
12. Correct the http runtime maxrequestLength so it matches the buffer sized used to transfer the stream. For the ASP.NET Development Server, add the following to the Web.Config <configuration> element:
<system.web>
<httpRuntime maxRequestLength="65536"/>
</system.web>
CLIENT
1. Set the transfer mode to Streamed at the client as well, as this is not described in the WSDL. In C#, this is most easilly done in the App.config by setting Mtom/Streamed in the configuration for the binding, as in the following example:
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IFileTransferService"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Mtom" transferMode="StreamedResponse">
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8100/FileTransfer" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IFileTransferService"
contract="IFileTransferService" name="BasicHttpBinding_IFileTransferService" />
</client>
2. To read a file into a Stream, call new FileStream(filename, FileMode.Open)
References:
http://weblogs.asp.net/cibrax/archive/2007/08/29/sending-attachments-with-wcf.aspx
http://blogs.msdn.com/b/drnick/archive/2006/03/31/565558.aspx
Using in ASP service
http://mark-csharp.blogspot.com/2009/01/wcf-file-transfer-streaming-chunking.html
MSDN article .NET Framework 3.5\Windows Communication Framework\WCF Feature Details\Data Transfer and Serialization in Windows Communication Framework\Large Data And Streaming
Q: I'm calling a WCF service using streaming and it is failing on my client with a ProtocolException. On the server, I get an Xml exception "The body of the message cannot be read because it is empty."
A: Set the transferMode in the binding type to StreamedResponse. This happens when the binding type is set to Streamed instead.
Q: Are exceptions thrown by WCF services marshalled to the client?
A: Yes, even without WSDL FaultContracts. A default WCF service will continue to run after throwing an exception.
Q: How do I use HTTPS with BasicHttpBinding?
A: Create a binding with:
<security mode="Transport">
<transport clientCredential="None" proxyCredentialType="None" realm=""/?
</security>
This is placed within the binding element defining the binding configuration, which is located in configuration\system.serviceModel\bindings\basicHttpBinding\<binding name=YOUR BINDING CONFIG'S NAME. See http://msdn.microsoft.com/en-us/library/ms752256.aspx.
Q: In my WCF project, Web.Config is not built. Why?
A: WCF projects do not build Web.Config normally. It is built (to obj/Debug or Release) when you use Build Deployment Package or Publish/Package action, however.
Q: How do I configure a WCF project to use https (security mode="Transport") in Release and http (security mode="None") in debug?
A: For example, say you want to set the following binding so it uses HTTPS, but in debug uses HTTP so it can be easilly debugged:
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IFileTransfer"
1. Edit the Web.Config and set the the security mode="Transport" for the bindings where you want it to be that way in release mode.
2. Edit the Web.Debug.Config and add the following inside the configuration element:
<system.serviceModel>
<!-- Define MTOM streamed binding -->
<bindings>
<basicHttpBinding>
<binding name="MtomHttpStreaming">
<!-- Use http for debug builds for convenience since the ASP.NET Dev Server does not support https-->
<security mode="None" xdt:Transform="Replace">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
3. This will show up when published or when building a deployment package.
4. NOTE that if the Transport mode does not match from client to server, the client proxy may noy throw an exception! From client->server config, if you use Transport->None, the client will throw. HOWEVER, if you use None->Transport, the client will silently fail without an exception and the server will never see the call.
Q: My WCF client's method call failed. The server threw a Catastrophic Exception error.
A: There is a WSDL mismatch. Interface changes that cause no logic change to the structure of the interface can still cause breaking changes. For example, renaming a data type used in the WSDL without changing it's structure can result in this. In this case, the server's event log will have an error like this one:
System.IO.IOException: An exception has been thrown when reading the stream. ---&gt; System.Xml.XmlException: Element 'UploadFileStreamedArgs' with namespace name 'http://tempuri.org/' was not found
Q: When I call a WCF method using Streaming MTOM, my client returns before the server has even processed the request sometimes. Why?
A: The method is marked OneWay, so the client proxy can return as soon as the message has been successfully sent to the server. No out parameters or status are returned.
Q: My WCF streamed interface client gets a strange communication exception when trying to send a file. The call works fine with small files. maxReceivedBufferSize is set high enough on client and server. The server log reports the exception "System.Web.HttpException: Maximum request length exceeded.", which makes no sense. How do I fix this? The client exception is shown below:
An error occurred while receiving the HTTP response to http://localhost:49509/Service1.svc/fileTransfer. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.
A: The service host is overriding the maxReceivedBufferSize to 4MB. To increase this in IIS, add the following to Web.config
For the ASP Net Development Server:
<system.web>
<httpRuntime maxRequestLength="65536"/>
</system.web>
For IIS, you may need to use this instead.
<system.serviceModel>
<!-- maxRequestLength (in KB) max size: 2048MB -->
<httpRuntime maxRequestLength="65536"/>
</system.serviceModel>
See http://kjellsj.blogspot.com/2007/02/wcf-streaming-upload-files-over-http.html for more information.
Q: My WCF streamed interface clients gets the following error:
"The remote server returned an unexpected response: (400) Bad Request."
A: Review the server log (see previous entries on how to enable debug logging if needed). If the server log reports "The maximum message size quota for incoming messages (<some number>) has been exceeded", the client is attempting to send a file bigger than the maxReceivedMessageSize setting for the service. For Streamed interfaces, this is the maximum size of the file sent + all other arguments. Increase this on both the client and server. If the service is hosted in IIS and you need to transfer files 4MB or larger, you must also increase IIS's maxReceivedMessageSize as it caps this at 4MB for security reasons.
Q: How do I delete the debug/trace log for a WCF service? I am debugging a WCF service run using the Visual Studio dev server.
A: Right clik the server process icon in the try and select stop, then the file can be deleted.
Q: I can't get a WCF streaming download API to work. Everything is written and configured correctly. I am using the ASP.NET Development server included with Visual Studio. What is the problem?
A: The ASP.NET Development Server does not fully support streaming. Use IIS or host the service in a console session. Testing has shown it can be made to work if you use StreamedResponse only. References:
http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/01bab577-2626-4cad-9a1f-601daeb42727/
http://bartwullems.blogspot.com/2010/02/wcf-streaming-is-not-supported-in.html.
Q: When I run my WCF service, I get an error saying I can't debug.
A: There are several possible causes, but the most common cause is an incomplete ASP.NET installation. To resolve this:
1. Open a command prompt
2. Change to c:\windows\Microsoft.Net\Framework\<highest number>
3. Run aspnet_regiis -i.
There are two types of WCF services: native and ASP.NET. Even native services use a very small amount of ASP.NET functionality. One common cause of this is reinstalling IIS: ASP.NET must be installed after IIS for it to install correctly.
Q: I changed the namespace or name of my class of my WCF server, and now I can't access it. Trace log shows ConstructServiceHost failed.
A: Change the Service= class name in the SVC file. This is set by Visual Studio when you create the class and must be changed manually if it is renamed or if it's namespace changes.
Q: How is the configuration of a WCF service determined when run in IIS?
A: IIS processes each configuration block or file starting with the IIS root and working towards your application/service's root. Nested Web.config files add to and override values in previous ones - the bottom of the hierarchy takes precedence over files higher in the hierarchy.
Q: My WCF service can't handle more than 10 clients. Why?
A: This is the default maximum number of sessions. Increase the max sessions via XML like this in the Web.config:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceThrottling maxConcurrentSessions="100" maxConcurrentInstances="100">
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
If this is a sessionless service, adjust maxConcurrentCalls instead. This defaults to 16.
Q: How do I get a dump of a hung WCF service?
A: Use adplus -hang -pn w3wp.exe. See http://blogs.msdn.com/b/tess/archive/2009/01/09/net-hang-my-application-hangs-after-i-called-my-wcf-service-a-couple-of-times.aspx for more information.
Q: After several client calls, my WCF service hangs and accesses to it return timeout errors like this:
System.Net.WebException: The operation has timed out
A: Modify the client to call close after it is done. They are not calling Close, so the WCF session never expires and it hits it's session max and can never proceed.
Q: How do I set the OperationTimeout for a WCF service contract?
A: Set the OperationTimeout property on the InnerChannel for the client's proxy object, as in:
transferClient.InnerChannel.OperationTimeout = new TimeSpan(0, 0, 60*5);
Since client proxies are auto-generated partial classes, this can be done via an additional method in a separate file so it is not wiped out when re-gen'd. This cannot be set declaratively (in the app.config) as of VS2010, in the WSDL. Server-side, default timesouts for all operations can be set via web.config's <system.web><httpRuntime executionTimeout>. Speculation: servers can access information on the current request via OperationContext class/object, and Channel.OperationTimeout exists here. For more information, see http://final-proj.blogspot.com/2009/09/wcf-timeouts.html.
Q: What exactly are the WCF timeout values for?
A:
Client side:
* SendTimeout is used to initialize the OperationTimeout, which governs the whole interaction for sending a message (including receiving a reply message in a request-reply case). This timeout also applies when sending reply messages from a CallbackContract method.
* OpenTimeout and CloseTimeout are used when opening and closing channels (when no explicit timeout value is passed).
* ReceiveTimeout is not used.
Server side:
* Send, Open, and Close Timeout same as on client (for Callbacks).
* ReceiveTimeout is used by ServiceFramework layer to initialize the session-idle timeout.
There are other timeout values for service operation as well - these are the primary ones of interest. See http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/84551e45-19a2-4d0d-bcc0-516a4041943d/.
Q: How do I create an application configuration value in a WCF service and read it in?
A: 1. To declare the value, edit the Web.config configuratoin\appSettings section and add keys to declare the settings with their default values. For example:
<appSettings>
<add key="LogFlags" value=""/>
</appSettings>
2. In your WCF service, call System.Configuration.ConfigurationManager.AppSettings["LogFlags"] to get the value. Get will return null if the setting is not found. If the service is hosted in IIS, the config is read via the IIS Web.config mechanism. Otherwise, it is read from App.Config.
Q: In a WCF service, how do I read the Web.Config's System.ServiceModel configuration at runtime?
A: Use System.ServiceModel.Configuration.ServiceModelSectionGroup.GetSectionGroup().. For example:
var config = System.Configuration.ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
var serviceModelConfig = config.GetSectionGroup("system.serviceModel");
System.Web.Configuration.SystemWebSectionGroup webConfiguration = (System.Web.Configuration.SystemWebSectionGroup) config.GetSectionGroup("system.web");
Q: How do I change WCF configuration at runtime?
A: Change the appSettings config, save the changes, then ask the ConfigurationManager to reload the section. The last step is unobvious and necessary. For example:
Configuration config = ConfigurationManager.OpenExeConfiguration(Assembly.GetEntryAssembly().Location);
AppSettingsSection appSettings = (AppSettingsSection) config.GetSection("appSettings");
appSettings.Settings.Add("name", "bar");
config.Save();
ConfigurationManager.RefreshSection("appSettings");
Note that RefreshSection works only on a single group, not a section group, so you'll typically have to refresh several sections, as in:
ConfigurationManager.RefreshSection("system.serviceModel/behaviors");
ConfigurationManager.RefreshSection("system.serviceModel/bindings");
ConfigurationManager.RefreshSection("system.serviceModel/client");
ConfigurationManager.RefreshSection("system.serviceModel/services");
Q: How do I write custom messages to the WCF trace log?
A: UNTESTED: Define a trace source in WebConfig, then instantiate it and use it. See http://social.msdn.microsoft.com/forums/en-US/wcf/thread/33c106b4-8f86-4e0f-ab2f-b3f1b289b926/
Q: How do I increase the IIS 5.1 (Windows XP) connection limit?
A: Open a command prompt and enter the following:
cd \inetpub\adminscripts
cscript adsutil.vbs set w3svc/MaxConnections <NewConnectionLimit>
iisreset
The default connection limit is 10. The maximum allowed is 40.
Q: What happens to a WCF service that throws an exception?
A: It depends on the type of exception thrown. If anything but a FaultException is thrown, the service instance is disposed and net result depends on the instance mode of the service:
Per-Call: Proxy throws a FaultException on client, server channel state->faulted, proxy no longer usable for any service.
Per-Session: Same as per-call + session is terminated
Singleton: Proxy/client behavior as above, but service is not disposed
If a FaultException is thrown, it is wrapped and sent to the client as a SOAP Fault (FaultException exception) and the service instance continues to run. Note that if a FaultException<T> exists for the type of exception thrown, it is marshalled to the client as this. Otherwise, it is wrapped in the non-template FaultException class. For more information, see http://blogs.msdn.com/b/pedram/archive/2008/01/25/wcf-error-handling-and-some-best-practices.aspx.
Q: Are there limitations on using Stream arguments in WCF?
A: Yes. For incoming messages, the data type must be exactly Stream. No derrived class can be used. See Specify Data Transfer in Service Contracts.
Q: My WCF service isn't accessible. How do I debug this?
A: First, verify that it fails during the constructor. Open a web browse and enter the URL to the SVC file for the service. If you get a server error mentioning an exception and a line of code in your constructor, it is a constructor error.
To debug the constructor, do the following:
1. Set the Server project to be the Startup Project
2. Set a breakpoint in the constructor
3. Highlight the SVC file for this service and select Debug|Start Debugging
If you fail to highlight the correct file in step 3, Visual Studio will appear to be debugging but will never break at the breakpoint. This is because no requests were sent to the SVC file, therefore the service was never activated, and so the code was never run. Either ensure the SVC file is highlighted or open a web browser and enter the URL to the service's SVC file manually. A common mistake causing this is to set a breakpoint in the service code and then hit <F5>. The focus is on the CS file backing the SVC, not the SVC, so the WCF test client is never run and consequently the service is never instantiated.
Q: While debugging my WCF service, Visual Studio suddennly jumped to Overapped.cs in _IOCompletionCallback.PerformIOCompletionCallback. The call stack now shows mscorlib.dll!System.Threading._IOCompletionCallback.PerformIOCompletionCallback and then some unmanaged calls. What is happenning?
A: Your code threw an unhandled exception. If you are debugging your service constructor, WCF will attempt to automatically restart it since it failed during construction, which can make following this confusing. Don't continue to trace after arriving in PerformIOCompletionCallback or the service will restart.
Q: What are the downsides of leaving debug="true" in the web.config of a web service?
A: Primarilly, some timeotus don't apply - things never timeout - and caching is disabled.
Q: When I try to debug my WCF service, I get this error and can't access it. How do I fix this?
The current identity does not have write access to Temporary ASP.NET Files
A: There are several possible causes. Most likely it is due to a NET Framework mismatch. Your app/service is written using NET 3.5, but IIS only has settings for NET 2 and NET 4. Visual Studio may have prompted you to downgrade the app to NET 2, causing this. To resolve it, open IIS Manager, find the web application, and change it's ASP.NET configuration to 4.0. Click OK to the restart, then restart IIS as well and the problem should be resolved.
Q: My WCF service threw an exception, killing the session, but the session didn't dispose immediately. This is not a singleton service. How do I fix this?
A: The timeout hasn't expired yet. The default is 10 minutes. There are two ways to address this:
1. Reduce both the receiveTimeout and inactivityTimeout on the binding to force abandoned sessions to be cleaned up quicker.
2. Update the client so Close is automatically if the service throws an exception (for example, in dispose). Note that SOAP services can intentionally return an exception via the SOAP Fault mechanism, wrapped in C# as a SoapFault. Depending on the declarations in the service contract, the client may need to ignore some of these as the service session is not destroyed in this case.
Q: I'm trying to return an Exception as an out parameter in my WCF service, but my client breaks with "The underlying connection was closed: The connection was closed unexpectedly." The service didn't do so and it's code ran fine. What is happenning?
A: This is a deserializing problem on the client. The WCF proxy excepts to demarshal an Exception, but the service is sending a subclass of exception. The types don't match, so the demarshaller fails on the client in an unexpected way. To confirm, check the stack trace of the exception on the client. It should report a server stack trace with System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException at the top, and an inner exception with System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage. This confirms the exception occured while the client was processing the SOAP response message.
To resolve this, decorate the DataContract or ServiceContract with the KnownType attribute so the deserializer will know how to demarshal this. Note that for the Exception class, this is not recommended for several reasons: it is impossible to know all Exception types, they may not be serializable, and the client may not have the backing assembly to instantiate them.
Q: I can no longer debug my WCF service application using the local IIS web server. I am always stuck at "Unable to Start Debugging...".
A: There are many causes. These steps solved it once when it was otherwise insoluable:
0. Delete the .user and Publish.xml files for this project
1. Delete the virtual directory in IIS Manager and restart IIS Manager.
2. In your VS2010 project, configure Web|Servers to use a Local IIS Web Server and make sure the path is correct.
3. Select File|Save All and ensure the file saves.
4. Click Create Virtual Directory
5. Try running the service. It will probably fail agian.
6. Right click the project and select Publish. Use Web Deploy with the same service URL as in the project's Web|Servers, Set Site=Default Web Site, check both boxes, and click Publish.
7. At a command prompt, change to your NET Framework 4 directory and run aspnet_regiis -i.
8. In IIS Manager, ensure this application is set to use the same NET Framework 4.
9. The application should now be able to run.
NOTE. If this doesn't work, you can also try:
1. Run c:\windows\Microsoft.Net\Framework\v3.0\Windows Communication Foundation\ServiceModelReg -i
2. Try to connect to your web service at http://localhost directly, the publish may have malfunctioned, targetting the root instead of your specified subdirectory.
Q: My WCF service doesn't work. It's stuck with the error "The type '...' provided as the Service attribute value in the ServiceHost directive could not be found."
A: Most likely, you created a new build configuration that places it's outputs in a different directory. Switch back to the original build configuration.
To debug this:
1. Run the Fusion log viewer (ProgramFilesDir\Microsoft SDKs\Windows\v7.0A\bin\FUSLOGVW.exe).
2. Click Settings, then Log in Exception text.
3. Restart IIS or your dev server
4. Create an aspx file named futz.aspx in your project directory root (same directory where SVC file is). Replace the fully qualified class name and it's hosting assembly file node name with the appropriate values.
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Runtime.Remoting" %>
<%
ObjectHandle oh = Activator.CreateInstance("Cybernet.Vsil.Repository.Server.RepositoryService", "RepositoryServer.dll");
Response.Write(oh.Unwrap().ToString() + " loaded OK");
%>
5. Start a web browser and browse to futz.aspx in the root of your web app. This will produce output with LOG trace values. For example, this sample log shows the problem was the different output directory used by the x86 build configuration of this project.
=== Pre-bind state information ===
LOG: User = RD-NUMBAT\dluxford
LOG: DisplayName = Cybernet.Vsil.Repository.Server.RepositoryService
(Partial)
LOG: Appbase = file:///D:/SourceTrees/Repo Interface WCF/VSIL/Repo/RepositoryServer/
LOG: Initial PrivatePath = D:\SourceTrees\Repo Interface WCF\VSIL\Repo\RepositoryServer\bin
Calling assembly : App_Web_xiew0wgh, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: D:\SourceTrees\Repo Interface WCF\VSIL\Repo\RepositoryServer\web.config
LOG: Using machine configuration file from C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/Temporary ASP.NET Files/root/ebef225d/3f6d24ff/Cybernet.Vsil.Repository.Server.RepositoryService.DLL.
LOG: Attempting download of new URL file:///C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/Temporary ASP.NET Files/root/ebef225d/3f6d24ff/Cybernet.Vsil.Repository.Server.RepositoryService/Cybernet.Vsil.Repository.Server.RepositoryService.DLL.
LOG: Attempting download of new URL file:///D:/SourceTrees/Repo Interface WCF/VSIL/Repo/RepositoryServer/bin/Cybernet.Vsil.Repository.Server.RepositoryService.DLL.
LOG: Attempting download of new URL file:///D:/SourceTrees/Repo Interface WCF/VSIL/Repo/RepositoryServer/bin/Cybernet.Vsil.Repository.Server.RepositoryService/Cybernet.Vsil.Repository.Server.RepositoryService.DLL.
LOG: Attempting download of new URL file:///C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/Temporary ASP.NET Files/root/ebef225d/3f6d24ff/Cybernet.Vsil.Repository.Server.RepositoryService.EXE.
LOG: Attempting download of new URL file:///C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/Temporary ASP.NET Files/root/ebef225d/3f6d24ff/Cybernet.Vsil.Repository.Server.RepositoryService/Cybernet.Vsil.Repository.Server.RepositoryService.EXE.
LOG: Attempting download of new URL file:///D:/SourceTrees/Repo Interface WCF/VSIL/Repo/RepositoryServer/bin/Cybernet.Vsil.Repository.Server.RepositoryService.EXE.
LOG: Attempting download of new URL file:///D:/SourceTrees/Repo Interface WCF/VSIL/Repo/RepositoryServer/bin/Cybernet.Vsil.Repository.Server.RepositoryService/Cybernet.Vsil.Repository.Server.RepositoryService.EXE.
Q: In WCF, How do I use Windows authentication with a wsHttpBinding and https?
A: See http://stackoverflow.com/questions/427954/wcf-sessions-with-https.
Q: How do I use Visual Studio's svcutil with WSDL that requires a login?
A: Svcutil does not support logins. To accomplish this, download the WSDL manually by entering the URL to the WSLD in a web brower, saving it to disk, then processing the saved file with svcutil.
Q: My WCF client of a Java Axis web service gets invalid return values calling an operation contract that returns an array of a basic type, like int, string, etc., but operations that return arrays of custom types are fine.
A: This is a WCF issue. Axis returns a proper SOAP response that WCF does not understand. To fix this, modify the Axis server's server-config.wsdd, setting sendMultiRefs=false. This can be done via the following command line:
java -cp %AXISCLASSPATH% org.apache.axis.client.AdminClient server-config.wsdl
The Axis server is returning the value of each array item using a pointer to data provided elsewhere in the SOAP response instead of simply listing the data directly in the location for that array element in the response, as would normally be done. WCF doesn't understand this. For example, given an operation contract like this:
int[] doSomething( String someParameter )
Axis will return the following SOAP response, which WCF cannot parse:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv=http://schemas.xmlsoap.org/soap/envelope/>
<soapenv:Body>
<doSomethingResponse>
<doSomethingReturn>
<doSomethingReturn href="#id0"/>
<doSomethingReturn href="#id1"/>
<doSomethingReturn href="#id2"/>
<doSomethingReturn href="#id3"/>
<doSomethingReturn href="#id4"/>
</doSomethingReturn>
</doSomethingResponse>
<multiRef id="id4">5</multiRef>
<multiRef id="id3">4</multiRef>
<multiRef id="id2">3</multiRef>
<multiRef id="id1">2</multiRef>
<multiRef id="id0">1</multiRef>
</soapenv:Body>
</soapenv:Envelope>
Q: My WCF service is not behaving as expected. Multiple threads using the same proxy appear to be serialized when calling the server. How do I fix this?
A: Set the service's ConcurrencyMode to Multiple. Each time a proxy calls the server, the server locks that session. Unless the service is marked ConcurrencyMode=Multiple,
re-entrant calls are serialized. See http://blogs.msdn.com/b/rickrain/archive/2009/06/17/wcf-instancing-concurrency-and-throttling-part-2.aspx.
Q: When I run my test application is Visual Studio, it runs something else with a similar EXE name, but postfixed with ".vshost.exe". What is this?
A: The Visual Studio debugger launches C# EXEs using a stub to reduce the time it takes for the C# debugger to attach to the process. This feature has existed since VS 2005. For more information, see http://msdn.microsoft.com/en-us/library/ms185331%28VS.80%29.aspx.
Q: What is WSDualHttpBinding for? Can't WSHttpBinding return information to the client?
A: This binding is only necessary when the service contract requires the client to provide a callback to the server.
Q: How do I set the OperationTimeout value?
A: As of WCF 3, this must be set in code. Server-side, use OperationContext.Current.OperationTimeout. Client-side, cast the proxy's .Channle member to an IContextChannel and set it's OperationTimeout member, as in:
((IContextChannel)base.Channel).OperationTimeout = timeout;
Q: My WCF service stopped working. I get an error like this:
Server Error in '/RepositoryServer' Application.
Configuration binding extension 'system.serviceModel/bindings/PrimaryServiceAPIBinding' could not be found. Verify that this binding extension is properly registered in system.serviceModel/extensions/bindingExtensions and that it is spelled correctly.
A: WCF cannot locate a binding that connects the service contract to the protocol to use to expose it on the web. The error is in the Web.Config services section in the service element for this service. The binding= attribute is specifying an unsupported value. Binding should be set equal to a standard WCF binding method. In this case, the author created a <bindings> element to customize this binding and specified that name here instead. In WCF, you must specify the type of binding for binding= and specify the configuration for that binding via a companion bindingConfiguration attribute on the same service element.
Q: I have a WCF service running on IIS 6 (Server 2003) using Winodws authentication only, but I get a NotSupportedException.
A: IIS 6 does not support Windows authentication on basicHttpBinding. Instead, set security mode to Ntlm and allow anonymous authentication in the IIS site settings. See http://anehir.blogspot.com/2010/02/wcf-basichttpbinding-and-windows.html.
Q: Deserialization of some double values using the DataContractSerializer is slow when run under a debugger, but otherwise is fast. Why?
A: The DataContractSerializer takes a long time to deserialize double.NaN (not a number). If you use these frequently, change the serialization data model so NaN is not deserialized/deserialized as little as possible. For example, change the field from a double to double? and represent NaN as a null. See this link.