How to use eucalyptus REST api in c# - c#

Could anyone help me with this example of REST api “describe eucalyptus instances” in c# without using AWS sdk for .net?
I give you my sample code. This code is running in aws successfully, but in eucalyptus they give a “404 not found” error.
protected void Page_Load(object sender, EventArgs e)
{
EucaListInstance("xyx/services/Eucalyptus");
}
private void ListEucaInstance(string inboundQueueUrl)
{
// Create a request for the URL.
string date = System.DateTime.UtcNow.ToString("s");
string stringToSign = string.Format("DescribeInstances" + date);
string signature = CalculateEucaSignature(stringToSign, true);
StringBuilder sb = new StringBuilder();
sb.Append(inboundQueueUrl);
sb.Append("?Action=DescribeInstances");
sb.Append("&Version=2013-10-15");
sb.AppendFormat("&AWSAccessKeyId={0}", m_EucaAccessKeyID);
sb.AppendFormat("&Expires={0}", date);
sb.AppendFormat("&Signature={0}", signature);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(sb.ToString());
HttpWebResponse response = null;
Stream dataStream = null;
StreamReader reader = null;
try
{
request.Credentials = CredentialCache.DefaultCredentials;
response = (HttpWebResponse)request.GetResponse();
// Get the stream containing content returned by the server.
dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
reader = new StreamReader(dataStream);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
// Cleanup the streams and the response.
if (reader != null)
reader.Close();
if (dataStream != null)
dataStream.Close();
if (response != null)
response.Close();
}
}
private string CalculateEucaSignature(string data, bool urlEncode)
{
ASCIIEncoding ae = new ASCIIEncoding();
HMACSHA1 signature = new HMACSHA1(ae.GetBytes(m_EucaSecretKey));
string retSignature = Convert.ToBase64String(signature.ComputeHash(ae.GetBytes(data.ToCharArray())));
return urlEncode ? HttpUtility.UrlEncode(retSignature) : retSignature;
}

You would get a 404 error if you are sending the request to the wrong URL. I would verify that you are sending to the correct URL, which would typically be along the lines of:
http://eucalyptus.your.domain.here.example.com:8773/services/Eucalyptus
You can find the URL to use in your deployment by looking in your eucarc file for the EC2_URL value, or by running the "euca-describe-services -T eucalyptus" admin command (in versions up to 4.0, for 4.0 onward you would use "-T compute")

Related

Download a URL image to a client PC via C#

I'm trying to access a file on the server via an api that is behind Basic Auth. I then want to download that to a client's PC.
I've got the following code which does GET the url from behind the basic auth, however the image never downloads properly. I either get a failed network error message or I get a message saying I can't download it because my machine doesn't have an app installed to open it. It's a png so it definitely does!
It goes the whole way through the code and doesn't error so I'm confused as to why it's not downloading correctly to the clients machine (my pc while I'm testing!)
In the code I am specifying one file and I have specified it's length as bytes just to try and narrow down where I'm going wrong. Normally this could be any file that's being access of any length!
This is the code I have:
//Create a stream for the file
Stream stream = null;
var size = fileResp.ContentLength; //I used this to determine the file was 64196 in size
//This controls how many bytes to read at a time and send to the client
int bytesToRead = 64196;
// Buffer to read bytes in chunk size specified above
byte[] buffer = new Byte[bytesToRead];
string url= "https://myURL/images/image-2019-04-02-16-25-18-458.png";
WebRequest myReq = WebRequest.Create(url);
string credentials = "username:pwd";
CredentialCache mycache = new CredentialCache();
myReq.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(credentials));
myReq.Method = "GET";
// The number of bytes read
try
{
//Create a response for this request
HttpWebResponse fileResp = (HttpWebResponse)myReq.GetResponse();
if (myReq.ContentLength > 0)
fileResp.ContentLength = myReq.ContentLength;
//Get the Stream returned from the response
stream = fileResp.GetResponseStream();
// prepare the response to the client. resp is the client Response
var resp = HttpContext.Current.Response;
//Indicate the type of data being sent
string contentType = MimeMapping.GetMimeMapping("new.png");
resp.ContentType = contentType;
string fileName = "new.png";
//Name the file
resp.AddHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
resp.AddHeader("Content-Length", fileResp.ContentLength.ToString());
int length;
do
{
// Verify that the client is connected.
if (resp.IsClientConnected)
{
// Read data into the buffer.
length = stream.Read(buffer, 0, bytesToRead);
// and write it out to the response's output stream
resp.OutputStream.Write(buffer, 0, length);
// Flush the data
resp.Flush();
//Clear the buffer
buffer = new Byte[bytesToRead];
}
else
{
// cancel the download if client has disconnected
length = -1;
}
} while (length > 0); //Repeat until no data is read
}
finally
{
if (stream != null)
{
//Close the input stream
stream.Close();
}
}
The output from here: fileResp.GetResponseStream();
At first, please try to test if the following code works on your computer.
private bool DownloadImage(string imgurl, string filename)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(imgurl);
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch
{
response = null;
return false;
}
if (response != null && response.StatusCode == HttpStatusCode.OK)
{
Stream receiveStream = response.GetResponseStream();
Bitmap bitmap = new Bitmap(receiveStream);
if (bitmap != null)
{
bitmap.Save(filename);
}
receiveStream.Flush();
receiveStream.Close();
response.Close();
return true;
}
else
{
return false;
}
}
private void button1_Click(object sender, EventArgs e)
{
string imgurl = "https://upload.wikimedia.org/wikipedia/commons/4/42/Cute-Ball-Go-icon.png";
string filename = "D:\\download_test.png";
bool bIsDownloadSuccess = DownloadImage(imgurl, filename);
}
This code works on me well.
It doesn't have error, but returns false.
Please check where false is returned.
If it has some error, the problem will be on Windows System.
Please try and let me know.
Thanks.

Consuming java web service getting error

I am getting error while consuming java web service in my win form application
The error is
You must provide a request body if you set ContentLength>0 or
SendChunked==true. Do this by calling [Begin]GetRequestStream before
[Begin]GetResponse.
My code to consume java service
public byte[] StringToByteArray(string stringData)
{
System.Text.UTF8Encoding Encoding = new System.Text.UTF8Encoding();
return Encoding.GetBytes(stringData);
}
private void button1_Click(object sender, EventArgs e)
{
string DATA = #"<RepositoryType>117</RepositoryType>
<RepositoryCategory>0</RepositoryCategory>
<ModifiedBy>2825</ModifiedBy>
<ReferenceCode>0</ReferenceCode>
<FromDate>2015-10-14T11:50:00</FromDate>
<ToDate>2015-10-14T11:51:00</ToDate>
<RepositoryName>ashok</RepositoryName>
<RepositoryShortName>kumar</RepositoryShortName>
<RepositoryDesc>nothing</RepositoryDesc>
<Fixed>F</Fixed>
<IsValid>true</IsValid>
<lstVisa />
<SortOrder>0</SortOrder>
</Repository>";`
byte[] postdata = null;
HttpWebRequest _WebRequest = null;
HttpWebResponse webresponse = null;
StreamReader ResponseStream = null;
string sReturnVal = string.Empty;
string
serviceAddress="http://172.16.12.21:8888/XML_RESPONSE/rest/test/xmltest/";
try
{
_WebRequest = (HttpWebRequest)WebRequest.Create(serviceAddress + "/" + DATA);
postdata = StringToByteArray(DATA);
if (_WebRequest != null)
{
if (postdata!=null)
{
_WebRequest.Method = "POST";
_WebRequest.ContentType= "text/xml";
_WebRequest.ContentLength = postdata.Length;
_WebRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)";
_WebRequest.SendChunked = true;
}
**webresponse = (HttpWebResponse)_WebRequest.GetResponse();**
{
if (webresponse.Headers.Get("Content-Encoding") != null && webresponse.Headers.Get("Content-Encoding").ToLower() == "gzip")
ResponseStream = new StreamReader(new GZipStream(webresponse.GetResponseStream(), CompressionMode.Decompress));
else
{
Encoding enc = System.Text.Encoding.GetEncoding(1252);
ResponseStream = new StreamReader(webresponse.GetResponseStream(), enc);
}
if (ResponseStream != null)
{
XElement Root = XElement.Load(ResponseStream);
sReturnVal = Root.Value;
}
}
}
else
{
throw new Exception("Connection to " + " Service could not be Established.",
new Exception("Please Check whether " +
" Service is running Or Contact your System Administrator."));
}
}
catch(Exception ex)
{
}
}
the highlighted line is getting error.
Please help in this.
You're adding the data to the URL instead of posting it as the request body. Take a look at this question for working code you can use: HTTP POST using web service. With ASP.NET webservices you must set the SOAPAction HTTP header, you can skip this line if your service doesn't require it.

Why would I get, "The remote server returned an error: (400) Bad Request" with this code?

I was first getting "Unable to connect to the remote server" but then remembered that I couldn't use "localhost" from a handheld device. I swapped that out with the name of the machine like so:
String uri = String.Format(#"http://PLATYPUS:21608/api/inventory/sendXML/woodrow/gus/{0}", fileName);
//I reckon I could also use the IP address in place of the machine name, but probably would make no difference
...and now I get, "The remote server returned an error: (400) Bad Request"
The same basic code (shown below) runs fine from a "regular" (C# desktop) app created in VS 2013. From the handheld device, with this code created in VS 2003, I get that ("400") err msg. Why might that be?
public static string SendXMLFile(string xmlFilepath, string uri, int timeout)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version10;
request.ContentType = "application/xml";
request.Method = "POST";
StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader(xmlFilepath))
{
String line;
while ((line = sr.ReadLine()) != null)
{
sb.Append(line);
sb.Append("\r\n");
}
byte[] postBytes = Encoding.UTF8.GetBytes(sb.ToString());
if (timeout < 0)
{
request.Timeout = timeout;
}
request.ContentLength = postBytes.Length;
request.KeepAlive = false;
request.ContentType = "application/x-www-form-urlencoded"; // not "text/xml" correct?
try
{
Stream requestStream = request.GetRequestStream();
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();
HttpWebResponse response = (HttpWebResponse) request.GetResponse();
return response.ToString();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
request.Abort();
return string.Empty;
}
}
}
This code differs only slightly from that in the VS 2013 app, in these ways:
(a) Above/not working:
sb.Append(line);
sb.Append("\r\n");
Below/working:
sb.AppendLine(line);
(b) Above/not working:
request.Timeout = timeout;
Below/working:
request.ReadWriteTimeout = timeout;
request.Timeout = timeout;
(c) Above/not working:
HttpWebResponse response = (HttpWebResponse) request.GetResponse();
return response.ToString();
Below/working:
using (var response = (HttpWebResponse)request.GetResponse())
{
return response.ToString();
}
VS 2013 code that works:
public static string SendXMLFile(string xmlFilepath, string uri, int timeout)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version10;
request.ContentType = "application/xml";
request.Method = "POST";
StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader(xmlFilepath))
{
String line;
while ((line = sr.ReadLine()) != null)
{
sb.AppendLine(line);
}
byte[] postBytes = Encoding.UTF8.GetBytes(sb.ToString());
if (timeout < 0)
{
request.ReadWriteTimeout = timeout;
request.Timeout = timeout;
}
request.ContentLength = postBytes.Length;
request.KeepAlive = false;
request.ContentType = "application/x-www-form-urlencoded"; // not "text/xml" correct?
try
{
Stream requestStream = request.GetRequestStream();
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();
using (var response = (HttpWebResponse)request.GetResponse())
{
return response.ToString();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
request.Abort();
return string.Empty;
}
}
}
The working code (no err msgs, and the file is saved to the hard drive) passes this to SendXMLFile():
xmlFilepath == "C:\\HoldingTank\\Bla123456789.xml"
uri == http://localhost:21608/api/inventory/sendXML/woodrow/gus/Bla123456789
timeout == 500
The failing code (err msg, file is created and saved, but it is empty) passes:
xmlFilepath == "Bla123456789.xml"
uri == http://SHANNON2:21608/api/inventory/sendXML/woodrow/gus/Bla123456789
timeout == 500
(the ".xml" is stripped out of xmlFilePath before passing that string to the server on the URI)
As to whether the file in xmlFilePath exists in the failing code, I've got this code:
public static bool WriteIt2( string fileName, string data, long fsize )
{
bool retVal = false;
long bytRd = 0;
string the_Msg = "";
if (File.Exists(fileName))
File.Delete(fileName);
using (FileStream fs = File.Create(#fileName))
{
Byte[] info = new UTF8Encoding(true).GetBytes(data);
fs.Write(info, 0, info.Length);
fs.Flush();
}
if (!File.Exists(fileName))
{
MessageBox.Show(String.Format("{0} does not seem to exist", fileName));
}
else
{
MessageBox.Show(String.Format("{0} DOES seem to exist", fileName));
}
string justFileName = Path.GetFileNameWithoutExtension(fileName);
String uri = String.Format(#"http://PLATYPUS:21608/api/inventory/sendXML/woodrow/gus/{0}", fileName);
. . .
...and I do see the "...DOES seem to exist" affirmation message.
Does the filename need to have "\" (or something else) prepended to it?
Is the file writing (FileStream) code wrong?
UPDATE
I tried it with slightly different FileStream code:
Byte[] info = Encoding.ASCII.GetBytes(data);
using (FileStream fileTest = File.Open(fileName, FileMode.CreateNew))
{
fileTest.Write(info, 0, info.Length);
fileTest.Flush();
}
. . .
...but still get the same "400" error.
UPDATE 2
Also with a UTF8 byte array instead of an ASCII byte array:
Byte[] info = Encoding.UTF8.GetBytes(data);
...still get the same err...
UPDATE 3
I realized I was making a boo-boo here:
string justFileName = Path.GetFileNameWithoutExtension(fileName);
. . .
SendXMLFile(fileName, uri, 500);
...and so changed it to:
SendXMLFile(justFileName, uri, 500);
...and now I get a "File not found" exception.
How can it pass the File.Exists test and then not be found?
UPDATE 4
Okay, something really crazy is going on, because I copied a file to the handheld device, into the folder where the .exe/.dll are located, and assigned its name to "justFileName"; it still says the file cannot be found.
Alright, Fiddler here I come...
UPDATE 5
Okay, here's what I see in Fiddler with the server running and then I try to send the file from the handheld device:
Not much appears in Fiddler before the attempt to send the file fails/aborts, and what does display in Fiddler doesn't seem overly helpful.
I wonder if it's not even getting to the point of sending any Http traffic from the handheld? Since I get "File not Found" there's a good chance that's true - why would it try to send it, if it can't find it?
UPDATE 6
As far as a possible header difference (still don't see anything related to my HTTP traffic in Fiddler), I would think I would think I might get a report from Fiddler about that if it was a problem, because I got this due to yahoo Ads bad acting (apparently):
UPDATE 7
I fixed the problem with the file not being found, but that takes me back to the "400" err. Odder yet, I have a breakpoint on the server code (on the "String saveLoc = " line), but it is not getting reached...???
[Route("api/inventory/sendXML/{userId}/{pwd}/{filename}")]
public async void SendInventoryXML(String userId, String pwd, String fileName)
{
XDocument doc = XDocument.Load(await Request.Content.ReadAsStreamAsync());
String saveLoc = String.Format(#"C:\HDP\{0}.xml", fileName); // this line has a breakpoint on it, but Rip Van Winkle is not getting poked.
doc.Save(saveLoc);
}
So the err returned from the server is happening even prior to that (breakpointed) line...???
UPDATE 8
In an attempt to understand why the server method is not being reached and I get the "error (400)" msg, I added a bunch of debug strings to see the values of the HttpWebRequest, like so:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
. . .
request.ContentLength = postBytes.Length;
String str;
if (null != request.Address)
{
String str = String.Format("request.Address == {0}", request.Address.ToString());
MessageBox.Show(str);
}
if (null != request.Connection)
{
str = String.Format("connection == {0}", request.Connection.ToString());
MessageBox.Show(str);
}
. . .
if (null != request.ContentLength.ToString())
{
str = String.Format("contentLength == {0}", request.ContentLength.ToString());
MessageBox.Show(str);
}
I added these debug strings for the following "request" (HttpWebRequest) properties:
Address
Connection
ContentType
Expect
MediaType
Referer // Referrer (don't fear the spell-checker)
RequestUri
TransferEncoding
UserAgent
ContentLength
The only ones that display (are not null) are:
Address
ContentType
RequestUri
ContentLength
So the others being null - is that possibly a/the problem?
In the interests of full disclosure, the values displayed are:
Address == http://PLATYPUS:21608/api/Inventory/sendXML/gus/woodrow/INV_0000003_08272014175010
ContentType == application/xml
RequestUri == [same as Address]
ContentLength == 11457215
Note: I still get the "400" err msg following the display of these four values...
UPDATE 9
Should this:
request.KeepAlive = false;
...be set to true instead (or simply left out altogether, as it is apparently true by default?
UPDATE 10
Please see Update 2 here.

Sending data to php from windows phone

I need to send some data from windows phone 7 to php page through POST method, I have the following code at wp7 side
public void SendPost()
{
var url = "http://localhost/HelpFello/profile.php";
// Create the web request object
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
// Start the request
webRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), webRequest);
MessageBox.Show("data sent");
}
void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
// End the stream request operation
Stream postStream = webRequest.EndGetRequestStream(asynchronousResult);
// Create the post data
// Demo POST data
string postData = "user_id=3&name=danish&email_id=mdsiddiquiufo&password=12345&phone_Number=0213&about_me=IRuel2&rating=5";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Add the post data to the web request
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Start the web request
webRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), webRequest);
}
void GetResponseCallback(IAsyncResult asynchronousResult)
{
try
{
HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response;
// End the get response operation
response = (HttpWebResponse)webRequest.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamReader = new StreamReader(streamResponse);
var Response = streamReader.ReadToEnd();
streamResponse.Close();
streamReader.Close();
response.Close();
}
catch (WebException e)
{
MessageBox.Show(e.ToString());
}
}
and following on my localhost, to send the data to database
<?php
require_once("constants.php");
$user_id = $_POST['user_id'];
$name = $_POST['name'];
$email_id = $_POST['email_id'];
$password = $_POST['password'];
$phone_number = $_POST['phone_number'];
$about_me = $_POST['about_me'];
$rating = $_POST['rating'];
$query="INSERT INTO profile(User_ID,Name,Email_ID,password,Phone_Number,About_Me,Rating) VALUES ({$user_id},'{$name}','{$email_id}','{$password}',{$phone_number}, '{$about_me}' , {$rating})";
mysql_query($query,$connection);
mysql_close($connection);
?>
When I run the code I have no errors it means code is working fine, but no data is inserted in the database.
I think there is a better way than HttpWebRequest. That is WebClient. You can change the method there and append data like you do in get string. key=value&key2=value then when you invoke that request and get the response try debugging and getting the output from VS or if that is difficult simply assign he string to a textblock in the code. You will get to know if that page has been ever executed or not.
A sample code :
WebClient wc = new WebClient();
wc.UploadStringCompleted += new UploadStringCompletedEventHandler(wc_UploadStringCompleted);
wc.Headers["Content-Type"] = "application/x-www-form-urlencoded";
wc.Encoding = Encoding.UTF8;
Parameters prms = new Parameters();
prms.AddPair("email", email);
prms.AddPair("password", password);
wc.UploadStringAsync(new Uri(loginUrl), "POST", prms.FormPostData(), null);
private void wc_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
// e.Result will contain the page's output
}
// This is my Parameters and Parameter Object classes
public class Parameters
{
public List<ParameterObject> prms;
public Parameters()
{
prms = new List<ParameterObject>();
}
public void AddPair(string id, string val)
{
prms.Add(new ParameterObject(id, val));
}
public String FormPostData()
{
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < prms.Count; i++)
{
if (i == 0)
{
buffer.Append(System.Net.HttpUtility.UrlEncode(prms[i].id) + "=" + System.Net.HttpUtility.UrlEncode(prms[i].value));
}
else
{
buffer.Append("&" + System.Net.HttpUtility.UrlEncode(prms[i].id) + "=" + System.Net.HttpUtility.UrlEncode(prms[i].value));
}
}
return buffer.ToString();
}
}
public class ParameterObject
{
public string id;
public string value;
public ParameterObject(string id, string val)
{
this.id = id;
this.value = val;
}
}
First error: assuming that no error messages means success
Second error: gaping SQL injection holes
first fix: always assume queries will fail, and check for that condition:
$result = mysql_query($query) or die(mysql_error());
second fix: ditch the mysql_() functions and switch to PDO using prepared statements with placeholders. Boom. No more injection problems, and your code won't stop working on you when mysql_() is removed in a future PHP version.
ps..
3rd error: no quotes on your phone number value. So someone submits 867-5309, and you end up inserting -4442 because mysql saw it as two numbers being subtracted, not a string.

The remote server returned an error: (405) Method Not Allowed. WCF REST Service

This question is already asked elsewhere but those things are not the solutions for my issue.
This is my 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();
}
I have this code to call the above service
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();
I get an exception at the last line:
The remote server returned an error: (405) Method Not Allowed. Not sure why this is happening i tried changing the host from VS Server to IIS also but no change in result. Let me know if u need more information
First thing is to know the exact URL for your REST Service. Since you have specified http://localhost:2517/Service1/Create now just try to open the same URL from IE and you should get method not allowed as your Create Method is defined for WebInvoke and IE does a WebGet.
Now make sure that you have the SampleItem in your client app defined in the same namespace on your server or make sure that the xml string you are building has the appropriate namespace for the service to identify that the xml string of sample object can be deserialized back to the object on server.
I have the SampleItem defined on my server as shown below:
namespace SampleApp
{
public class SampleItem
{
public int Id { get; set; }
public string StringValue { get; set; }
}
}
The xml string corresponding to my SampleItem is as below:
<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>
Now i use the below method to perform a POST to the REST service :
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;
}
Now i call the above method as shown:
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);
I have the SampleItem object defined in the client side as well. If you want to build the xml string on the client and pass then you can use the below method:
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;
}
And the call to the above method would be as shown below:
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: Just make sure that your URL is correct
Are you running WCF application for the first time?
run below command to register wcf.
"%WINDIR%\Microsoft.Net\Framework\v3.0\Windows Communication Foundation\ServiceModelReg.exe" -r
After spending 2 days on this, using VS 2010 .NET 4.0, IIS 7.5 WCF and REST with JSON ResponseWrapped, I finally cracked it by reading from "When investigating further..." here https://sites.google.com/site/wcfpandu/useful-links
The Web Service Client code generated file Reference.cs doesn't attribute the GET methods with [WebGet()], so attempts to POST them instead, hence the InvalidProtocol, 405 Method Not Allowed. Problem is though, this file is regenerated when ever you refresh the service reference, and you also need a dll reference to System.ServiceModel.Web, for the WebGet attribute.
So I've decided to manually edit the Reference.cs file, and keep a copy. Next time I refresh it, I'll merge my WebGet()s back in.
The way I see it, it's a bug with svcutil.exe not recognising that some of the service methods are GET and not just POST, even though the WSDL and HELP that the WCF IIS web service publishes, does understand which methods are POST and GET??? I've logged this issue with Microsoft Connect.
When it happened to me, I just simply added the word post
to the function name, and it solved my problem. maybe it will help some of you too.
In the case I came up against, there was yet another cause: the underlying code was attempting to do a WebDAV PUT. (This particular application was configurable to enable this feature if required; the feature was, unbeknownst to me, enabled, but the necessary web server environment was not set up.
Hopefully this may help someone else.
The issue I have fixed, because your service is secured by login credential with user name and password, try set up the user name and password on the request, it will be working. Good luck!

Categories