web-dev-qa-db-fra.com

ProtocolException Unhandled / (405) Méthode non autorisée avec WCF; Les liaisons et les noeuds finaux semblent cependant corrects

J'apprends juste à utiliser WCF et j'essaie d'écrire un petit programme HelloWorld à partir de zéro (à la fois côté hôte et côté client). J'ai reçu un ProtocolException Unhandled Chaque fois que mon client essaie d'utiliser le service, et je n'arrive pas à comprendre pourquoi. J'héberge le service à l'aide d'IIS.

En ce qui concerne la façon dont je fais les choses: je fais de mon mieux pour séparer le client, le proxy, l'hôte, le service et le contrat, comme détaillé dans ce vidéo et comme indiqué dans ce article . Fondamentalement, j'ai différents projets dans la solution pour chacun d'entre eux.

Voici quelques fichiers différents montrant de quoi je parle:

Un service

namespace HelloWorld
{
  public class HelloWorldService : IHelloWorldService
  {
    public String GetMessage(String name)
    {
        return "Hello World from " + name + "!";
    }
  }
}

Contrat

namespace HelloWorld
{
  [ServiceContract]
  public interface IHelloWorldService
  {
      [OperationContract]
      String GetMessage(String name);
  }
}

Procuration

namespace HelloWorld
{
  public class Proxy : ClientBase<IHelloWorldService>, IHelloWorldService
  {
    #region IHelloWorldService Members

    public String GetMessage(String name)
    {
        return Channel.GetMessage(name);
    }

    #endregion

  }

}

Client

namespace Client
{
  public partial class Form1 : Form
  {
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click_1(object sender, EventArgs e)
    {
        Proxy proxy = new Proxy();
        MessageBox.Show(proxy.GetMessage(textBox1.Text));
    }
  }

}

Le client est juste un formulaire avec une zone de texte et un bouton, et il essaie d'exécuter GetMessage () en utilisant ce qui se trouve dans la zone de texte comme paramètre. Il existe une autre classe qui crée en fait une instance du formulaire.

Voici mon web.config pour le site Web:

Web.config

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MyServiceTypeBehaviors">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior> 
      </serviceBehaviors>
    </behaviors>
    <services>
      <service name="HelloWorld.HelloWorldService" behaviorConfiguration="MyServiceTypeBehaviors">
        <endpoint address="http://localhost:8002/" binding="basicHttpBinding" contract="HelloWorld.IHelloWorldService"/>
        <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex"/>
      </service>
    </services>
  </system.serviceModel>
</configuration>

Et voici mon app.config qui va avec le client:

app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <client>
      <endpoint address="http://localhost:8002/" binding="basicHttpBinding" contract="HelloWorld.IHelloWorldService" />
    </client>
  </system.serviceModel>

</configuration>

Mon fichier svc est très court, juste:

HelloWorldService.svc

<%@ServiceHost Service="HelloWorld.HelloWorldService"%>

Je sais que le service est en cours d'exécution, car lorsque je navigue vers http://localhost:8002/HelloWorldService.svc Dans mon navigateur, j'obtiens l'écran qui dit

Vous avez créé un service.

Pour tester ce service, vous devrez créer un client et l'utiliser pour appeler le service.

Voici donc où le problème se produit: le service s'exécute à l'aide d'IIS, je démarre une instance du client, la fenêtre avec la zone de texte et le bouton s'affiche, je tape quelques lettres, j'appuie sur le bouton, puis le programme se bloque et je obtenir la ProtocolException Unhandled, (405) Method not allowed. L'erreur se produit sur cette ligne de la classe Proxy:

return Channel.GetMessage(name);

J'essaie de comprendre cela depuis des heures et des heures, et je n'ai pas fait beaucoup de progrès. Si quelqu'un pouvait au moins m'orienter dans la bonne direction, je serais très reconnaissant.

Dernière chose: je veux écrire le client et le proxy à partir de zéro, sans utiliser svcutil.exe.

26
Nathaniel Elkins

Ok, j'ai trouvé une solution, même si je ne sais pas vraiment pourquoi cela fonctionne. Je suppose que lorsque vous utilisez Cassini ou IIS ou quoi que ce soit pour héberger le site Web, vous n'êtes pas censé spécifier une adresse dans le point de terminaison dans le fichier web.config. Tout ce que j'avais à faire était changez-le en address="" et il a commencé à fonctionner correctement. Assurez-vous que le port sur lequel votre serveur héberge le service correspond au code de votre fichier app.config.

1
Nathaniel Elkins

La raison pour laquelle cela fonctionne lorsque vous accédez à l'adresse de base (.svc) est qu'il s'agit d'une opération HTTP GET pour obtenir les métadonnées du service. Lorsque vous appelez une méthode sur votre contrat de service, vous effectuez une opération POST et, plus que probablement, cette fonctionnalité n'est tout simplement pas activée. Selon la version .NET que vous ciblez , ce sera l'un d'entre eux surligné en rouge.

enter image description here

72
Rick Rainey

Vous devez spécifier l'adresse complète de votre service dans la balise de point de terminaison de la configuration du client. Comme ça:

<endpoint address="http://localhost:8002/HelloWorldService.svc" binding="basicHttpBinding" contract="HelloWorld.IHelloWorldService" />

N'oubliez pas d'ajouter '. Svc' extension après votre nom de service dans l'attribut d'adresse de la balise de point de terminaison. Ça a marché pour moi. J'espère que vous obtiendrez la solution maintenant.

La configuration du client ressemblera à ceci:

 <system.serviceModel>
<bindings>
  <wsHttpBinding>
    <binding name="WSHttpBinding_IService"/>
  </wsHttpBinding>
</bindings>
<client>
  <endpoint address="http://localhost:61569/Service1.svc" binding="wsHttpBinding" 
            bindingConfiguration="WSHttpBinding_IService" contract="WcfServiceApp.IService1" name="WSHttpBinding_IService"/>
</client>
4
Rashmi Singh

Vous devez spécifier l'adresse complète de votre service dans la balise de point de terminaison de la configuration du client

address = "http: // localhost: 8002/HelloWorldService.svc", où vous mettez les mêmes configurations de point de terminaison.

Cela a fonctionné pour moi pendant que j'étais pris au piège de l'enfer ...

2
Manish Anjara