Saturday, June 23, 2012

Issue installing Packages from Android SDK Manager

I was interested in testing my android application using different packages and tools that is available from the Android SDK Manager. I clicked the SDK Manager and I was presented with the tools/packages already installed in my system as well as those that are not installed into my system.

I selected the packages, accepted the licensing of the package and clicked the “Install (x) Packages…” button. The download started but after few seconds I noticed that the download and installation of the selected package was not successful and I got the “Connection reset” message in the log window. I wasn’t sure what could be the issue but I was able browse the internet.

After having googled about this issue, my colleague recommended to try the installation on another machine. I tried in one my colleague’s machine and saw that the download of the package and the installation succeeded. Next what I did is copied all these packages from the my colleagues system under the folder: <android-sdk-directory>/add-ons and copied to my system’s <android-sdk-directory>/add-ons directory. Then I restarted my Eclipse studio and opened the SDK Manager. I noticed all these packages marked as installed.
Hope this helps someone solve this type of issue…

Thursday, June 21, 2012

Eclipse TFS Plugin Source control issue

At times when working with Team explorer, connecting to TFS Server from Eclipse studio can be a painful experience. Assume that you are working in a project and the source code is controlled from TFS server. Every changes are checked id and you are good for the day.

Next day you open the Eclipse studio ready to work on your project and notice that your project is not getting connected to TFS server (though all internet connectivity and your TFS server is up). You notice from the “Team” menu (right click your project to find this menu) that all command of TFS are disabled but “Return online…”. Clicking “Return online…” You will notice a window shows up displaying progress trying to connect to TFS server to associate source control binding to your project but fails in the first attempt but still continues and then displays the projects you have permission on. You select the project from the list of projects displayed and click the Finish button believing your project would now be associated but still no luck. You will find that all commands are still disabled under “Team” menu except “Return online…”. Annoying huh…

In this situation we can notice that if we double click the source control from the Team Explorer window, nothing will show up in the Source Control Explorer window…arrrr

We can try cleaning the project, restarting the eclipse studio, etc.., but nothing helps and we continue to face this issue and the Team Explorer will continue its struggle trying to connect to the TFS Server.

Ok so what’s the solution then…well...In this situation, instead of spending more time researching on this issue, we can perform the following actions to restore source code binding with TFS:

1.       Delete the project (remove only) from eclipse studio (Important Note: Not physical delete of the project from the system)
2.       Restart Eclipse studio and connect to TFS server. This time you will notice that it connects successfully without any issues.
3.       From the Source Control Explorer, right click on your project and click Import… button.
4.       Provide appropriate details in the “Import Project from Team Foundation Server” wizard and…

Things are back to normal….
Hope this help you solve your problem…

Saturday, June 16, 2012

Debugging Android Application directly from Android Mobile

We develop the android application and 75% of the time test using android simulator and witness the application working perfectly all right. We are happy and deploy the application to our android mobile (same target platform) and test verify. 90 to 95% of the time we see the application working alright with the actual device but sometimes we face issues.

What do we do next…we check back the application in simulator atleast once following the same scenario and see if we are able to replicate the issue. We see that the application works just fine in the same scenario in case of the simulator.

OK what next…what are our options…Well we have different mechanism to troubleshoot and the popular amongst those are as follows:

1.       Write to the log and then work through the application in the device with the same scenario reproducing the issue and then pull the log from the device and identify and solve the issue.
Yes but this type of troubleshooting is less preferable if the owner of the mobile is our pocket!!! This type of troubleshooting is more suitable when the user of our application lives in remote location.

2.       From the eclipse studio start debugging the application directly from the android device.
This is one of the easiest way to quickly troubleshoot and fix if we are facing the issue only when executing the application in the android mobile.

Ok…but how…well here is how you do this…

1.       From the Eclipse studio, pull open the “Windows” menu and select “Android SDK Manager” to view the list of target platform, additional libraries and Devices installed and/or available.

2.       From this list, expand the “Extras” folder and make sure “Google USB Driver” is installed as shown below in the screenshot. If this is not installed, then check mark the “Google USB Driver” and get this installed. Note: If any updates are available to the packages already installed, then they are selected by default. It is upto us if we want those updates or not.


3.       On your phone, click Settings > Applications > Development and make sure USB Debugging is on.

4.       After installing the “Google USB Driver”, connect the device to the system using the USB cable. A window opens up and prompt about installing drivers. Wait for it to complete.

5.       Open the command prompt window and navigate to the “platform-tools” directory under android-sdk directory. In my case it was (D:\Program Files\Android\android-sdk-windows\platform-tools)

6.       Type “adb devices” in the command prompt and this will list the devices installed. From this list you should see a serial number (some sequence of digits) and this happens to be the serial number of your android mobile. If you see so, then you are set to go.

7.       Now, instead of following the regular way of executing/running the application, this time it will be different. Right click on your project and from the context menu select Run As > Run Configurations…

8.       From the “Run Configurations” window, click the “Target” tab and select the “Manual” option from the “Deployment Target Selection Mode” panel as shown below


9.       Now click the “Run” button from the “Run Configurations” window and you will be prompted with the “Android Device Chooser” window.

10.   From the “Android Device Chooser” window, select “Choose a running Android device” option and then select the serial number (this will match with the serial number that displayed in the command window) and click the “OK” button.

11.   This time the application (apk file) is loaded directly in the android mobile and you can follow the same mechanism to debug it (Setting breakpoints and so on)

Hope this helps troubleshooting your issue…

Happy Androiding…

Saturday, June 09, 2012

Simulating an Incoming Call in the Android Simulator

At times, when developing the application or after developing the application, we are interested to test and break our application with all possible ways we can so that end users don’t end up facing such issues. One such scenario that we possibly miss out while testing our application using simulator is when a call arrives and our application is active.

This scenario is easy to simulate in the android simulator and this is done as follows:

1.       Start the Android Simulator and we can notice the number that is displayed on the title bar (as showing using the arrow mark in the screenshot below). In this case it is 5554.


2.       Open the command prompt window and type the following command to start the telnet session to localhost with port number as the number identified in the above step i.e., 5554

telnet localhost 5554

3.       This will open the telnet command session to the simulator. In this session, we can type help command and this will display all possible actions that we can perform on the simulator.


4.       From the displayed list of commands, we are interested in performing an incoming call to the simulator. The command is gsm and to know the syntax we type the following command:

help gsm

This command will display all sub-commands that can be used as part of gsm operation and they are as follows:


5.       From the above list, we are interested in the gsm call sub-command and this can be issued as follows:

gsm call 9999999999

here we can use any 10 digit number and not less or more. Issuing this command we can see an inbound call in the simulator as shown below:


                This helps us by providing a new level of testing using the android simulator and not depend on android devices in such scenarios.

                Happy Androiding…

Wednesday, June 06, 2012

Eclipse displaying error icon on Android Project

When working with Android Project files, sometimes we work directly from within Eclipse studio and sometimes outside of the studio. Assume that in one our android project, we are in need of one complex functionality to be performed. We Google and get hold of java source that does exactly what we require. So, we go ahead and download the java source file and add it using Eclipse studio to our android project. Having added that we notice a couple of errors in the downloaded java file. Instead of fixing it right away, we decide to fix at a later point of time and close the eclipse editor (assuming a long break time).

Returning back we learn that our R & D team have implemented the complex functionality and now we decide to get rid of the downloaded java file. We move to the src folder location using windows explorer and delete the file. (Note that this file was added using the eclipse studio and on top of that the downloaded file had errors). Now we open the eclipse studio and notice that there are no error icons displayed for any files but the android project.

We try the following ways to get rid of the error but all goes in vain:
1. Clean the project but still the error remains
2. Refresh the project but still the error remains
3. Fix Project Properties from Android Tools but still the error remains

The fix that worked in our case is removing the .metadata folder from the project root location. This folder seems to hold reference to all the files added using eclipse studio.

Friday, June 01, 2012

Android ~ Facebook login issue from Android application

When developing android applications that uses Facebook’s LoginButton to authenticate and authroize, there will be no issues running on the emulator. But when the same apk file (android installation file) is installed in an android device and executed it won’t work. The Facebook’s LoginButton, after clicking, progresses a while and returns back to the same screen taking us nowhere.

There could be several reasons for this behaviour but I have came across a couple of symptoms and was successful in addressing those:

1.       You might have not set the hashkey for your application in facebook or you might have messed up/changed your working android debug.keystore file locally in your system.

If you have not yet set the hashkey for your application, please generate hashkey for your application first, then set the hashkey for the facebook application. Here is the article that explains in a step by step manner to create your hashkey: http://hemant-vikram.blogspot.in/2012/05/generating-hashkey-for-android-facebook.html

At times when working with our android application we may sometimes use other’s debug.keystore file and replace our’s to see if some of our issues go away. Now if we generate the apk file and install in the device to test it out, we will notice this issue. To resolve we will have to re-generate hashkey and set that in the facebook apps.
2.       You might have missed the invocation of super method in the protected void onActivityResult(int requestCode, int resultCode, Intent data) method block

If you have missed, then add the following as the first line in your method block:
super.onActivityResult(requestCode, resultCode, data);

Edit: There is one another problem that I dealt with the signed apk file. I used the following steps to sign the apk file:
Right Click on the Project -> Android Tools -> Export Signed Application Package...
I provided the project name and clicked next and selected the keystore location path that has an empty space in it. Having generated the keystore file, signed apk file, generated the hashkey using the keystore file and setting it to facebook app settings page I was seeing that I was not able to get past the login screen. I was seeing a facebook progress dialog and after few seconds it disappears. I was running out of clues as what could be missing. Later along with my colleague, went thru the same process of generating the keystore and all that but this time without an empty space character in the path. We ran the apk file and tried the facebook signon and bingo. It worked!!!

Hope this helps you to resolve your problem and importantly save some time…

Happy Androiding

Wednesday, May 30, 2012

Eclipse & TFS ~ Ignoring file from commit

The TFS plugin for Eclipse doesn’t have a direct way to support ignoring the files from committing directly from IDE just like SVN does. For example, we prefer not to commit the “bin” directory. In order to ignore certain files or directory, we will have to create a file with the name .tpignore and save it in the root directory of the project. For example, to ignore bin directory and all of its files, the content of the .tpignore file should be as follows:

/bin/
/bin/.*

Generating Hashkey for Android Facebook Application Integration

Step 1


Step 2

Extract to a folder (in my case d:\android\openssl)

Step 3

Copy your debug.keystore file to the Java JDK folder where keytool.exe is present
In my case debug.keystore was in C:\Users\hemant\.android\debug.keystore
And
keytool.exe was in D:\Program Files\Java\jre7\bin folder

Step 4

Open the command prompt in the jdk bin folder where keytool.exe is and execute the following command:
keytool -exportcert -alias androiddebugkey -keystore debug.keystore > d:\android\openssl\bin\debugkey.txt
Provide password as android when prompted

Step 5

Navigate to openssl\bin folder (here we have debugkey.txt) in the command prompt and execute the following commands:
a.       openssl sha1 -binary debugkey.txt > debugkey_sha.txt
b.      openssl base64 -in debugkey_sha.txt > debugkey_base64.txt

That’s it! We are done. The debugkey_base64.txt contains the hashvalue. We need to copy paste this key to the Basic Settings page of our facebook application as shown below using the green arrow.

Friday, May 25, 2012

Android ~ Manually terminating an application or an activity

Best Practice recommended for Android development is to leave memory management to Android OS itself. What this means is when user moves out of our activity/application, we need not call the finish method to destroy it and release memory rather leave the application running without “finishing” it. When Android OS runs low in memory, it may decide to terminate the running activities.

Ok having said that and during development, assume we are interested to start the application fresh. In order to achieve this, we have four ways to do it and they are as follows:

1.       Restart the emulator    
This will take longer time but you can achieve your expectation

2.       Re-run the application 
This too will take longer time but comparatively less than that of restarting the emulator and you will achieve your expectation

3.       Stop Process from DDMS view 
This is quickest method and can be done only from the Eclipse studio
Eclipse Studio -> DDMS Perspective view -> Devices panel -> select process -> click stop button

4.       Force stop from Settings             
This is also the quickest and the safest method you can do directly from the Android device.
                Android Emulator -> Settings -> Applications -> Manage Applications -> Running Tab -> Select Application -> Force Stop

Android LogCat does not show anything !!!

Sometimes when working with Android applications, we may come across a situation where we will not see anything showing up the log no matter even if we select application specific log or all verbose messages. So what went wrong and how can this be fixed.

Here is the easiest way to fix this….


Open the DDMS perspective view. From the top left panel (Devices panel), select your application and that’s it…You will see the next moment logs get pouring in the logcat window.

Thursday, March 29, 2012

Deploying WCF Service on IIS 6.0

After deploying WCF service to IIS 6.0, we will notice that the page will not load when requesting http://mydomain.com/myservice.svc instead we would get 404 page not found exception. If you place a sample HTML file in the same directory and try to visit the page, the page will show up.

 

After googling, I learnt that after installing .NET Framework 4.0 Client Profile redistributable in the server, by default the ASP.NET 4.0 ISAPI extension is not enabled. This can be determined using the following command in the command prompt:

 

C:\>cscript c:\WINDOWS\system32\iisext.vbs /ListFile

 

Executing the above command will list all the extension files of IIS as

 

Status / Extension Path
------------------------
0  C:\WINDOWS\system32\inetsrv\httpodbc.dll
0  C:\WINDOWS\system32\inetsrv\ssinc.dll
0  C:\WINDOWS\system32\inetsrv\asp.dll
1  C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll
1  C:\WINDOWS\system32\MQISE.DLL
0  C:\WINDOWS\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll

 

From the above listed extension files, you will see that the status is 0 for aspnet_isapi.dll of ASP.NET Framework 4.0. This means it is not enabled and this is preventing ASP.NET 4.0 processing your request. To enable the extension use the following command:

 

C:\>cscript c:\WINDOWS\system32\iisext.vbs /EnFile C:\WINDOWS\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll

 

Once the above command is executed successfully, you should be able to see your WCF service coming up in the browser.

Monday, February 27, 2012

Sql Server 2008 Express SP1 installation on Windows XP SP 3

Hi Guys,

 

I was working with my team creating setup package using VS 2010 for a desktop application. The requirement is to install Sql Server 2008 Express Edition with SP1 along with other tools. The setup was working fine Windows 7 and Windows XP. But with Windows XP SP 3 64 bit machine, we started facing issues installing Sql Express 2008 SP1. We were getting the following exception log message:

 

An error occurred attempting to install SQL Server 2008 Express Service Pack 1

Installing using command 'C:\DOCUME~1\TICKSE~1\LOCALS~1\Temp\VSDB.tmp\SqlExpress2008\SQLEXPR32_x86_ENU.EXE' and parameters '/q /hideconsole /action=Install /features=SQL /instancename=SQLEXPRESS /enableranu=1 /sqlsvcaccount="NT Authority\Network Service" /AddCurrentUserAsSqlAdmin /skiprules=RebootRequiredCheck'

Process exited with code -2067922433

After lot of googling and with help of my team, I got the following link that discusses about addressing permission issue with the registry key “Microsoft Sql Server”. We tried the option and bingo!!! It worked. Here are the steps if in case you are stuck with similar issue.

 

Steps

 

1.       Located HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server in registry

2.       Right click and go to Permission

3.       Click on Advance

4.       Tick on both check box (I. Inherit from parent the permission... II. Replace permission entries on all child objects...), click OK

5.       Click OK again

Tuesday, January 31, 2012

Programmatic SiteMinder 2.0 authentication and getting the FedAuth cookie to access SharePoint 2010 service

-->
One of our client upgraded their SSO authentication mechanism for their site from SiteMinder v1 to SiteMinder v2. We have built one project for this client that was making use of SSO to authenticate users and allowing them access. With WSS 3.0 and SiteMinder v1, we didn’t had much issues. We passed the username password, got hold of the SAML token and used it in the cookie container to consume the service from WSS 3.0.

But with sharepoint 2010 (claims enabled) and SiteMinder v2.0, there were a lot of difference. There were around 7-8 redirects before we hit the login page. Then we constructed the data to be posted and posted to the login page. Got the SAML token but it’s not finished yet. There were again a series of redirects before we hit the _Trust link. The trust link is where we post the web context, web result and web authentication data. Successfully posting these 3 data along with required cookies helped to get hold of the much wanted FedAuth cookie. This is the cookie that will help you consume services hosted at sharepoint 2010. Below is the full listing of the code.

public static void UpdateListItem(string listPath, string username, string password)
        {
            CookieContainer cookies = new CookieContainer();
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
            string message = string.Empty;

            try
            {

                // Open connection to Protected URI.  This will be intercepted and redirected
                // to SiteMinder login screen.
                Uri listUri = new Uri(listPath);
                HttpWebRequest request = WebRequest.Create(listUri) as HttpWebRequest;
                request.AllowAutoRedirect = false;

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                string url = string.Empty;
                string domain = listUri.Host; //"https://yourdomain.com";
                string userAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)"; //very important to set the agent parameter to requests
                Cookie jcookie = null;

                while (response.StatusCode == HttpStatusCode.Redirect)
                {
                    url = response.Headers[HttpResponseHeader.Location];

                    //check headers for Set-Cookie
                    if (!string.IsNullOrEmpty(response.Headers[HttpResponseHeader.SetCookie]))
                    {
                        string[] cookie = response.Headers[HttpResponseHeader.SetCookie].Split(';');

                        string[] cookieNameValue = cookie[0].Split('=');
                        jcookie = new Cookie(cookieNameValue[0], cookieNameValue[1]);
                        jcookie.Domain = listUri.Host;

                        string[] cookiePathValue = cookie[1].Split('=');
                        jcookie.Path = cookiePathValue[1];

                        string cookieIsSecure = cookie[2];
                        if (cookieIsSecure.Trim().ToLower() == "secure")
                            jcookie.Secure = true;

                        cookies.Add(jcookie); // This is one of the cookie that is required when posting data to trust link. Verified using fiddler
                    }

                    request = WebRequest.Create(url) as HttpWebRequest;
                    request.AllowAutoRedirect = false;
                    request.UserAgent = userAgent;

                    response = (HttpWebResponse)request.GetResponse();
                }

                // Create the form data to post back to the server
                NameValueCollection namevalues = GetHTMLInputTags(ResponseToString(response));
                string postData = string.Empty;
                foreach (string key in namevalues.Keys)
                {
                    postData += key + "=" + System.Web.HttpUtility.UrlEncode(namevalues[key]) + "&";
                }
                postData += "postpreservationdata=&";
                postData += "userid=" + System.Web.HttpUtility.UrlDecode(username) + "&";
                postData += "password=" + System.Web.HttpUtility.UrlEncode(password);

                // Submit the data back to SiteMinder
                cookies.Add(response.Cookies);

                request = WebRequest.Create(url) as HttpWebRequest;
                request.CookieContainer = cookies;
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = postData.Length;
                request.Method = "POST";
                // Important: we need to handle the redirect ourselves
                request.AllowAutoRedirect = false;

                // post the data to the request
                using (StreamWriter sw = new StreamWriter(request.GetRequestStream()))
                {
                    sw.Write(postData); sw.Flush(); sw.Close();
                }

                // Important to get the cookies here (they will include the SMSESSION cookie)
                response = (HttpWebResponse)request.GetResponse();
                cookies.Add(response.Cookies);

                while (response.StatusCode == HttpStatusCode.Redirect)
                {

                    url = response.Headers[HttpResponseHeader.Location];

                    request = WebRequest.Create(url) as HttpWebRequest;
                    request.CookieContainer = cookies;
                    request.AllowAutoRedirect = false;

                    response = (HttpWebResponse)request.GetResponse();
                    cookies.Add(response.Cookies);

                }

                #region Manual Authenticate

                string rootUrl = string.Format("{0}://{1}", listUri.Scheme, listUri.Host);// "https://mydomain.com";
                request = WebRequest.Create(rootUrl) as HttpWebRequest;
                request.CookieContainer = cookies;
                request.AllowAutoRedirect = false;
                request.UserAgent = userAgent;
                response = (HttpWebResponse)request.GetResponse();
                cookies.Add(response.Cookies);

                while (response.StatusCode == HttpStatusCode.Redirect)
                {

                    url = response.Headers[HttpResponseHeader.Location];

                    if (url.StartsWith("/"))
                        url = rootUrl + url;

                    if (url.Contains("affwebservices"))
                        cookies.Add(jcookie); // This is the place we add the jsession cookie (seems optional)

                    request = WebRequest.Create(url) as HttpWebRequest;
                    request.CookieContainer = cookies;
                    request.UserAgent = userAgent;
                    request.AllowAutoRedirect = false;

                    response = (HttpWebResponse)request.GetResponse();
                    cookies.Add(response.Cookies);

                }
  
                #region Manual STS Post to Trust

                url = rootUrl + "/_trust/default.aspx";

                namevalues = GetHTMLInputTags(ResponseToString(response));

                string stringData = String.Format("wctx={0}&wresult={1}&wa=wsignin1.0",
                System.Web.HttpUtility.UrlEncode(namevalues["Wctx"]),
                System.Web.HttpUtility.UrlEncode(namevalues["wresult"].Replace(""", @"""")));

                request = HttpWebRequest.Create(url) as HttpWebRequest;

                Console.WriteLine(string.Format("Programmatic Post to URL = {0}
"
, request.RequestUri));
                Console.WriteLine(string.Format("Post Data = {0}

"
, stringData));

                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.CookieContainer = cookies;
                request.UserAgent = userAgent;
                request.AllowAutoRedirect = false; // This is important
                Stream newStream = request.GetRequestStream();

                // Actually send the request
                using (StreamWriter sw = new StreamWriter(newStream))
                {
                    sw.Write(stringData); sw.Flush(); sw.Close();
                }

                response = request.GetResponse() as HttpWebResponse;
                //get the fed-auth cookie
                if (response.Cookies.Count > 0)
                {
                    var fedAuth = response.Cookies["FedAuth"];
                    if (fedAuth != null)
                    {
                        cookies.Add(fedAuth);
                    }
                    else
                    {
                        cookies.Add(response.Cookies);
                    }
                }
                else if (!string.IsNullOrEmpty(response.Headers[HttpResponseHeader.SetCookie]))
                {
                    string[] cookie = response.Headers[HttpResponseHeader.SetCookie].Split(';');

                    Cookie fedCookie = null;

                    for (int index = 0; index < cookie.Length; index++)
                    {
                        string[] cookieNameValue = cookie[index].Split('=');

                        switch (cookieNameValue[0].ToLower())
                        {
                            case "fedauth":
                                fedCookie = new Cookie(cookieNameValue[0], cookieNameValue[1]) { Domain = domain.Replace("https://", string.Empty) };
                                break;

                            case "expires":
                                fedCookie.Expires = Convert.ToDateTime(cookieNameValue[1]);
                                break;

                            case "path":
                                fedCookie.Path = cookieNameValue[1];
                                break;

                            case "secure":
                                fedCookie.Secure = true;
                                break;
                        }
                    }
                    cookies.Add(fedCookie);

                }
                else
                {
                    throw new ApplicationException("FedAuth cookie not received from Sharepoint. Please contact sharepoint administrator for further assistance.");
                }

                #endregion

                // Get the page we should hit next (should be Cognos)
                // Step 7: Persist the cookie
                while (response.StatusCode == HttpStatusCode.Redirect)
                {

                    url = response.Headers[HttpResponseHeader.Location];
                    Console.WriteLine(string.Format("Status = {0}, Response URL = {1}

"
, response.StatusDescription, url));

                    if (url.StartsWith("/"))
                        url = rootUrl + url;

                    request = WebRequest.Create(url) as HttpWebRequest;
                    request.CookieContainer = cookies;
                    request.AllowAutoRedirect = false;

                    Console.WriteLine(string.Format("Request URL = {0}
"
, request.RequestUri));

                    response = (HttpWebResponse)request.GetResponse();
                    cookies.Add(response.Cookies);

                }

                var lists = new Lists { CookieContainer = cookies };

                #region Code to update metadata for "My Submitted Content" list
                var camlcmd = new StringBuilder();
                camlcmd.Append("");
                foreach (var field in mmsParams.ListItemFields)
                {
                    camlcmd.AppendFormat
                        (
                            "{1}",
                            field.Key.Replace(" ", "_x0020_"),
                            field.Value
                        );
                }
                camlcmd.Append("
");

                var updates = (new XmlDocument()).CreateElement("Batch");
                updates.InnerXml = camlcmd.ToString();

                var resp = lists.UpdateListItems(mmsParams.PublishListName, updates);
                #endregion

                #region List Service response
                if (resp.FirstChild.FirstChild.InnerText == "0x00000000")
                {
                    var listitemid = resp.ChildNodes[0].ChildNodes[2].Attributes["ows_ID"].Value;
                    foreach (string attachment in mmsParams.Attachments)
                    {
                        lists.AddAttachment
                            (
                                mmsParams.PublishListName,
                                listitemid,
                                Path.GetFileName(attachment),
                                ReadBytes(attachment)
                            );
                    }
                }
                else
                {
                    throw new Exception("No field was found with that name. Check the name, and try again");
                }
                #endregion
            }
            finally
            {
                // Step 9: Delete the cookie from cache when done
                //DeletePersistentCookies(cookies);
            }
        }

        public static string ResponseToString(HttpWebResponse response)
        {
            // Get the stream containing content returned by the server and.
            // Open the stream using a StreamReader for easy access.
            using (StreamReader reader = new StreamReader(response.GetResponseStream()))
            {
                // Read the content.
                return reader.ReadToEnd();
            }
        }
        public static NameValueCollection GetHTMLInputTags(string responseString)
        {
            var htmlDocument = new HtmlDocument();
            htmlDocument.LoadHtml(responseString);
            var nodeCollection = htmlDocument.DocumentNode.SelectNodes("//input");
            var tags = new NameValueCollection();
            for (var index = 0; index < nodeCollection.Count; index++)
            {
                var attributeCollection = nodeCollection[index].Attributes;
                var type = attributeCollection["type"] != null ?
                                    attributeCollection["type"].Value :
                                    string.Empty;
                if (type.ToLower().Equals("submit") || type.ToLower().Equals("button")) continue;
                var name = attributeCollection["name"] != null
                                  ? attributeCollection["name"].Value
                                  : string.Empty;
                var value = attributeCollection["value"] != null
                                   ? attributeCollection["value"].Value
                                   : string.Empty;
                if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(value))
                    tags.Add(name, value);
            }
            return tags;
        }