この質問はすでに他の場所で質問されていますが、それらは私の問題の解決策ではありません。
これは私のサービスです
[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();
}
上記のサービスを呼び出すためのこのコードがあります
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();
最後の行で例外が発生します。
リモートサーバーがエラーを返しました:(405)メソッドが許可されていません。なぜこれが起こっているのかわからないので、ホストをVSサーバーからIISにも変更しましたが、結果は変わりません。詳細が必要な場合はお知らせください
まず、RESTサービスの正確なURLを確認します。 http://localhost:2517/Service1/Create
を指定したので、IEから同じURLを開こうとすると、Create
メソッドがWebInvokeおよびIEはWebGetを実行します。
次に、クライアントアプリのSampleItemがサーバーの同じ名前空間で定義されていることを確認するか、作成するXML文字列に、サービスがサンプルオブジェクトのXML文字列を逆シリアル化できることを識別する適切な名前空間があることを確認します。サーバー上のオブジェクトに。
以下に示すように、サーバーでSampleItemを定義しています。
namespace SampleApp
{
public class SampleItem
{
public int Id { get; set; }
public string StringValue { get; set; }
}
}
SampleItemに対応するxml文字列は次のとおりです。
<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>
ここで、以下のメソッドを使用して、POSTサービスに対して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;
}
次に、上記のメソッドを次のように呼び出します。
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);
クライアント側でもSampleItemオブジェクトを定義しています。クライアントでxml文字列を作成して渡す場合は、以下のメソッドを使用できます。
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;
}
上記のメソッドの呼び出しは以下のようになります。
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);
注:URLが正しいことを確認してください
初めてWCFアプリケーションを実行していますか?
以下のコマンドを実行してwcfを登録します。
"%WINDIR%\Microsoft.Net\Framework\v3.0\Windows Communication Foundation\ServiceModelReg.exe" -r
これに2日間費やした後、VS 2010 .NET 4.0、IIS 7.5 WCF、およびRESTをJSON ResponseWrappedで使用して、「ここでさらに調査するとき...」を読んで最終的にクラックしました https://sites.google.com/site/wcfpandu/useful-links
Webサービスクライアントのコードで生成されたファイルReference.csは、GET
メソッドを[WebGet()]
で属性付けしないため、代わりにPOST
メソッドを試みます。したがって、InvalidProtocol、405メソッドは許可されません。問題は、サービス参照を更新するとこのファイルが再生成され、WebGet属性の_System.ServiceModel.Web
_へのdll参照も必要になることです。
そのため、Reference.csファイルを手動で編集し、コピーを保持することにしました。次にリフレッシュするときに、WebGet()s
をマージして戻します。
WCF IIS Webサービスが公開しているWSDLおよびHELPがどのメソッドを理解しているかにかかわらず、一部のサービスメソッドがGET
ではなくPOST
であると認識しないsvcutil.exeのバグですPOST
およびGET
???この問題をMicrosoft Connectで記録しました。
私が修正した問題は、ユーザー名とパスワードを使用したログイン資格情報によってサービスが保護されているため、リクエストにユーザー名とパスワードを設定してみてください。サービスは機能します。幸運を!
私が直面したケースでは、さらに別の原因がありました:基礎となるコードが WebDAV PUTを実行しようとしていました。 (この特定のアプリケーションは、必要に応じてこの機能を有効にするように構成可能でした。この機能は、私には知られていないため有効にされていましたが、必要なWebサーバー環境がセットアップされていませんでした。
うまくいけば、これは他の誰かを助けるかもしれません。
それが起こったときは、関数名にWord post
を追加するだけで問題が解決しました。多分それはあなたの一部にも役立ちます。