En utilisant l'objet sur mesure FaultContract contenant causes System.Exception « Ajouter un service de référence » à l'échec

StackOverflow https://stackoverflow.com/questions/4656257

Question

Je viens de remarquer quelque chose de particulier. J'ai un service d'actions interne qui est publié par basicHttpBinding, et un CustomBinding (http + binaire) pour lesquels des métadonnées est activée. J'ai aussi inclus un point de terminaison pour http MEX. Nous utilisons Visual Studio 2008 et VB.NET

Tout récemment nous avons remarqué que nous ne pouvions pas ajouter avec succès une référence de service à ce service dans nos autres projets. Tout ce qu'il générerait était la première exception personnalisée, nous avons inclus dans un FaultContract (en fait, il n'y avait que 1 type). si je rajouterais une simple référence web il fonctionne correctement aussi bien. En outre, le WcfClient.exe n'a eu aucun problème ni dans le chargement des services. Juste référence de service VS.NET add ne marcherait pas.

Dans le service d'exception cette hérite de l'exception et est marquée comme sérialisable. Que vous est tout est censé faire, non?

En tout cas, cela me avait déconcerté. Si je retire le FaultContract pour cette exception tout personnalisé fonctionne très bien. Je peux ajouter une référence de service, pas de problème. Mais est-il un moyen que je peux encore avoir mes exceptions personnalisées? Est-ce un problème connu?

Était-ce utile?

La solution

je suis tombé sur moi-même aujourd'hui. La solution était d'utiliser un objet non héritant d'exception dans le FaultContract. Si vous regardez la documentation MSDN pour FaultException et FaultContract vous verrez que les exemples officiels utilisent des classes simples ( avec des attributs DataContact) plutôt que des classes s'étendant exception pour FaultException.Detail. Je ne sais pas pourquoi le fait exception Ajouter un service de référence à l'échec, mais je soupçonne que cela a à voir avec la sérialisation ou de récupérer les informations de type pour les exceptions personnalisées. J'ai inclus avant et après les mises en œuvre par exemple pour démontrer l'approche de travail.

Avant (n'a pas fonctionné):

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    [FaultContract(typeof(MyException))]
    MyResults MyServiceOperation(string myParameter);
}

[Serializable]
public class MyException : Exception
{
    public string CustomData { get; set; }
}

[ErrorHandlerBehavior(typeof(MyErrorHandler))]
public class MyService : IMyService
{
    public MyResults MyServiceOperation(string myParameter)
    {
        ...
        throw new MyModelException { CustomData = "42" };
        ...
    }
}

public class MyErrorHandler : IErrorHandler
{
    public bool HandleError(Exception error) { return false; }

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        try { throw error; }
        catch (MyModelException ex)
        {
            var faultEx = new FaultException<MyException>(new MyException { CustomData = ex.CustomData });
            fault = Message.CreateMessage(version, faultEx.CreateMessageFault(), faultEx.Action);
        }
        catch { /* Supress all others */ }
    }
}

Après (travaillé):

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    [FaultContract(typeof(MyFault))]
    MyResults MyServiceOperation(string myParameter);
}

[DataContract]
public class MyFault
{
    [DataMember]
    public string CustomData { get; set; }
}

[ErrorHandlerBehavior(typeof(MyErrorHandler))]
public class MyService : IMyService
{
    public MyResults MyServiceOperation(string myParameter)
    {
        ...
        throw new MyModelException { CustomData = "42" };
        ...
    }
}

public class MyErrorHandler : IErrorHandler
{
    public bool HandleError(Exception error) { return false; }

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        try { throw error; }
        catch (MyModelException ex)
        {
            var faultEx = new FaultException<MyFault>(new MyFault { CustomData = ex.CustomData });
            fault = Message.CreateMessage(version, faultEx.CreateMessageFault(), faultEx.Action);
        }
        catch { /* Supress all others */ }
    }
}

Source: Max Strini pour l'utilisation de son code et l'aide à trouver la solution à ce problème <. / p>

Autres conseils

Je trouve l'article suivant sur la façon de créer un contrat de défaut en utilisant hérité de System.Exception ont objecté: http://blog.clauskonrad.net/2008/06/wcf-and-custom-exceptions.html

Cependant, il ne fonctionne pas pour moi. Je soupçonne que la raison pour laquelle il n'a pas fonctionné pour moi est que j'utilise un liant BasicHttp et non un .NET .NET liant.

Je l'ai également frappé cette question. Je fini par utiliser svcutil.exe pour générer le proxy qui ne semble pas subir le même problème.

J'ai eu le même problème et résolu en générant le proxy à l'aide Svcutil.exe. J'ai eu le recommande la façon dont MSDN configuration de défaut personnalisé exactement, mais n'a pas été compris « référence de service ajouter » le contrat de défaut dans la procuration. Ensuite, je l'svcutil et cela a fonctionné comme par magie:)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top