I'm trying to use a web service that doesn't use SOAP and WSDL but i don't know how to do it. I would really appreciate some pointers.
The API for the service is:
http://someaddress.com/webservices/name/id where id is the parameter.
The supported request method is GET.
Could i use something like this:
var myReq = new XMLHttpRequest();
var url = "http://someaddress.com/webservices/name/2"
myReq.open("GET", url, true);
myReq.send();
The simplest way to get an xml is to use the url as an argument to XDocument.Load() method.
var xml = XDocument.Load("http:...");
This method fetches the data from a remote url, parses it using an XmlReader an constructs an XDocument object. Then you can use LINQ to XML to query or transform data.
Unfortunately, this wouldn't work for POST, DELETE, PUT http requests
Edit:
It depends on your service and what operations you can do with it:
Using XDocument.Load() is the simplest solution. If this is a simple resource over the internet, with no authentication, no HTTp headers needed and supports only GET requests than this is the way to go. You can write a method which take your parameters and appends them in the URL
public SomeClass GetSomeEntity(string id)
{
var xml = XDocument.Load("http://mywebservice.com/ws/" + id);
// transform xml into an instance of actual type
}
Using a WebClient you can get more control over your HttpRequest. You can set basic authentication credentials, append other HTTP headers, POST form-data etc. You have "async" methods also.
using (var client = new WebClient())
{
var xml = XDocument.Load(client.OpenRead("http://yoururl.com");
// process xml
}
You can think of "HttpWebRequest" as a low-level implementation of a web request.
Here is a snipped of code to help you do this..
public static string SendRequest(string uri, string method, string contentType, string body)
{
string responseBody = String.Empty;
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(new Uri(uri));
req.Method = method;
if (!String.IsNullOrEmpty(contentType))
{
req.ContentType = contentType;
}
if (!String.IsNullOrEmpty(body))
{
byte[] bodyBytes = Encoding.UTF8.GetBytes(body);
req.GetRequestStream().Write(bodyBytes, 0, bodyBytes.Length);
req.GetRequestStream().Close();
}
HttpWebResponse resp;
try
{
resp = (HttpWebResponse)req.GetResponse();
}
catch (WebException e)
{
resp = (HttpWebResponse)e.Response;
}
Stream respStream = resp.GetResponseStream();
if (respStream != null)
{
responseBody = new StreamReader(respStream).ReadToEnd();
}
return responseBody;
}
The WebClient object is very well done for those kind of tasks.
Check out the WCF REST Developer Center - it shows you how easily and efficiently you can create REST services (no SOAP) using the WCF infrastructure.
Using JQuery is the simplest as far as I know. Try if this works in your case:
var param = new Object();
param.id = 2;
$.ajax({
type: "GET",
url: "http://someaddress.com/webservices/name",
data: $.toJSON(param),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
if (msg.d) {
//do something
}
}
});
Related
I have some JavaScript code that I need to convert to C#. My JavaScript code POSTs some JSON to a web service that's been created. This JavaScript code works fine and looks like the following:
var vm = { k: "1", a: "2", c: "3", v: "4" };
$.ajax({
url: "http://www.mysite.com/1.0/service/action",
type: "POST",
data: JSON.stringify(vm),
contentType: "application/json;charset=utf-8",
success: action_Succeeded,
error: action_Failed
});
function action_Succeeded(r) {
console.log(r);
}
function log_Failed(r1, r2, r3) {
alert("fail");
}
I'm trying to figure out how to convert this to C#. My app is using .NET 2.0. From what I can tell, I need to do something like the following:
using (WebClient client = new WebClient())
{
string json = "?";
client.UploadString("http://www.mysite.com/1.0/service/action", json);
}
I'm a little stuck at this point. I'm not sure what json should look like. I'm not sure if I need to set the content type. If I do, I'm not sure how to do that. I also saw UploadData. So, I'm not sure if I'm even using the right method. In a sense, the serialization of my data is my problem.
Can someone tell me what I'm missing here?
Thank you!
The question is already answered but I think I've found the solution that is simpler and more relevant to the question title, here it is:
var cli = new WebClient();
cli.Headers[HttpRequestHeader.ContentType] = "application/json";
string response = cli.UploadString("http://some/address", "{some:\"json data\"}");
PS: In the most of .net implementations, but not in all WebClient is IDisposable, so of cource it is better to do 'using' or 'Dispose' on it. However in this particular case it is not really necessary.
The following example demonstrates how to POST a JSON via WebClient.UploadString Method:
var vm = new { k = "1", a = "2", c = "3", v= "4" };
using (var client = new WebClient())
{
var dataString = JsonConvert.SerializeObject(vm);
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
client.UploadString(new Uri("http://www.contoso.com/1.0/service/action"), "POST", dataString);
}
Prerequisites: Json.NET library
You need a json serializer to parse your content, probably you already have it,
for your initial question on how to make a request, this might be an idea:
var baseAddress = "http://www.example.com/1.0/service/action";
var http = (HttpWebRequest)WebRequest.Create(new Uri(baseAddress));
http.Accept = "application/json";
http.ContentType = "application/json";
http.Method = "POST";
string parsedContent = <<PUT HERE YOUR JSON PARSED CONTENT>>;
ASCIIEncoding encoding = new ASCIIEncoding();
Byte[] bytes = encoding.GetBytes(parsedContent);
Stream newStream = http.GetRequestStream();
newStream.Write(bytes, 0, bytes.Length);
newStream.Close();
var response = http.GetResponse();
var stream = response.GetResponseStream();
var sr = new StreamReader(stream);
var content = sr.ReadToEnd();
hope it helps,
I have an api
http://cbastest.cadvilpos.com/module/posmodule/customapi
with parameters
{
"action":4,
"device_token": "3e8ea119a90ee6d2",
"key":"9475962085b3a1b8c475d52.95782804",
"shop":1,
"language":1
}
This is working fine in postman. But when I try to connect from c# project its showing an error {"success":0,"error":"Missing the action parameter."}. Please give a working C# code to get the json result.
The code I tried:
var request = (HttpWebRequest)WebRequest.Create("http://cbastest.cadvilpos.com/module/posmodule/customapi");
var postData = "{ 'action':'4', 'device_token':'3e8ea119a90ee6d2','key':'9475962085b3a1b8c475d52.95782804','shop':'1','language':'1'}";
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/json";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response2 = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response2.GetResponseStream()).ReadToEnd();
You don't need to use a raw HttpWebRequest object to make an HTTP call. HttpClient was introduced in 2012 to allow easy asynchronous HTTP calls.
You could do something as simple as :
var content=new StringContent(postData,Encoding.UTF8, "application/json");
HttpResponseMessage response=await httpClient.PostAsync(url,content);
//Now process the response
if (response.IsSuccessCode)
{
var body=await response.Content.ReadAsStringAsync();
var responseDTO=JsonConvert.DeserializeObject<MyDTO>(body);
}
Instead of building a JSON string by hand you could use a strongly typed class or an anonymous object and serialize it to JSON with JSON.NET :
var data=new {
action=4,
device_token="3e8ea119a90ee6d2",
key = "9475962085b3a1b8c475d52.95782804",
shop=1,
language=1
};
var postData=JsonConvert.SerializeObject(data);
var content=new StringContent(postData,Encoding.UTF8, "application/json");
var response=await httpClient.PostAsync(url,content);
...
You can read a response body in one go as a string, using ReadAsStringAsync or you can get the response stream with ReadAsStreamAsync. You could copy the response data directly to another stream, eg a file or memory stream with HttpContent.CopyToAsync
Check Call a Web API from a .NET Client for more examples. Despite the title, the examples work to call any HTTP/REST API.
The Microsoft.AspNet.WebApi.Client package mentioned in that article is another thing that applies to any call, not just calls to ASP.NET Web API. The extension method PostAsJsonAsync for example, combines serializing and posting a request to a url. Using it, posting the action DTO could be reduced to a single line:
var data=new {
action=4,
device_token="3e8ea119a90ee6d2",
key = "9475962085b3a1b8c475d52.95782804",
shop=1,
language=1
};
var response=await httpClient.PostAsJsonAsync(url,data);
There is a button in Postman that will generate code for the currently defined request. The link is here:
And this is what the code looks like. You'll need to pull in RestSharp from Nuget
Currently trying to do a Get request as part of a c# program. The request works fine on Postman as it uses a header for authorization. However I cannot get the code working for the program to use this header correctly in its Get request. I've had a good look around and tried various bits of code I've found but haven't managed to resolve it so any help would be appreciated!
public string Connect()
{
using (WebClient wc = new WebClient())
{
string URI = "myURL.com";
wc.Headers.Add("Content-Type", "text");
wc.Headers[HttpRequestHeader.Authorization] = "Bearer OEMwNjI2ODQtMTc3OC00RkIxLTgyN0YtNzEzRkE5NzY3RTc3";//this is the entry code/key
string HtmlResult = wc.DownloadString(URI);
return HtmlResult;
}
}
Above is one method inside the class.
Below is another attempt which is an extension method that gets passed the URL:
public static string GetXml(this string destinationUrl)
{
HttpWebRequest request =
(HttpWebRequest)WebRequest.Create(destinationUrl);
request.Method = "GET";
request.Headers[HttpRequestHeader.Authorization] = "Bearer
OEMwNjI2ODQtMTc3OC00RkIxLTgyN0YtNzEzRkE5NzY3RTc3";
HttpWebResponse response;
response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
Stream responseStream = response.GetResponseStream();
string responseStr = new
StreamReader(responseStream).ReadToEnd();
return responseStr;
}
else
{
Console.Write(String.Format("{0}({1})",
response.StatusDescription, response.StatusCode));
}
return null;
}
Might I recommend the very handy RestSharp package (find it on Nuget).
It turns your current code into something like
public string Connect()
{
var client = new RestClient();
var request = new RestRequest("myURL.com", Method.GET);
request.AddParameter("Authorization", "Bearer OEMwNjI2ODQtMTc3OC00RkIxLTgyN0YtNzEzRkE5NzY3RTc3");
var response = client.Execute(request);
return response.Content;
}
It's much more succinct and easier to use (in my opinion) and thus lessens the likelihood of passing in or using incorrect methods.
If you're still having issues getting data back/connecting. Then using PostMan click Code in the upper right of PostMan and select the C# (RestSharp) option. Whatever is generated there matches exactly what PostMan is sending. Copy that over and you should get data back that matches your PostMan request.
I am serializing an IEnumerbale object using JsonConvert.SerializeObject( );
it produces string with quotes and escape character with spaces
from web Api controller i return that string using code below
[HttpGet]
public string GetDegreeCodes(int id)
{
string result = //output from JsonConvert.SerializeObject( );
return result;
}
"[{\"DegreeId\":1,\"DegreeName\":\"High School\",\"ImageSrc\":\"
http://bootsnipp.com/apple-touch-icon-114x114-pre\",\"Description\":\"
Get High School
Degree\r\"},{\"DegreeId\":2,\"DegreeName\":\"Associate\",\"ImageSrc\":\"
http://bootsnipp.com/apple-touch-icon-114x114-pre\",\"Description\":\"
Get Associate
Degree\r\"},{\"DegreeId\":3,\"DegreeName\":\"Bachelor\",\"ImageSrc\":\"
http://bootsnipp.com/apple-touch-icon-114x114-pre\",\"Description\":\"
Get Bachelor
Degree\r\"},{\"DegreeId\":4,\"DegreeName\":\"Masters\",\"ImageSrc\":\"
http://bootsnipp.com/apple-touch-icon-114x114-pre\",\"Description\":\"
Get Master
Degree\r\"},{\"DegreeId\":5,\"DegreeName\":\"Doctrate\",\"ImageSrc\":\"
http://bootsnipp.com/apple-touch-icon-114x114-pre\",\"Description\":\"
Get Doctorate Degree\"}]"
This is my ajax and it does not recognize the JSON correctly because of the extra wrapper quotes and escape characters,
$.ajax({
url: "/api/helloservice/getdegreecodes",
type: "get",
contentType: "application/text",
data: { id: 1 }
}).done(function (data) {
if (data.length > 0) {
for (i = 0; i < data.length; i++) {
viewEduModel.degreeCodes.push(data[i]);
}
}
});
i need to use JsonConvert.SerializeObject since i am caching it as a JSon
in my redis cache server using booksleeve that way I do not need to
re serialize and read from db every time. how do i avoid web api controller sending
Quotes and backslashes? i could simply return IEnumerable and
let Web Api do the JSOn serialization but i need to cache it on redis
side
You could something like below:
[HttpGet]
public HttpResponseMessage GetDegreeCodes(int id)
{
StringContent sc = new StringContent("Your JSON content from Redis here");
sc.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage resp = new HttpResponseMessage();
resp.Content = sc;
return resp;
}
by using this you can call your webapi through code.
using (var client = new WebClient()) //WebClient
{
string mystring = "";
client.Headers.Add("Content-Type:application/json"); //Content-Type
client.Headers.Add("Accept:application/json");
var dataa = Encoding.UTF8.GetBytes("{\"Username\":\"sdfsd\"}");
byte[] a = client.UploadData("your API url", "POST",dataa);
myString = Encoding.UTF8.GetString(a);
}
I'm trying to test web service calls using an ASP.NET page that creates a form with username and password fields and a "Submit" button. (Both jQuery and the .js file I'm using are included in script tags in the head element.)
The "Submit" button calls a function created in the C# code behind file that makes a call to a separate JavaScript file.
protected void mSubmit_Click(object sender, EventArgs eventArgs)
{
String authenticate = String.Format("Authentication(\"{0}\",\"{1}\");", this.mUsername.Text,this.mPassword.Text);
Page.ClientScript.RegisterStartupScript(this.GetType(), "ClientScript", authenticate, true);
}
The JavaScript function, Authenticate, makes web service call, using jQuery and Ajax, to a different server, sending JSON parameters and expecting back JSON in response.
function Authentication(uname, pwd) {
//gets search parameters and puts them in json format
var params = '{"Header":{"AuthToken":null,"ProductID":"NOR","SessToken":null,"Version":1},"ReturnAuthentication":true,"Password":"' + pwd + '","Username":"' + uname + '",ā€¯ReturnCredentialsā€¯:false }';
var xmlhttp = $.ajax({
async: false,
type: "POST",
url: 'https://myHost.com/V1/Identity/Authenticate',
data: params,
contentType: 'application/json'
});
alert(xmlhttp.statusText);
alert(xmlhttp.responseText);
return;
}
However, because the web service I'm calling is on a different server than the ASP.NET, C# and JavaScript files, I'm not getting a statusText or responseText alert.
Somehow, nothing is being sent to the web service and I'm not getting anything back, not even an error. I tried putting a function in the beforeSend attribute, but that didn't fire. Is there a special way I need to handle calling an off-server web service?
UPDATE!
At the advice of jjnguy, Janie and Nathan, I'm now trying a server side call to the web service using HttpWebRequest. Using some of jjnguy's code as well as code from this question, I've come up with this.
public static void Authenticate(string pwd, string uname)
{
string ret = null;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://myhost.com/V1/Identity/Authenticate");
request.ContentType = "application/json";
request.Method = "POST";
string data = "{\"Header\":{\"AuthToken\":null,\"ProductID\":\"NOR\",\"SessToken\":null,\"Version\":1},\"ReturnAuthentication\":true,\"Password\":\"" + pwd + "\",\"Username\":\"" + uname + "\",\"ReturnCredentials\":false }'";
byte[] byteData = UTF8Encoding.UTF8.GetBytes(data);
request.ContentLength = byteData.Length;
using (Stream postStream = request.GetRequestStream())
{
postStream.Write(byteData, 0, byteData.Length);
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (response)
{
// Get the response stream
StreamReader reader = new StreamReader(response.GetResponseStream());
// Console application output
ret = reader.ReadToEnd();
}
Console.WriteLine(ret);
}
However, I'm getting a (400) Bad Request error from the remote server when I try to get the response from my HttpWebRequest. The value of the Response property of the exception says {System.Net.HttpWebResponse} and the value of the Status property is ProtocolError. I'm pretty sure this is because the URL is using HTTP SSL protocol. What can I do to get around that, other than having the ASP.NET page URL start with HTTPS (not an option)?
Turns out the code that I posted in my update was correct, I just had a typo and one setting incorrect in the data string.
string data = "{\"Header\":{\"AuthToken\":null,\"ProductID\":\"NOR\",\"SessToken\":null,\"Version\":1},\"ReturnAuthentication\":true,\"Password\":\"" + pwd + "\",\"Username\":\"" + uname + "\",\"ReturnCredentials\":true}";
For simplicity's sake, why don't you write the call to the webservice in C# on the Server Side?
You have the same abilities to send requests and get responses in C# as you do with Javascript.
Here is a crack at your function in C#:
public static string Authenticate(string pwd, string uname)
{
HttpWebRequest requestFile = (HttpWebRequest)WebRequest.Create("https://myHost.com/V1/Identity/Authenticate");
requestFile.ContentType = "application/json";
requestFile.Method = "POST";
StreamWriter postBody = new StreamWriter(requestFile.GetRequestStream())
using (postBody) {
postBody.Write("{\"Header\":{\"AuthToken\":null,\"ProductID\":\"NOR\",\"SessToken\":null,\"Version\":1},\"ReturnAuthentication\":true,\"Password\":\"" + pwd + "\",\"Username\":\"" + uname + "\",\"ReturnCredentials\":false }'");
}
HttpWebResponse serverResponse = (HttpWebResponse)requestFile.GetResponse();
if (HttpStatusCode.OK != serverResponse.StatusCode)
throw new Exception("Url request failed. Connection to the server inturrupted");
StreamReader responseStream = new StreamReader(serverResponse.GetResponseStream());
string ret = null;
using (responseStream) {
ret = responseStream.ReadLine();
}
return ret;
}
Disclaimer This has not been tested.
Instead of using the client script to make the request from the server; use server side code to make the request
EDIT to expand answer:
From your web project in visual studio, click add web reference, and point to the service you were originally accessing via your client script: (I believe it was 'https://myHost.com/V1/Identity/Authenticate)
You can now talk to the service using c# code instead of js (and pass in the users provided credentials.)
Also, since the request against the service is coming from a server, rather than a browser; you bypass the cross-domain restrictions that apply.
FURTHER EDIT to show additional technique:
If you don't like the idea of using Visual Studio to generate a service proxy for you, then you can handcraft the request yourself using WebClient or HttpRequest
WebClient:
http://msdn.microsoft.com/en-us/library/system.net.webclient(VS.80).aspx
HttpWebRequest:
http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest(VS.80).aspx
Seems like you're running into the same origin policy
http://en.wikipedia.org/wiki/Same_origin_policy
I believe there are ways to circumvent it, but I think the other posters are right. On the server, write methods that use a HttpWebRequest to call the web service, and then use JavaScriptSerializer to parse out the JSON. I spent most of the afternoon researching this cause I'll have to write something similar myself.
>>>> Nathan
P.S. I like #Janie's plan better... Can you do that with a web service that returns JSON as well as one that would pass back XML?