swift 3, wcf service - wcf

I am trying to use an existing WCF service in an IOS APP coded in swift 3.
The problem seem to be in the format of the envelope.
The service is on line and work well (is already used by an android app)
URL of the service: www.esmnovara.it\FitnessManagerService.svc
This is the request, seen from a WCF test client:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/FitnessManagerIService/Login</Action>
</s:Header>
<s:Body>
<Login xmlns="http://tempuri.org/">
<NomeUtente></NomeUtente>
<Password></Password>
</Login>
</s:Body>
</s:Envelope>
It must return this:
"
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body>
<LoginResponse xmlns="http://tempuri.org/">
<LoginResult>0|ERRORE GENERICO, RIVOLGERSI ALLA RECEPTION</LoginResult>
<NomeUtente a:nil="true" xmlns:a="http://www.w3.org/2001/XMLSchema-instance" />
<Password a:nil="true" xmlns:a="http://www.w3.org/2001/XMLSchema-instance" />
</LoginResponse>
</s:Body>
</s:Envelope>
"
This is the code of my IOS swift 3 app:
var soapMessage : String = ""
soapMessage += "<s:Envelope xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'>"
soapMessage += "<s:Header>"
soapMessage += "<Action s:mustUnderstand='1' xmlns='http://schemas.microsoft.com/ws/2005/05/addressing/none'>http://tempuri.org/FitnessManagerIService/Login</Action>"
soapMessage += "</s:Header>"
soapMessage += "<s:Body>"
soapMessage += "<Login xmlns='http://tempuri.org/FitnessManagerIService/Login'>"
soapMessage += "<NomeUtente></NomeUtente>"
soapMessage += "<Password></Password>"
soapMessage += "</Login>"
soapMessage += "</s:Body>"
soapMessage += "</s:Envelope>'"
let urlString = "http://www.esmnovara.it/FitnessManagerService.svc"
let url = URL(string: urlString)
let theRequest = NSMutableURLRequest(url: url!)
let msgLength = soapMessage.characters.count
theRequest.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
theRequest.addValue(String(msgLength), forHTTPHeaderField: "Content-Length")
theRequest.httpMethod = "POST"
theRequest.httpBody = soapMessage.data(using: String.Encoding.utf8, allowLossyConversion: false) // or false
let connection = NSURLConnection(request: theRequest as URLRequest, delegate: self, startImmediately: true)
connection!.start()
if (connection != nil) {
var mutableData : Void = NSMutableData.initialize()
//debugPrint(mutableData)
}
And this is what I get:
"IIS 8.5 Detailed Error - 400.0 - Bad Request"
"HTTP Error 400.0 - Bad Request"
"Bad Request"
"Detailed Error Information:"
"Module"
"IsapiModule"
"Notification"
"ExecuteRequestHandler"
"Handler"
"svc-ISAPI-4.0_32bit"
"Error Code"
"0x00000000"
"Requested URL"
"http://www.esmnovara.it:80/FitnessManagerService.svc"
"Physical Path"
"D:\\inetpub\\webs\\esmnovarait\\FitnessManagerService.svc"
"Logon Method"
"Anonymous"
"Logon User"
"Anonymous"
"Request Tracing Directory"
"D:\\LogFiles\\FailedReqLogFiles"
"More Information:"
" \n The request could not be understood by the server due to malformed syntax. \n "
"View more information "
"Microsoft Knowledge Base Articles:"
Can anyone help me?

I wrote a little playground script which seems to work:
import UIKit
import PlaygroundSupport
// Ignore the next line, it's just to avoid a annoying message in Playgrounds
URLCache.shared = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil)
// Service URL
let serviceUrl = URL(string: "http://www.esmnovara.it/FitnessManagerService.svc")
// Service request using the serviceURL
var serviceRequest = URLRequest(url: serviceUrl!)
// Set a couple of headers
serviceRequest.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
serviceRequest.addValue("http://tempuri.org/FitnessManagerIService/Login", forHTTPHeaderField: "SOAPAction")
// Set the http verb
serviceRequest.httpMethod = "POST"
// Soap message
let soapMessageAsText = "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body><Login xmlns=\"http://tempuri.org/\"><NomeUtente/><Password/></Login></s:Body></s:Envelope>"
// Enconded as data
let soapMessageAsData = soapMessageAsText.data(using: String.Encoding.utf8)
// Set message as data in the http body of the request
serviceRequest.httpBody = soapMessageAsData
// Call the service using URLSession
URLSession.shared.dataTask(with: serviceRequest) { (data, response, error) in
// Check for error
guard error == nil else {
print(error ?? "Unknown error")
return
}
// Display data as string
let dataAsString = String(data: data!, encoding: String.Encoding.utf8)
print(dataAsString)
}.resume()
// Ignore this line, it's neccesary so that playground waits
PlaygroundPage.current.needsIndefiniteExecution = true
Hope it works.

Related

The remote server returned an error: (500) Internal Server Error. - URL created by IBM ICN

I am creating a console application in C# to check if URL is up and running using HttpWebRequest.
Note that the URL is generated by IBM's ICN (IBM Content Navigator). It is NOT hosted using IIS.
I am receiving the below error while trying to get HttpWebResponse from my C# console application.
Message: "The remote server returned an error: (500) Internal Server Error."
Status: ProtocolError
Below code is not working:
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(myurl);
request.Credentials = CredentialCache.DefaultCredentials;
request.Method = "GET";
request.Accept = "text/plain";
request.ContentType = "text/plain;charset=UTF-8";
request.Headers.Add("Accept-Language", "en-US");
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (response != null && response.StatusCode == HttpStatusCode.OK)
{
//Do some operations
}
else
{
//Do some operations
}
}
Please let me know if additional info. is required.
Any help or suggestions to solve this issue are appreciated.
Thanks in advance.

Create a new calendar from CalDav API

I am trying to create a new calendar in my principal's home folder using SabreDav.
I couldn't find how to achieve this - is it even possible ?
UPDATE:
I found out about MKCALENDAR method, but the following returns an "abandoned" request error:
<C:mkcalendar xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav" xmlns:ical="http://apple.com/ns/ical/" >"
<D:set>
<D:prop>
<D:displayname>cal Display Name</D:displayname>
<ical:calendar-color>cal Color</ical:calendar-color>
</D:prop>
</D:set>
</C:mkcalendar>
Sending it with a HttpWebRequest fails with a canceled request messgage...
Thanks in advance!
UPDATE 2:
Some more details:
HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create("http://my.sabredavcalendar.srv/calendarserver.php/calendars/admin/my_new_calendar/");
Request.Method = "MKCALENDAR";
Request..Credentials = new NetworkCredentials("usr", "pwd");
Request.ContentType = "application/xml";
string body = "<C:mkcalendar [.....] </C:mkcalendar>";
Request.ContentLength = body.Length;
// ---
// The using block throws an error...
using (Stream reqStream = Request.GetRequestStream()) {
byte[] encodedBody = Encoding.UTF8.GetBytes(body);
reqStream.Write(encodedBody, 0, encodedBody.Length);
reqStream.Close();
}
Response = (HttpWebResponse)Request.GetResponse();
The error message I get is
The request was aborted: The request was canceled
On the server side, here is the access log:
192.168.1.200 - - [06/Jul/2015:09:51:48 +0200] "MKCALENDAR /calendarserver.php/calendars/admin/my_new_calendar/ HTTP/1.1" 400 25 "-" "-"
The error log is empty... so it seems I get a "bad request" response which is not caught when preparing the request?!
UPDATE 3: the body contains special characters as "éàê..." which is why the contentlength part was wrong !
I take hnh's comment as an answer: the problem was indeed the Request.ContentLength = body.Length.
Corrected code is:
Request.ContentLength = Encoding.UTF8.GetByteCount(body);

Get url shortened with Google API, AFNetworking in Swift

In Google documentation (https://developers.google.com/url-shortener/v1/getting_started), to use Google URL shortener, I should make a request as below:
POST https://www.googleapis.com/urlshortener/v1/url
Content-Type: application/json
{"longUrl": "http://www.google.com/"}
They also stated that I will have to authenticate:
"Every request your application sends to the Google URL Shortener API
needs to identify your application to Google. There are two ways to
identify your application: using an OAuth 2.0 token (which also
authorizes the request) and/or using the application's API key."
I chose public API key as a method to authenticate: I create a public key for my iOS app. Then I use the following code to POST (AFNetworking, using Swift):
func getShortURL(longURL: String){
let manager = AFHTTPRequestOperationManager()
let params = [
"longUrl": longURL
]
manager.POST("https://www.googleapis.com/urlshortener/v1/url?key={my_key_inserted}", parameters: params, success: {
(operation: AFHTTPRequestOperation!,responseObject: AnyObject!) in
println("JSON: " + responseObject.description)
},
failure: { (operation: AFHTTPRequestOperation!,error: NSError!) in
println("Error while requesting shortened: " + error.localizedDescription)
})
}
However, I got the log: Error while requesting shortened: Request failed: bad request (400).
Please tell me how to fix it.
What you are missing is setting the right AFNetworking serializer for this request.
Since the Google response is in JSON, you should use AFJSONRequestSerializer.
Add manager.requestSerializer = AFJSONRequestSerializer() like this:
let manager = AFHTTPRequestOperationManager()
manager.requestSerializer = AFJSONRequestSerializer()
let params = ["longUrl": "MYURL"]
manager.POST("https://www.googleapis.com/urlshortener/v1/url?key=MYKEY", parameters: params, success: {(operation: AFHTTPRequestOperation!,responseObject: AnyObject!) in
println("JSON: " + responseObject.description)
}, failure: { (operation: AFHTTPRequestOperation!,error: NSError!) in
println("Error while requesting shortened: " + error.localizedDescription)
})

Consuming Analytics from Parse.com in an IOS App

I am generating custom Parse Analytic events in the background cloud code based on Save events from my ios app . I can also see it in the Analytic panel on Parse.com.
How do I access it in my ios app ?
I get the following error when I try
Error Domain=com.alamofire.error.serialization.response Code=-1011 "Request failed: bad request (400)" UserInfo=0x7a9697e0 {com.alamofire.serialization.response.error.response=<NSHTTPURLResponse: 0x7a956d00> { URL: https://api.parse.com/1/events/commentsAnalytics } { status code: 400, headers {
"Access-Control-Allow-Methods" = "*";
"Access-Control-Allow-Origin" = "*";
Connection = "keep-alive";
"Content-Length" = 36;
"Content-Type" = "application/json; charset=utf-8";
Date = "Fri, 23 Jan 2015 06:43:38 GMT";
Server = "nginx/1.6.0";
"X-Parse-Platform" = G1;
"X-Runtime" = "0.007086";
} }, NSErrorFailingURLKey=https://api.parse.com/1/events/commentsAnalytics, NSLocalizedDescription=Request failed: bad request (400),
Check if you are adding the keys (X-Parse-Application-Id and X-Parse-REST-API-Key) of your application in the request header. Here is an example with Alamofire.
Example
var request = NSMutableURLRequest(URL: NSURL(string: "https://api.parse.com/1/events/Buy")!)
request.HTTPMethod = "POST"
request.setValue("<APPLICATION-KEY>", forHTTPHeaderField: "X-Parse-Application-Id")
request.setValue("<REST-KEY>", forHTTPHeaderField: "X-Parse-REST-API-Key")
var parameter: NSDictionary = ["dimensions" :["product" : ["name" : "macpro", "price" : "350"]]]
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(parameter, options: nil, error: nil)
Alamofire.request(request).response { (request, response, result, error) -> Void in
// handle response
println("\(request) \t \(response) \t \(result) \t \(error) ")
}
Checking
to check the event, go to your application panel in the parse ...
...click "Custom Breakdown"...
and customize your chart.

Post SOAP Envelope to WCF service

I have the following SOAP message that i want to post it to my WCF Service and get response.
"<s:Envelope xmlns:a=\"http://www.w3.org/2005/08/addressing\" xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\">\r\n <s:Header>\r\n <a:Action s:mustUnderstand=\"1\">http://schemas.devleap.com/OrderService/IOrderService/InsertOrder</a:Action>\r\n <a:MessageID>urn:uuid:4cb619b7-365b-4108-880f-b302029d03c2</a:MessageID>\r\n <a:ReplyTo>\r\n <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>\r\n </a:ReplyTo>\r\n </s:Header>\r\n <s:Body>\r\n <InsertOrder xmlns=\"http://schemas.devleap.com/OrderService\">\r\n <order xmlns:d4p1=\"http://schemas.devleap.com/OrderService/Order\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n <d4p1:IdCustomer>2</d4p1:IdCustomer>\r\n <d4p1:IdOrder>46</d4p1:IdOrder>\r\n <d4p1:OrderItems xmlns:d5p1=\"http://schemas.devleap.com/OrderService/OrderItems\" xmlns:d5p2=\"http://schemas.devleap.com/OrderService/OrderItem\">\r\n <d5p1:OrderItem>\r\n <d5p2:IdProduct>P01</d5p2:IdProduct>\r\n <d5p2:Quantity>5</d5p2:Quantity>\r\n <d5p2:EuroPrice>20</d5p2:EuroPrice>\r\n </d5p1:OrderItem>\r\n <d5p1:OrderItem>\r\n <d5p2:IdProduct>P01</d5p2:IdProduct>\r\n <d5p2:Quantity>5</d5p2:Quantity>\r\n <d5p2:EuroPrice>20</d5p2:EuroPrice>\r\n </d5p1:OrderItem>\r\n </d4p1:OrderItems>\r\n </order>\r\n </InsertOrder>\r\n </s:Body>\r\n</s:Envelope>"
How can i post this SOAP to the WCF service?
I tried this but i get "The remote server returned an error: (500) Internal Server Error." exception.
using (var client = new WebClient())
{
client.Headers.Add("Content-Type", "application/soap+xml; charset=utf-8");
var response = client.UploadString("http://localhost:8000/OrderService", data);
}
If i remove the header from Envelope and add:
client.Headers.Add("Content-Type", "application/soap+xml; charset=utf-8");
client.Headers.Add("SOAPAction", "\"http://schemas.devleap.com/OrderService/IOrderService/InsertOrder\"");
i get the same error.
If i put
client.Headers.Add("Content-Type", "text/xml; charset=utf-8");
i get exception that server expects "application/soap+xml; charset=utf-8".
If someone knows how to call it right please help.
Thank you,
Adrya
After more digging i managed to post the SOAP to the service.
Here is code:
WebClient myWebClient = new WebClient();
myWebClient.Headers.Add("Content-Type", "application/soap+xml; charset=utf-8");
byte[] byteArray = Encoding.ASCII.GetBytes(postData);
byte[] responseArray = myWebClient.UploadData("http://localhost:8000/OrderService", "POST", byteArray);
Console.WriteLine("\nResponse received was {0}", Encoding.ASCII.GetString(responseArray));
Console.ReadKey();