Wout Ware Blog

My external memory

Use .svc extension in address when hosting using ASP.NET server (e.g. in VS "WCF Service Application" project)

clock December 26, 2009 08:49 by author Administrator

Today I was playing with WCF and for a change I created a "WCF Service Application" project to act as a WCF service. I removed the default created stuff and added my own service class. I quickly whipped up a client project, and fired up the debugger:

+        [System.ServiceModel.CommunicationException]    {"An error occurred while receiving the HTTP response to http://localhost:8083/Service. 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."}    System.ServiceModel.CommunicationException

Argh! Why me? A couple of hours, a lot of cursing and trial and erroring later I figured out that the ASP.NET development server must be able to recognize the .svc extension. So the client configuration must refer to the actual .svc file:


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <client>
            <endpoint address="http://localhost:8083/Service.svc" binding="wsHttpBinding" bindingConfiguration="" contract="WcfData.IService"
                name="MyService">
                <identity>
                    <dns value="localhost" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>

 

The service's config may have the address attribute empty or the explicit reference to the .svc file, but I had the string "http://localhost:8083/Service" initially, which works ok with anything else but ASP.NET hosts. Hosting in a Console app, or windows service using ServiceHost works just fine without .svc extension.



Implementing IErrorHandler and working around SerializationException.

clock December 17, 2009 06:40 by author Administrator

EDIT Nov 25, 2009: note that the problem described in this post below only happens in the VS debugger, under some circumstances.

Today I was attempting to implement a custom IErrorHandler to wrap Exception instances into a FaultException<T> instance, so they can be properly turned into a soap fault by WCF. Seemed easy at first, but there was a nasty fly in the ointment. The original code in the service would work fine, which looked like this:

throw new FaultException<Exception>(new Exception("test"));


When I would just throw a new Exception("test") in the service, and wrap it in the error handler, then it wouldn't work. The service code now looks like this:

throw new Exception("test");


The error handler code looks like this:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Web;

namespace Test {
    public class ErrorHandler : IErrorHandler {
        #region IErrorHandler Members

        public bool HandleError(Exception error) {
            return false;
        }

        public void ProvideFault(Exception error, MessageVersion version, ref Message fault) {
            if (error is FaultException) {
                return;
            }

            Type faultExceptionType = typeof(FaultException<>).MakeGenericType(error.GetType());
            FaultException faultException = (FaultException)Activator.CreateInstance(faultExceptionType, error);
            MessageFault messageFault = faultException.CreateMessageFault();
            fault = Message.CreateMessage(
                version,
                messageFault,
                faultException.Action
            );
        }

        #endregion
    }
}


Now the exception doesn't get turned into a soap fault anymore, instead we're getting a SerializationException hidden away quite nicely. What's going on???

After a whole day of digging around, googling, debugging and trying hacks I did manage to find out what's going on and also find a workaround. Googling around first made me find part of the problem. The normal DataContractSerializer can't handle the Exception.Data property when it has a value. And when the exception arrives at the error handler, it does have a Data value. This isn't the complete story though, the field behind the Data property is _data. Whenever Data gets evaluated, it will set _data to a value, and then the serialization breaks. The next piece in the puzzle is this: initially the _data field of an Exception is null, but doing a throw/catch causes the _data to be initialized (Edit Nov 25, 2009: only when the debugger stops when e.g. the exception is thrown, when the debugger doesn't stop, _data remains null and there is no problem). In other words: a throw/catch will break serialization! Note that this all is a debugger side effect, so once you've figured out it's a debugger side effect, you can just make sure you don't break on exceptions in the service.

There's also a workaround. The _data field can be set to null in the error handler using reflection. Modify the ProvideFault method like this and the serialization will work again:

        public void ProvideFault(Exception error, MessageVersion version, ref Message fault) {
            if (error is FaultException) {
                return;
            }

            // This hack sets the _data field to null again.
            FieldInfo fieldInfo = typeof(Exception).GetField("_data", BindingFlags.Instance | BindingFlags.NonPublic);
            fieldInfo.SetValue(error, null);

            Type faultExceptionType = typeof(FaultException<>).MakeGenericType(error.GetType());
            FaultException faultException = (FaultException)Activator.CreateInstance(faultExceptionType, error);
            MessageFault messageFault = faultException.CreateMessageFault();
            fault = Message.CreateMessage(
                version,
                messageFault,
                faultException.Action
            );
        }

 



About the author

Wout is trying to keep up with the latest .NET developments with minimal success!

Page List

    Sign in