23 Ekim 2011 Pazar

Android ile dataset dönen bir .NET webmethod'unu çağırmak. How to call a .NET webmethod which returns dataset using Android

Arkadaşlar merhaba,
(Hello guys)

10 yılı aşkın bir süredir profesyonel olarak yazılım sektörünün içinde olmam sebebiyle rahatlıkla söyleyebilirim ki gerçek hayat projelerinin neredeyse hiç birinde işler yazılımcının istediği şekilde ilerlemez.  Lafı uzatmadan android'de pek çok kişinin karşılaştığı ancak koca internette "1" tane bile örneğin bulunmadığı bu tür durumlardan birine değineceğim: Android ile .NET'te yazılmış dataset dönen bir webservise erişmek. Aslında hiçbirimiz dataset veya datatable gibi belli bir platforma (.NET) özel oluşturulmuş kompleks bir nesnenin webmethod gibi globallik arz eden bir yapıda dönüş değeri olarak kullanılmasını doğru bulmayacağız, bundan eminim. Fakat sizden böyle bir webmethod'la iletişime geçmenizin istendiğini ve bunun alternatifi olmadığını düşünün, ne yapacaksınız? Bu tamamen yanlış demeniz muhatabınız açısından ne kadar gerçekçi ve kabul edilebilir bir cevap olarak karşılanacak?

(As a professional developer who develops, plans and executes for 10 years, I can conveniently say without any doubt that in real life projects the things rarely comply with our plan. This example is one of them: Today we are going to mention about a case that there can not be found any tutorial on the internet about it, reaching a webservice which returns .NET dataset. I'm sure nobody wants to use these kind of complex objects like dataset or datatable -which runs only in .NET- as a parameter with a webmethod. However let's suppose that you are facing with a case that you need to call a webmethod like this and there is no any alternative way to do. Do they accept it as a reasonable answer when you say this is impossible? Or just think how they react when you say that.)

Gelin nasıl bu işin altından kalkacağımıza bakalım.
(Let's look how do we resolve that.)

Dediğimiz gibi bir webmethodumuz var ve dataset dönüyor. Önceki yazılarımızda 3. parti kütüphane kullanmadan (ksoap2 gibi) android ile bir webservise nasıl soap request atacağımızı ve geri dönüşü nasıl handle edeceğimizi anlatmıştık. Tüm bu bilgiler üzerine dataset dönen bir webmethod'un nasıl bir xml şemasına sahip olduğunu da bilirsek geriye kalan tek şey uygun yapıyı hazırlamak olacaktı ve öyle de oldu. Yeri gelmişken söylemekte fayda var bu tür envelope'un doğru oluşup oluşmadığını deneme amaçlı testlerde soapUI size büyük kolaylık sağlayacaktır.

(As I said there is a webmethod which returns dataset. I mentioned on previous tutorials that we need to know some key facts like how do we send soap request on android without using any third party library like ksoap2 and how do you handle return parameter which comes from AsyncClass on android -at the moment it supports turkish only-. In addition to this, if we know the xml schema of the soap response that comes from a webmethod which returns dataset then we can write the code very easily what we need.)

Bu noktadan sonra şu aşamada olduğumuzu varsayıyorum. (I suppose that we are here at this point)
  1. Soap envelope'umuz hazır,(we prepared the soap envelope)
  2. Webmethod'a başarıyla request attık. (we can call the webmethod without exception)
  3. Response'umuzu XML olarak aldık ve parse edilmeyi bekliyor. (we got the response as xml and it is waiting for parsing)
private DataTable parseAsDataTable(String x, String methodName){  
    //Datatable benim android için geliştirdiğim, .NET'teki DataTable nesnesinin içerdiği neredeyse bütün method ve özellikleri barındıran bir nesne. Siz bunun yerine 2 boyutlu bir object array kullanabilirsiniz. 
    //Datatable is an object that I created for android. It supports a lot of methods and properties of .NET datatable. But you can use 2 dimensional array instead of using this object -Object[row][column]-) 
    DataTable dt = new DataTable(Gonderim.this);
    try {
        String sMethodBaslangic = "<"+methodName+" xmlns=\"\">";
        String sMethodBitis = "";
        int artiBaslangic = sMethodBaslangic.indexOf(">");
        artiBaslangic++;
        int baslangic = x.indexOf(sMethodBaslangic);
        if(baslangic>-1){
            baslangic+=artiBaslangic;
            x = x.substring(baslangic);
            int bitis = x.indexOf(sMethodBitis);
            x = x.substring(0, bitis).replace(":", "_");
            x = new StringBuffer(x).insert(0,"<"+methodName+">").toString();
            x += "";        
            byte[] bytes = x.getBytes();
            ByteArrayInputStream bInputStream = new ByteArrayInputStream(bytes);


            // gelen string'i bir xml haline getiriyoruz.
            // converting string to xml
            DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
            org.w3c.dom.Document doc = docBuilder.parse (bInputStream);
            org.w3c.dom.Element element = doc.getDocumentElement();
            NodeList nl = element.getChildNodes();
            boolean takenColumnNames=false;
            String[] columnArray;
            String columnNames = "";
            int rowIndex =  nl.getLength();
            int colIndex = nl.item(0).getChildNodes().getLength();
            Object[][] dataSource = new Object[rowIndex][colIndex];


            for (int i = 0; i < rowIndex; i++) {
                NodeList nlChildren = nl.item(i).getChildNodes();
                for (int j = 0; j < nlChildren.getLength(); j++) {
                    Node node = nlChildren.item(j);
                    if(!takenColumnNames){
                        columnNames+=node.getNodeName()+",";
                    }
                    dataSource[i][j] = node.getChildNodes().item(0).getNodeValue();
                }
                takenColumnNames = true;
            }


           columnArray = columnNames.split(",");
           dt.setColumns(columnArray);
           dt.setDataSource(dataSource);
        }
    } catch (Exception e) {
        Util.setException(Gonderim.this, e);
    }
    return dt;
    }
Anlaşılmayan bir nokta olursa çekinmeden mesaj atabilirsiniz. İyi çalışmalar.
(Please feel free to contact me if you have any questions)


mgNet Library kullanımı
örnek video



15 yorum:

  1. Sanırım ksoap2 de işimizi görebilirdi burda.

    YanıtlaSil
  2. Neden ksoap2 kullanmıyoruz ? ksoap2 kullanınca dataset'i mi kullanamıyoruz? yukarıdaki işlemin gerçekleştiği bir projeyi upload eder misiniz rica etsem..

    volkan@wapdizayn.com
    Saygılarımla
    Volkan ÇOBAN

    YanıtlaSil
    Yanıtlar
    1. Android yazmaya başladığım sıralarda android'in kendisi zaten yeni yeni geliştiriliyordu. Yani altyapısında deprecated veya obsolete olabilecek nesnelerin potansiyeli hayli yüksekti. Bunları .NET çıkarken kanlı canlı yaşadık. Daha bu aşamada 3. party bir kütüphane sizi zaman zaman kısıtlayabilir. Hele bir de dökümantasyonu kolay ulaşılabilir değilse. Bunun yanında mobil cihazlar gibi kapasitesi bir çok farklı parametreyle sınırlandırılmış aygıtlarda, network işleri vb önem arz eden işlemleri kontrol altında tutmayı isteyebilirsiniz. KSoap en nihayetinde bir kütüphane. Bir yandan android'in gelişimi diğer yandan ksoap'ın ona ayak uydurmasını takip etmeniz gerekecektir. Ayrıca tecrübelerle sabit bu yüzden de dillere pelesenk olmuş "gerçek dünya ile örnek projeler arasındaki uyuşmazlık" sıkıntısı bu işi kontrol altında tutmamın -en azından belli bir süre için- en doğrusu olacağı düşüncesini doğurdu. Sonuç olarak bir süre sonra Dataset dönen webservislerle karşılaştığım da ne kadar haklı olduğumu anladım. Ksoap için dataset demek kompleks bir sınıf demektir. Yani onun için personel türünde dönen bir webmethod ile dataset dönen bir webmethod arasında çok fark yoktur, personeli nasıl parse edeceksen dataseti de o şekilde alıp parse etmen gerekir. Burada dikkat edilmesi gereken şey datasetin sıradan bir kompleks yapı olmadığı yani parse etmesi çok daha zor. Benim yaptığım bu yöntemi seçmek yerine kendi kütüphanemi yazmak oldu. Yani ikinci sorunuza istinaden belirtiyorum ksoap2 dataset diye bir şey bilmez. Onun için dönüş tipi primitive midir yoksa kompleks midir bu önemlidir ve ona bakar. Ben bu tür işlemleri minimum sıkıntıyla bertaraf edebilmek için DataGrid (rowdatabound tarzı bir kaç eventiyle birlikte), DataTable, DataRow, DataSet, GenelSql ve CallSoap adında nesneler yazdığım bir kütüphane oluşturdum. Bunlar ile .NET tarafıyla çok rahat iletişim sağlayabiliyor ve/veya .NET yazan kişilerin android yazabilmesini aşırı derecede kolaylaştırabiliyorum. Bahsettiğim bu nesneler ile ilgili en kısa zamanda bir video koyup burada da paylaşacağım -hatta belki bugün bir tane koyabilirim-. Yalnız şu an bu nesneleri paylaşmam pek mümkün gözükmüyor. Önceki makalelerde kilit noktaların nasıl aşıldığına dair belirttiğim hususlar mevcut. Anlayamadığınız noktaları mümkün mertebe yanıtlamaya çalışırım.

      Sil
  3. web service ile direkt dataset gönderebiliyoruz. Peki bu dataset'i direkt java'da denk olan bir object'e çevirebilmemiz mümkün mü?

    YanıtlaSil
    Yanıtlar
    1. DataSet, DataTable, DataRow gibi kompleks nesneler .NET'e aittir. Java'da karşılıkları yoktur. Ancak şu videoda bu istediğinizi sağlamak mümkün. http://www.youtube.com/watch?v=YbrwaQbRA1k

      Sil
  4. Anladığım kadarıyla çözümü bulmuşsunuz ama tam olarak paylaşmamışsınız. Vermiş olduğunuz parseAsDataTable methodunda geri dönüş değeri DataTable türünden fakat elimizde DataTable diye bir nesnemiz mevcut değil. Yanılıyor muyum?

    YanıtlaSil
    Yanıtlar
    1. Pardon açıklama satırı olarak yazılanı görmemiştim. Videoyu izleyince farkettim.
      "Datatable benim android için geliştirdiğim, .NET'teki DataTable nesnesinin içerdiği neredeyse bütün method ve özellikleri barındıran bir nesne. Siz bunun yerine 2 boyutlu bir object array kullanabilirsiniz."

      Sil
    2. Aynen öyle, olay parse işleminde bitiyor zaten. Datatable benim c# tarafıyla kolay anlaşmam için geliştirdiğim bir nesneden ibaret.

      Sil
    3. mgnet2.jar dosyası nerde hocam

      Sil
  5. where i will be found mgNet.jar file

    YanıtlaSil
  6. Merhabalar örneği ve kütüphaneleri paylaşmanız mumkunmu?

    YanıtlaSil
  7. how get data from Datatable in android

    YanıtlaSil
  8. merhaba mgnet2.jar dosyasını paylaşabilir misiniz

    YanıtlaSil
  9. cevap versene library le yapmışsın nerden bulucamızı söyle bari

    YanıtlaSil
  10. Şu DataTable nesnesini görmeyi isterim aslında. Çünkü gerçekten merak ettim ve hiçbir kaynak ta yok.

    YanıtlaSil