I am developing my first Dashboard Widget and trying to call a webservice. But I keep on getting XMLHTTPRequest status 0.
Following is the code
var soapHeader = '<?xml version=\"1.0\" encoding=\"utf-8\"?>\n'
+'<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n'
+'<soap:Body>\n'
+'<UsersOnline xmlns=\"http://wsSync\" />\n'
+'</soap:Body>\n'
+'</soap:Envelope>';
var destinationURI = 'http://ws.storan.com/webservicesformraiphone/wssync.asmx';
var actionURI = 'http://wsSync/UsersOnline';
function callWebService() {
try{
SOAPObject = new XMLHttpRequest();
SOAPObject.onreadystatechange = function() {fetchEnd(SOAPObject);}
SOAPObject.open('POST', destinationURI, true);
SOAPObject.setRequestHeader('SOAPAction', actionURI);
SOAPObject.setRequestHeader('Content-Length', soapHeader.length);
SOAPObject.setRequestHeader('Content-Type', 'text/xml; charset=utf-8');
var requestBody = soapHeader;
SOAPObject.send(requestBody);
} catch (E)
{
alert('callWebService exception: ' + E);
}
}
function fetchEnd(obj)
{
if(obj.readyState == 4){
if(obj.status==200)
{
alert("Yahooooooo");
}
}
}
Any ideas?
have you added
<key>AllowNetworkAccess</key>
<true/>
to the plist? if not the outside world will not be available.
You may also encounter problems if trying to cross domains.
Related
I have a asp.net WebAPI service for user login that takes an email and password. The api method has the following signature. LoginDto has two fileds, Email and password.
public async Task<IActionResult> Login(LoginDto dto)
Once the user is authenticated, WebAPI returns an object that has token and Id:
return Ok(new { Token = GenerateJwtTokenFromClaims(claims), Id=user.Id });
On the client side (Blazor app), I used nswag command line tool by running nswag run and it "successfully" generated the Service and Contract files. Everything complies. nswag generated code is pasted below.
When I want to use the login nswag Service, I have the following method (I also have an overloaded method with CancellationToken but I only use this method):
public System.Threading.Tasks.Task Login2Async(LoginDto body)
{
return Login2Async(body, System.Threading.CancellationToken.None);
}
The question that I have is that how do I get the response out of the nswag-generated-code that the WebAPI login sent back to the client? When I try to assign a var to the method, I get Cannot assign void to an implicitly-typed variable which makes sense since I don't see a return type. I also don't see any logic in the nswag generated service file to return the response to the caller. How do I get the response back from the nswag generated API call? Is there an option I have to set in nswag run to get a response object back? Thanks in advance.
public async System.Threading.Tasks.Task Login2Async(LoginDto body, System.Threading.CancellationToken cancellationToken)
{
var urlBuilder_ = new System.Text.StringBuilder();
urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/api/Account/Login");
var client_ = _httpClient;
var disposeClient_ = false;
try
{
using (var request_ = new System.Net.Http.HttpRequestMessage())
{
var content_ = new System.Net.Http.StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(body, _settings.Value));
content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json");
request_.Content = content_;
request_.Method = new System.Net.Http.HttpMethod("POST");
PrepareRequest(client_, request_, urlBuilder_);
var url_ = urlBuilder_.ToString();
request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
PrepareRequest(client_, request_, url_);
var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
var disposeResponse_ = true;
try
{
var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value);
if (response_.Content != null && response_.Content.Headers != null)
{
foreach (var item_ in response_.Content.Headers)
headers_[item_.Key] = item_.Value;
}
ProcessResponse(client_, response_);
var status_ = (int)response_.StatusCode;
if (status_ == 200)
{
return;
}
else
if (status_ == 400)
{
var objectResponse_ = await ReadObjectResponseAsync<ProblemDetails>(response_, headers_).ConfigureAwait(false);
throw new ApiException<ProblemDetails>("Bad Request", status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
}
else
{
var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
}
}
finally
{
if (disposeResponse_)
response_.Dispose();
}
}
}
finally
{
if (disposeClient_)
client_.Dispose();
}
}
Big thanks to the NSwag team, the issue is resolved. I was returning anonymous object from the WebAPI method. The correct way to do is the following. Notice that IActionResult was changed to ActionResult passing a concrete object to return to the caller.
public async Task<ActionResult<LoginDtoResponse>> Login(LoginDto dto)
then returning
return Ok(new LoginDtoResponse { Token = GenerateJwtTokenFromClaims(claims), Id=user.Id });
After that I did that, the following code was generated:
if (status_ == 200)
{
var objectResponse_ = await ReadObjectResponseAsync<LoginDtoResponse>(response_, headers_).ConfigureAwait(false);
return objectResponse_.Object;
}
help me, i couldn't get the cookies from an httprequest, i tried the plugins.settings, i tried the pcl share too, am in this problem for a month
public async Task<bool> PostAsync(AuthUser user)
{
var CookieContainer = new CookieContainer();
var handler = new HttpClientHandler() { CookieContainer =
CookieContainer };
var _client = new HttpClient(handler);
IEnumerable<string> cookieStrings = null;
//var httpClient = new HttpClient();
_client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
var json = JsonConvert.SerializeObject(user);
HttpContent httpContent = new StringContent(json);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
try
{
string url = WebServiceUrl + "j_spring_security_check?j_username=" + user.j_username +"&j_password=" + user.j_password + "&ajax=true";
HttpResponseMessage result = await _client.PostAsync(url, httpContent);
IEnumerable<string> cookies;
if (result.Headers.TryGetValues("set-cookie", out cookies))
{
foreach (var c in cookies)
{
await App.Current.MainPage.DisplayAlert("Cookie", c , "OK");
}
}
if (result.IsSuccessStatusCode)
{
using (var responsecontent = result.Content)
{
string resultString = responsecontent.ReadAsStringAsync().Result;
var response = JsonConvert.DeserializeObject<AuthUser>(resultString);
if (response.error != null)
{
await App.Current.MainPage.DisplayAlert("Error", response.result.error, "OK");
return false;
}
else if (response.result.success.Equals("1"))
{
App.Current.MainPage = new NavigationPage(new TimelineMenuPage(response.result.user_id.ToString(), response.result.token));
return true;
}
}
}
return result.IsSuccessStatusCode;
}
catch (Exception e)
{
await App.Current.MainPage.DisplayAlert("Alert", e.ToString(), "OK");
throw;
}
}
when debugging it skips this part :
if (result.Headers.TryGetValues("set-cookie", out cookies))
{
foreach (var c in cookies)
{
await App.Current.MainPage.DisplayAlert("Cookie", c , "OK");
}
}
**and then i get in CookieContainer count=0 **
Since you are already using a CookieContainer, and you will know the Uri you are getting them from, why don't you just get the Cookies directly from the Container, instead of a set-cookie command, that you will then have to parse.
cookieContainer.GetCookies(new Uri("mydomain.com"));
After your HttpRequest, it will automatically put them into the CookieContainer.
I want to consume ASMX service in my titanium project, for that I have used the Kitchen Sink Nook project and it works well for the currency convertor asmx webservice and it doesn't have the authentication header.
But I have authentication header for my client webservice, I have tested the below webservice in SOAP UI and it works perfect. But I don't get the solution for Titanium SOAP Call.
Calling_class.js
Titanium.include('suds.js');
var window = Ti.UI.createWindow({
title:"Web Service Test",
backgroundColor:"#FFF",
exitOnClose:true
});
var label = Ti.UI.createLabel({
top: 10,
left: 10,
width: 'auto',
height: 'auto',
text: 'Contacting currency rates web service...'
});
var bouton = Titanium.UI.createButton({
title:"Test",
bottom:20,
height:120,
width:135,
});
window.add(label);
var url = "http://192.168.15.45:8082/CrmAppointments.asmx";
var callparams = {
AppointmentNumber: 'APP-00000003-H042S5',
UserId: '4'
};
var suds = new SudsClient({
endpoint: url,
targetNamespace: 'http://tempuri.org'
});
bouton.addEventListener("click", function(e){
try {
suds.invoke('BookAppointmentFromWCF', callparams, function(xmlDoc) {
console.log('response : '+ this.responseText);
var results = xmlDoc.documentElement.getElementsByTagName('BookAppointmentFromWCF');
if (results && results.length>0) {
var result = results.item(0);
label.text = '1 Euro buys you ' + results.item(0).text + ' U.S. Dollars.';
} else {
label.text = 'Oops, could not determine result of SOAP call.';
}
});
} catch(e) {
Ti.API.error('Error: ' + e);
}
});
window.add(bouton);
window.open();
suds.js
/**
* Suds: A Lightweight JavaScript SOAP Client
* Copyright: 2009 Kevin Whinnery (http://www.kevinwhinnery.com)
* License: http://www.apache.org/licenses/LICENSE-2.0.html
* Source: http://github.com/kwhinnery/Suds
*/
function SudsClient(_options) {
function isBrowserEnvironment() {
try {
if (window && window.navigator) {
return true;
} else {
return false;
}
} catch(e) {
return false;
}
}
function isAppceleratorTitanium() {
try {
if (Titanium) {
return true;
} else {
return false;
}
} catch(e) {
return false;
}
}
//A generic extend function - thanks MooTools
function extend(original, extended) {
for (var key in (extended || {})) {
if (original.hasOwnProperty(key)) {
original[key] = extended[key];
}
}
return original;
}
//Check if an object is an array
function isArray(obj) {
return Object.prototype.toString.call(obj) == '[object Array]';
}
//Grab an XMLHTTPRequest Object
function getXHR() {
var xhr;
if (isBrowserEnvironment()) {
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}
else {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
}
else if (isAppceleratorTitanium()) {
xhr = Titanium.Network.createHTTPClient();
}
return xhr;
}
//Parse a string and create an XML DOM object
function xmlDomFromString(_xml) {
var xmlDoc = null;
if (isBrowserEnvironment()) {
if (window.DOMParser) {
parser = new DOMParser();
xmlDoc = parser.parseFromString(_xml,"text/xml");
}
else {
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = "false";
xmlDoc.loadXML(_xml);
}
}
else if (isAppceleratorTitanium()) {
xmlDoc = Titanium.XML.parseString(_xml);
}
return xmlDoc;
}
// Convert a JavaScript object to an XML string - takes either an
function convertToXml(_obj, namespacePrefix) {
var xml = '';
if (isArray(_obj)) {
for (var i = 0; i < _obj.length; i++) {
xml += convertToXml(_obj[i], namespacePrefix);
}
} else {
//For now assuming we either have an array or an object graph
for (var key in _obj) {
if (namespacePrefix && namespacePrefix.length) {
xml += '<' + namespacePrefix + ':' + key + '>';
} else {
xml += '<'+key+'>';
}
if (isArray(_obj[key]) || (typeof _obj[key] == 'object' && _obj[key] != null)) {
xml += convertToXml(_obj[key]);
}
else {
xml += _obj[key];
}
if (namespacePrefix && namespacePrefix.length) {
xml += '</' + namespacePrefix + ':' + key + '>';
} else {
xml += '</'+key+'>';
}
}
}
return xml;
}
// Client Configuration
var config = extend({
endpoint:'http://localhost',
targetNamespace: 'http://localhost',
envelopeBegin: '<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:ns0="PLACEHOLDER" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header><ns0:Authentication><ns0:Username>Infrab</ns0:Username><ns0:Password>ZxH35oCeXnA</ns0:Password></ns0:Authentication></soap:Header><soap:Body>',
envelopeEnd: '</soap:Body></soap:Envelope>'
},_options);
// Invoke a web service
this.invoke = function(_soapAction,_body,_callback) {
//Build request body
var body = _body;
//Allow straight string input for XML body - if not, build from object
if (typeof body !== 'string') {
body = '<ns0:'+_soapAction+'>';
body += convertToXml(_body, 'ns0');
body += '</ns0:'+_soapAction+'>';
}
var ebegin = config.envelopeBegin;
config.envelopeBegin = ebegin.replace('PLACEHOLDER', config.targetNamespace);
//Build Soapaction header - if no trailing slash in namespace, need to splice one in for soap action
var soapAction = '';
if (config.targetNamespace.lastIndexOf('/') != config.targetNamespace.length - 1) {
soapAction = config.targetNamespace+'/'+_soapAction;
}
else {
soapAction = config.targetNamespace+_soapAction;
}
//POST XML document to service endpoint
var xhr = getXHR();
xhr.onload = function() {
_callback.call(this, xmlDomFromString(this.responseText));
};
xhr.open('POST',config.endpoint);
xhr.setRequestHeader('Content-Type', 'text/xml');
xhr.setRequestHeader('SOAPAction', soapAction);
xhr.send(config.envelopeBegin+body+config.envelopeEnd);
console.log(config.envelopeBegin+body+config.envelopeEnd);
};
}
The main methods in this code is the var config = extend({ which is the client configuration for SOAP xml. When I execute I get this output:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>Server was unable to process request. ---> Object reference not set to an instance of an object.</faultstring>
<detail />
</soap:Fault>
</soap:Body>
</soap:Envelope>
I've checked SOAP UI for testing the webservice by removing the authentication header, and it gives me the same exact error like in Titanium.
My question is how would I can pass the Authentication header with username and password values?
I'm using the free version of Xamarin Studio to do some test. In aprticular I'm trying to connect to web Service but I receive the ConnectFailure (Network unreachable) when I debug the application.
This is my code
public class MainActivity : Activity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
// Our code will go here
// Get our UI controls from the loaded layout
EditText phoneNumberText = FindViewById<EditText>(Resource.Id.editText1);
Button translateButton = FindViewById<Button>(Resource.Id.button1);
Button callButton = FindViewById<Button>(Resource.Id.button2);
// Disable the "Call" button
callButton.Enabled = false;
// Add code to translate number
string translatedNumber = string.Empty;
var rxcui = "198440";
var request = HttpWebRequest.Create(string.Format(#"http://rxnav.nlm.nih.gov/REST/RxTerms/rxcui/{0}/allinfo", rxcui));
request.ContentType = "application/json";
request.Method = "GET";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
if (response.StatusCode != HttpStatusCode.OK)
Console.Out.WriteLine("Error fetching data. Server returned status code: {0}", response.StatusCode);
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
var content = reader.ReadToEnd();
if(string.IsNullOrWhiteSpace(content)) {
Console.Out.WriteLine("Response contained empty body...");
}
else {
Console.Out.WriteLine("Response Body: \r\n {0}", content);
}
//Assert.NotNull(content);
}
}
}
}
}
I don't understand if this is an error caused by the free version or it's me.
Please help me.
Thanks
This must be close but I can't figure out what's causing the error.
In my Titanium app, I have a Webview with a canvas element and this code:
function getImageData() {
return canvas.toDataURL('image/png');
}
I am moving that data to the Titanium app like this:
var imageBase64data = webview.evalJS('getImageData()')
The data looks good starting with "data:image/png;base64,"...
Then in Titanium, I have a logged-in drupal session and call this function:
function uploadImage(imageBase64data, callback) {
var url = REST_PATH + "file.json";
var file = {
filename: utils.createRandomString() + ".png",
file: imageBase64data
// uid: Titanium.App.Properties.getString("userUid"),
// filesize: ""+Titanium.Utils.base64decode(imageBase64data).length,
};
var xhr = Titanium.Network.createHTTPClient({timeout: 30000});
xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
var authString = Titanium.App.Properties.getString("userSessionName")+'='+Titanium.App.Properties.getString("userSessionId");
xhr.setRequestHeader("Cookie", authString);
xhr.onload = function() {
if(xhr.status == 200) {
var response = xhr.responseText;
callback(response);
}
};
xhr.onerror = function(e) {
alert("There was an error: " + e.error);
Ti.API.info(JSON.stringify(this));
};
xhr.open("POST", url);
xhr.send(file);
}
xhr.onerror is being called with e.error = "undefined"
The trace looks like this:
{
"responseData":{},
"readyState":4,
"connected":true,"UNSENT":0,"DONE":4,"HEADERS_RECEIVED":2,"OPENED":1,"LOADING":3,
"responseText":null,"status":406
}
I think authentication is working because I was previously getting a "need authentication" error until I added the Cookie header.
That was with the installation provided by Drupanium. I just did a fresh Drupal and fresh Services 3 install and my file is uploading nicely.