Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ASMX service return List<Object> #74

Closed
mrfoxbit opened this issue Sep 24, 2015 · 15 comments
Closed

ASMX service return List<Object> #74

mrfoxbit opened this issue Sep 24, 2015 · 15 comments
Labels

Comments

@mrfoxbit
Copy link

Hi,
Please help me.

My service return a List. If the list has multi value then everything is OK, but the list only has 1 element, it error: Could not cast value of type '__NSDictionaryM' (0x1249380) to 'NSArray' (0x124918c)

And, how to handle service method return a object, and service return bool value?

Thank you.

@priore
Copy link
Owner

priore commented Sep 24, 2015

From a SOAP message (XML) is hard to know if it return a single value or an array, this is possible only with processing the WSDL definition, but this takes a long processing time for each request, many many seconds for each request. The our framework only processes the response message, if it contains one element then it is considered as a dictionary or string, if it contains more consecutive elements, with the same identifier, it is considered as an array.

When you get the value through the key, and it can return a single value or multi values, we recommend using the method name isKindOfClass, like below:

    id obj = [responseDict objectForKey:@"my-key"]; // generic object
    if ([obj isKindOfClass:[NSDictionary class]]) {
        NSDictionary *dictValue = (NSDictionary*)obj;
        // TODO: your code here
    } else if ([obj isKindOfClass:[NSArray class]]) {
        NSArray *arrayValues = (NSArray*)obj;
        // TODO: your code here
    }

@mrfoxbit
Copy link
Author

Thank you for your help. I solved it.

I have a another problem.

My code is:
soap.setValue(objA, forKey: "obja")
soap.setValue(lstobjB, forKey: "lstobjb")

My service is:

publich bool TestService(objA obja, List lstobjb)
{
// Do something...
//
return true;
}

I can receive obja , but lstobjb.count is alway return 0

How can i fix it? And how receive bool value from service

Thank you

@priore
Copy link
Owner

priore commented Sep 24, 2015

try to set the property named responseHeader = true or/and retrievesAttributes = true

@mrfoxbit
Copy link
Author

I did, but It's not work

@priore
Copy link
Owner

priore commented Sep 24, 2015

You use Cocoapods ? I apologize, the last podspec had not been pushed to cocoapods, you try again now with pod update.

@mrfoxbit
Copy link
Author

I just download latest release (v.1.22).
If i set the property named responseHeader = true, i can get bool value return by valueForKeyPath.
But list object for service param still not work

@priore
Copy link
Owner

priore commented Sep 24, 2015

you can give us the URL of the service, and the method and the test credentials if required, so that we can test for you?

@mrfoxbit
Copy link
Author

I deleted my comment for security

@priore
Copy link
Owner

priore commented Sep 24, 2015

we not did understand the problem, but this is a sample code:

        // quotation
        let quotation = ["QuotationID": "1234",
            "FullName": "yourname",
            "Email": "youemail",
            "Phone": "yourphone"
            ] // TODO: complete with other key/values
        soap.setValue(quotation, forKey: "quotation")
        // single products
        let product = ["ProductID": "1234",
            "ProductCode": "code1234",
            "ProductName": "prod-name"
            ] // TODO: complete with other key/values
        // products
        let lstproducts = [product, product, product]
        soap.defaultTagName = "Product" // BUG: not work for array
        soap.setValue(lstproducts, forKey: "lstproducts")
        // soap request
        soap.actionNamespaceSlash = true
        soap.responseHeader = true;
        soap.requestURL("http://www.b.....d.com/webservices/service-name.asmx", soapAction: "http://www.b....d.com/SendMail_Quotation",
            completeWithDictionary: { (statusCode: Int, dict : [NSObject: AnyObject]!) -> Void in
                let result:Dictionary = dict as Dictionary
                NSLog("%@", result)
            }, failWithError: { (error : NSError!) -> Void in
                NSLog("%@", error)
        })

note: during this test we found a bug that will fixes within one to two days, sorry.

@mrfoxbit
Copy link
Author

Thank you very much for your fast response. I will wait for the fix.

@priore priore added the bug label Sep 24, 2015
priore added a commit that referenced this issue Sep 25, 2015
@mrfoxbit
Copy link
Author

Hi,
Thank you very much for fix it very fast. But it still not work.

P/s: method that return a single boolean value is very good

@priore
Copy link
Owner

priore commented Sep 29, 2015

which the error ? you can send us a complete example ? (you can use the email)

us with the previous example we did have a response from the server, but the parameters are invalid and the server responded with an error message (invalid xml), look below:

<?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:Client</faultcode>
            <faultstring>Server was unable to read request. ---&gt; There is an error in XML document (1, 418). ---&gt; Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).</faultstring>
            <detail/>
        </soap:Fault>
    </soap:Body>
</soap:Envelope>

@mrfoxbit
Copy link
Author

Hi,

I have a new webmethod: TestCountList

   [WebMethod(Description = "Test SOAPEngine")]
    public int TestCountList(List<Product> lstproducts)
    {
        return lstproducts.Count;
    }

   public class Product
  {
    public Guid ProductID { get; set; }
    public string ProductCode { get; set; }
    public string ProductName { get; set; }
    public string ProductDesc { get; set; }
    public string ProductThumb { get; set; }
    public string ProductImage { get; set; }
    public int InputPrice { get; set; }
    public int OutputPrice { get; set; }
    public int Quantity { get; set; }
    public int IsOutOfStock { get; set; }
    public bool IsHot { get; set; }
    public bool IsNew { get; set; }
    public string CatalogueID { get; set; }
    public bool IsDeleted { get; set; }
    public byte[] ProductThumbByte { get; set; }
    public byte[] ProductImageByte { get; set; }
    public int ViewCount { get; set; }
    public int FavouriteCount { get; set; }
    public string FlickrID { get; set; }
    public int TotalPage { get; set; }
    public int TotalRecord { get; set; }
    public bool IsSelected { get; set; }
    public string ProductNoteMail { get; set; }
}

This is my example

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    let soap = SOAPEngine()
    soap.userAgent = "SOAPEngine"
    soap.licenseKey = "eJJD..../FA=="

    let product = Product(ProductID: "5ba6d7c4-d89f-7d99-df0c-618d9cd60729",
                          ProductCode: "",
                          ProductName: "Test",
                          ProductThumb: "ThumbPath",
                          ProductImage: "ImagePath")

    let lstproducts = [product, product, product]
    soap.defaultTagName = "Product"
    soap.setValue(lstproducts, forKey: "lstproducts")

    soap.actionNamespaceSlash = true
    soap.responseHeader = true;
    soap.requestURL("http://www.b....d.com/webservices/service_name.asmx",
        soapAction: "http://www.b....d.com/TestCountList",
        completeWithDictionary: { (statusCode: Int, dict : [NSObject: AnyObject]!) -> Void in

            //let result:Dictionary = dict as Dictionary

            print(statusCode)                  // statusCode = 200

            print(soap.integerValue())    //  But lstproducts.Count = 0

        }, failWithError: { (error : NSError!) -> Void in

            print(error)
    })

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

class Product : NSObject {

var ProductID:String = "";
var ProductCode:String = "";
var ProductName:String = "";
var ProductThumb:String = "";
var ProductImage:String = "";
var OutputPrice:Int = 0;
var IsOutOfStock:Int = 0;
var IsHot:Bool = false;
var IsNew:Bool = false;
var FlickrID:String = "";
var ViewCount:Int = 0;
var FavouriteCount:Int = 0;
var ProductNoteMail:String = "";
var TotalPage:Int = 0;
var TotalRecord:Int = 0;

init(ProductID:String, ProductCode:String, ProductName:String, ProductThumb:String,ProductImage:String)
{
    self.ProductID = ProductID;
    self.ProductCode = ProductCode;
    self.ProductName = ProductName;
    self.ProductThumb = ProductThumb;
    self.ProductImage = ProductImage;
}

}

@priore
Copy link
Owner

priore commented Oct 1, 2015

Today we release a fix that resolves retrieval of the class name when you pass a user-object.

@priore priore closed this as completed in ba3c984 Oct 1, 2015
@mrfoxbit
Copy link
Author

mrfoxbit commented Oct 1, 2015

Perfect. Thank you very much.

Bug fixed, great library and great job.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants