2

I used swiftyJSON in my project when i use php created API it works fine in project but when i used C# Created API in my project it gives null in response. I Searched on net and I got you can use it in your project.

Here is code

let url: NSURL = NSURL(string: "http://compareit.unitechecom.com/AndroidClass/API/login.aspx?Mobile_Number=8523697888&Password=123")! // Enter URL Here

        let request:NSMutableURLRequest = NSMutableURLRequest(url:url as URL)
        //let bodyData = "employeeVerify & employeeID=\(empID)"// Pass parameter Form Here.
        //  print(bodyData)
        request.httpMethod = "GET"
        //request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding);

        print(request)
        let task = URLSession.shared.dataTask(with: request as URLRequest)
        {

            data, response, error in

            if error != nil
            {

                print("error=\(error)")
                return
            }
            // You can print out response object
            print("response = \(response)")


            do {
                let json = JSON(data: data!)

                print(json)

            }
              }

        task.resume()

what is the solution for this.? Can i use it.?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Dhruv Khatri
  • 803
  • 6
  • 15

1 Answers1

2

In answer to your question, yes, you can call your C#, ASP.NET web service from Swift. That's the beauty of web services, that the respective technologies used in the client and server code are entirely independent of each other, as long as the requests and responses are properly formatted.

Having said that, there are a couple of issues here:

  1. If response (the URLResponse) is nil, then error will not be nil. Look at what the error is and act accordingly.

    For example, you would get an error if you didn't update your Info.plist to accept insecure requests (i.e. those without https://). But you can add the following entry to your plist:

    https://www.dropbox.com/s/2q0r8nhx8lxr6dm/Screenshot%202017-01-01%2017.45.37.png?dl=0

  2. Having said that, I suspect that the network response may not have failed (i.e. the response, the URLResponse object, itself, was not nil), but rather the JSON parsing failed, but that you didn't capture the JSON parsing errors.

    Ironically for a library called SwiftyJSON, the way it captures errors is uniquely unswifty. To capture errors, you have to call the JSON() initializer with the error parameter supplied. Thus, in the current version of SwiftyJSON, you would do something like:

    func performGetRequest(completionHandler: @escaping (JSON?, Error?) -> Void) {
        let url = URL(string: "http://compareit.unitechecom.com/AndroidClass/API/login.aspx?Mobile_Number=8523697888&Password=123")!
    
        var request = URLRequest(url: url)
        request.httpMethod = "GET"
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.setValue("application/json", forHTTPHeaderField: "Accept")
    
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            guard let data = data, error == nil else {
                completionHandler(nil, error)
                return
            }
    
            var error: NSError?
            let json = JSON(data: data, options: [], error: &error)
            completionHandler(json, error)
        }
    
        task.resume()
    }
    

    and then call it like so:

    performGetRequest() { json, error in
        guard let json = json, error == nil else {
            print("error = \(error)")
            return
        }
    
        print("\(json)")
    }
    

    If you do that, you'll see it report:

    error = Optional(Error Domain=NSCocoaErrorDomain Code=3840 "Garbage at end." UserInfo={NSDebugDescription=Garbage at end.})

    Looking at the contents of the data returned by your web service, the problem is apparent:

    [{"success":"1","Id":"5","FirstName":"admin","LastName":"admin","Email":"admin@gmail.com","Password":"123","Mobile_Number":"8523697888"}]
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head><title>
    
    </title></head>
    <body>
        <form method="post" action="./login.aspx" id="form1">
    <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="dLzeSuX8RwkzsXsmp+fPMkjIu69T9SDFeB24ER3qTQYwmIJB0b8hk32gWHwKrHiE2deVYOcUhwor5igxXXPwUh/uQ+FoE26gCWjolkMFgpg=" />
    
    <input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="45AB9188" />
        <div>
    
        </div>
        </form>
    </body>
    </html>
    

    As you can see, your web service is returning not only the JSON, but the HTML, too. You need to fix your web service to return the JSON only.


Having said all of that, there are a few more, largely unrelated observations:

  1. As shown in my example above, a well-formed request will often specify certain headers, namely Content-Type (to tell web service how you constructed your request) and Accept (to tell web service in what form you expect the response body). These aren't technically required, but (a) it's best practice to do so; and (b) depending upon how you wrote your web service, it might require it. It's not true in this case, but when writing a C# ASP.NET web API, it often can default to sending XML responses unless the client request explicitly requests JSON in the Accept header.

  2. Also notice that in my above example, I'm not using either NSURL, NSURLRequest, or NSMutableURLRequest. I'm using URL and URLRequest directly.

  3. Note, it is not good practice to send passwords in a URL. That's not as as secure as one might like. You'd want to put it in the body of the request, not the URL. Thus, you'd probably want to use POST request (and then change your server to use https rather than http):

    func performPostRequest(completionHandler: @escaping (JSON?, Error?) -> Void) {
        let url = URL(string: "http://compareit.unitechecom.com/AndroidClass/API/login.aspx")! // Enter URL Here
    
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.httpBody = "Mobile_Number=8523697888&Password=123".data(using: .utf8)
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.setValue("application/json", forHTTPHeaderField: "Accept")
    
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            guard let data = data, error == nil else {
                completionHandler(nil, error)
                return
            }
    
            var error: NSError?
            let json = JSON(data: data, options: [], error: &error)
            completionHandler(json, error)
        }
    
        task.resume()
    }
    
  4. It's also worth noting that while I haven't done it above, when preparing these requests, you really should be percent escaping these field values, in case they included any reserved characters. See https://stackoverflow.com/a/41092318/1271826 for an example.

    Also, in the httpBody that you've commented out, there are spaces in there, but in a proper x-www-form-urlencoded request, you should have no spaces.

As you can see, in addition to your server code problems, there are issues associated with your client code. To do all of that properly is non-trivial, and you might want to consider using a library like Alamofire that makes this a bit easier.

Community
  • 1
  • 1
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • So basically my API gives me wrong Answer. So anything that i have to suggest my API Creator.? @Rob – Dhruv Khatri Jan 03 '17 at 18:21
  • 1
    @DhruvKhatri - Yes, the API gives you the wrong answer, but you also wrote code that failed to detect/handle the error. Tell the API creator that the response is sending not only the expected JSON, but after that it is also sending the HTML. As soon as you show any experienced web service developer what the response looked like (the combined JSON/HTML at the end of my point 2, above), they'll likely be horrified and immediately know how to fix it. – Rob Jan 03 '17 at 18:25
  • 1
    BTW, I mentioned this awkward parsing error detection to the authors of SwiftyJSON and, to their credit, they not only recognize the issue, but it appears that they had a fix in the works. It's just not easy to fix this in a backward-compatible way, so they're likely deferring this change until the next major update to the library. Anyway, see our discussion in pull #[774](https://github.com/SwiftyJSON/SwiftyJSON/pull/774). You can still use the above to detect errors until something more swifty gets integrated in the library, though. Or just use `JSONSerialization` directly, if you want. – Rob Jan 03 '17 at 18:38