web-dev-qa-db-fra.com

Le serveur distant a renvoyé une erreur: (405) Method Not Allowed. WCF REST Un service

Cette question est déjà posée ailleurs, mais ce n'est pas la solution à mon problème.

C'est mon service

[WebInvoke(UriTemplate = "", Method = "POST")]
public SampleItem Create(SampleItem instance)
{
    // TODO: Add the new instance of SampleItem to the collection
    // throw new NotImplementedException();
    return new SampleItem();
}

J'ai ce code pour appeler le service ci-dessus

XElement data = new XElement("SampleItem",
                             new XElement("Id", "2"),
                             new XElement("StringValue", "sdddsdssd")
                           ); 

System.IO.MemoryStream dataSream1 = new MemoryStream();
data.Save(dataSream1);

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:2517/Service1/Create");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
// You need to know length and it has to be set before you access request stream
request.ContentLength = dataSream1.Length;

using (Stream requestStream = request.GetRequestStream())
{
    dataSream1.CopyTo(requestStream);
    byte[] bytes = dataSream1.ToArray();
    requestStream.Write(bytes, 0, Convert.ToInt16(dataSream1.Length));
    requestStream.Close();
}

WebResponse response = request.GetResponse();

Je reçois une exception à la dernière ligne: 

Le serveur distant a renvoyé une erreur: (405) Method Not Allowed. Pas sûr pourquoi cela se produit j'ai essayé de changer l'hôte de VS Server à IIS également mais aucun changement dans le résultat Faites-moi savoir si vous avez besoin de plus d'informations

7
Praneeth

La première chose à faire est de connaître l'URL exacte de votre service REST. Puisque vous avez spécifié http://localhost:2517/Service1/Create, essayez simplement d'ouvrir la même URL à partir de IE et vous devriez obtenir une méthode non autorisée car votre méthode Create est définie pour WebInvoke et que IE effectue un WebGet.

Maintenant, assurez-vous que le SampleItem de votre application client est défini dans le même espace de noms sur votre serveur ou assurez-vous que la chaîne xml que vous créez a l'espace de noms approprié pour le service afin d'identifier que la chaîne xml de l'exemple d'objet peut être désérialisée à l'objet sur le serveur.

J'ai le SampleItem défini sur mon serveur comme indiqué ci-dessous:

namespace SampleApp
{
    public class SampleItem
    {
        public int Id { get; set; }
        public string StringValue { get; set; }            
    }    
}

La chaîne xml correspondant à mon SampleItem est la suivante:

<SampleItem xmlns="http://schemas.datacontract.org/2004/07/SampleApp" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Id>6</Id><StringValue>from client testing</StringValue></SampleItem>

Maintenant, j'utilise la méthode ci-dessous pour effectuer un POST sur le service REST:

private string UseHttpWebApproach<T>(string serviceUrl, string resourceUrl, string method, T requestBody)
        {
            string responseMessage = null;
            var request = WebRequest.Create(string.Concat(serviceUrl, resourceUrl)) as HttpWebRequest;
            if (request != null)
            {
                request.ContentType = "application/xml";
                request.Method = method;
            }

            //var objContent = HttpContentExtensions.CreateDataContract(requestBody);
            if(method == "POST" && requestBody != null)
            {
                byte[] requestBodyBytes = ToByteArrayUsingDataContractSer(requestBody);
                request.ContentLength = requestBodyBytes.Length;
                using (Stream postStream = request.GetRequestStream())
                    postStream.Write(requestBodyBytes, 0, requestBodyBytes.Length);                    
            }

            if (request != null)
            {
                var response = request.GetResponse() as HttpWebResponse;
                if(response.StatusCode == HttpStatusCode.OK)
                {
                    Stream responseStream = response.GetResponseStream();
                    if (responseStream != null)
                    {
                        var reader = new StreamReader(responseStream);

                        responseMessage = reader.ReadToEnd();                        
                    }
                }
                else
                {
                    responseMessage = response.StatusDescription;
                }
            }
            return responseMessage;
        }

private static byte[] ToByteArrayUsingDataContractSer<T>(T requestBody)
        {
            byte[] bytes = null;
            var serializer1 = new DataContractSerializer(typeof(T));            
            var ms1 = new MemoryStream();            
            serializer1.WriteObject(ms1, requestBody);
            ms1.Position = 0;
            var reader = new StreamReader(ms1);
            bytes = ms1.ToArray();
            return bytes;
        }

Maintenant, j'appelle la méthode ci-dessus comme indiqué:

SampleItem objSample = new SampleItem();
objSample.Id = 7;
objSample.StringValue = "from client testing";
string serviceBaseUrl = "http://localhost:2517/Service1";
string resourceUrl = "/Create";
string method="POST";

UseHttpWebApproach<SampleItem>(serviceBaseUrl, resourceUrl, method, objSample);

J'ai aussi l'objet SampleItem défini dans le côté client. Si vous voulez construire la chaîne xml sur le client et la transmettre, vous pouvez utiliser la méthode ci-dessous:

private string UseHttpWebApproach(string serviceUrl, string resourceUrl, string method, string xmlRequestBody)
            {
                string responseMessage = null;
                var request = WebRequest.Create(string.Concat(serviceUrl, resourceUrl)) as HttpWebRequest;
                if (request != null)
                {
                    request.ContentType = "application/xml";
                    request.Method = method;
                }

                //var objContent = HttpContentExtensions.CreateDataContract(requestBody);
                if(method == "POST" && requestBody != null)
                {
                    byte[] requestBodyBytes = ASCIIEncoding.UTF8.GetBytes(xmlRequestBody.ToString());
                    request.ContentLength = requestBodyBytes.Length;
                    using (Stream postStream = request.GetRequestStream())
                        postStream.Write(requestBodyBytes, 0, requestBodyBytes.Length);                    
                }

                if (request != null)
                {
                    var response = request.GetResponse() as HttpWebResponse;
                    if(response.StatusCode == HttpStatusCode.OK)
                    {
                        Stream responseStream = response.GetResponseStream();
                        if (responseStream != null)
                        {
                            var reader = new StreamReader(responseStream);

                            responseMessage = reader.ReadToEnd();                        
                        }
                    }
                    else
                    {
                        responseMessage = response.StatusDescription;
                    }
                }
                return responseMessage;
            }

Et l'appel à la méthode ci-dessus serait comme indiqué ci-dessous:

string sample = "<SampleItem xmlns=\"http://schemas.datacontract.org/2004/07/XmlRestService\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><Id>6</Id><StringValue>from client testing</StringValue></SampleItem>";   
string serviceBaseUrl = "http://localhost:2517/Service1";
string resourceUrl = "/Create";
string method="POST";             
UseHttpWebApproach<string>(serviceBaseUrl, resourceUrl, method, sample);

NOTE: Assurez-vous simplement que votre URL est correcte

6
Rajesh

Utilisez-vous l'application WCF pour la première fois?

exécuter ci-dessous la commande pour enregistrer wcf.

"%WINDIR%\Microsoft.Net\Framework\v3.0\Windows Communication Foundation\ServiceModelReg.exe" -r
2
user1312242

Après avoir passé 2 jours à ce sujet, utilisant VS 2010 .NET 4.0, IIS 7.5 WCF et REST avec JSON ResponseWrapped, je l’ai finalement déchiffré en lisant "Si l’enquête est approfondie ..." ici https : //sites.google.com/site/wcfpandu/useful-links

Le fichier généré par le code du client de service Web Reference.cs n'attribue pas les méthodes GET à [WebGet()]; il tente donc de les POST, d'où le InvalidProtocol, Méthode 405 non autorisée. Le problème est que ce fichier est régénéré chaque fois que vous actualisez la référence de service et que vous avez également besoin d'une référence à la DLL avec System.ServiceModel.Web, pour l'attribut WebGet.

J'ai donc décidé de modifier manuellement le fichier Reference.cs et d'en conserver une copie. La prochaine fois que je l'actualiserai, je fusifierai ma WebGet()s dans.

Comme je le vois, c'est un bogue avec svcutil.exe qui ne reconnaît pas que certaines des méthodes de service sont GET et pas seulement POST, même si le WSDL et HELP que le service Web WCF IIS publie, comprend quelles méthodes sont POST et GET ??? J'ai enregistré ce problème avec Microsoft Connect.

2
Deano

Le problème que j'ai résolu, car votre service est sécurisé par des informations de connexion avec nom d'utilisateur et mot de passe, essayez de configurer le nom d'utilisateur et le mot de passe sur la demande, cela fonctionnera. Bonne chance!

0
user10244822

Dans le cas que j'ai rencontré, il y avait encore une autre cause: le code sous-jacent essayait de faire un WebDAV PUT. (Cette application particulière était configurable pour activer cette fonctionnalité si nécessaire; elle était, à mon insu, activée, mais l'environnement de serveur Web nécessaire n'était pas configuré.

J'espère que cela pourra aider quelqu'un d'autre.

0
Reg Edit

Quand cela m'est arrivé, j'ai simplement ajouté Word postau nom de la fonction, et cela a résolu mon problème. peut-être que cela aidera aussi certains d’entre vous.

0
ParPar