drupal hit counter
Jerry Huang | C#

Jerry Huang apps and developing apps

Re-using your SOAP in Xamarin .Net Standard

19. January 2019 22:01 by Jerry in C#, Xamarin

I have an old Xamarin Forms project that created couple years ago, by then, was using PCL as project template. The project initially was only for iOS but recently I need to support Android as well. For some reason, there is an runtime error as soon as the app launched. Long story short, I want to upgrade the PCL to .Net Standard 2.0. The project consumes a SOAP web service (asmx) also written long time ago. Even thought I manage to eliminate all compile time error after re-generating the proxy class. The WS call end up with the same exception as below:

https://github.com/dotnet/wcf/issues/1804

Operation 'methodNameAsync' contains a message with parameters. Strongly-typed or untyped message can be paired only with strongly-typed, untyped or void message.

The issue is currently opened here as well:

https://github.com/dotnet/wcf/issues/1808

After some research, I understand that there is no solution for that while I don't want to re-write my SOAP WS into REST api. I decided to write my own SOAP client by re-using the data/schema classes generated inside proxy class. Here is my soap client looks like:

public class SoapService 
{ 
private static T Deserialize(string xml, string ns= "http://home.jerryhuang.net/")
{
Message m = Message.CreateMessage(XmlReader.Create(new StringReader(xml)), int.MaxValue, MessageVersion.Soap11);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T), ns);
return (T)xmlSerializer.Deserialize(m.GetReaderAtBodyContents()); 
}
class RequestMessageBodyWriter : BodyWriter
{
private MessageBodyDescription bodyDescription;
private object[] parameters;
public RequestMessageBodyWriter(MessageBodyDescription bodyDescription, params object[] parameters)
: base(false)
{
this.bodyDescription = bodyDescription;
this.parameters = parameters;
}
protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
{
// Can't Dispose this xmlWriter, 'cause it will close 'writer'.
var xmlWriter = XmlWriter.Create(writer);
xmlWriter.WriteStartElement(bodyDescription.WrapperName, bodyDescription.WrapperNamespace);
foreach (var part in bodyDescription.Parts)
{
var dcs = new DataContractSerializer(part.Type, part.Name, part.Namespace);
dcs.WriteObject(xmlWriter, parameters[part.Index]);
}
xmlWriter.WriteEndElement();
}
}
private Message GetRequestMessage(string opName, params object[] para)
{
var serviceDescription = ContractDescription.GetContract(typeof(HomeServices.HomeServiceSoapClient));
var operationDescription = serviceDescription.Operations.Single(op => op.Name.Equals(opName));
var inputMessage = operationDescription.Messages.Single(msgDescription => msgDescription.Direction == MessageDirection.Input);
var bodyDescription = inputMessage.Body;
var msg = Message.CreateMessage(MessageVersion.Soap11,
inputMessage.Action, new RequestMessageBodyWriter(bodyDescription, para));
//msg.Headers.Clear();
return msg;
}
private string GetUrl(string api)
{
return string.Format("https://yourWSURL/something.asmx?op={0}", api);
}
public async Task Login(string user, string pass)
{
var msg = GetRequestMessage("LoginAsync", user, pass);
var _httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Add("SOAPAction", msg.Headers.Action);
msg.Headers.Clear();
var soapString = msg.ToString();
var response = await  _httpClient.PostAsync(GetUrl("Login"),
new StringContent(soapString, Encoding.UTF8, "text/xml"));
var content = await response.Content.ReadAsStringAsync();
var o = Deserialize(content);
return o;
}
}

That's it, I keep re-writing the method similar to Login. The implementation is to serialize the request and manually POST via HttpClient; then deserialize the response back to objects.

Translation between WP and Win8 Metro series: loading byte array into BitmapImage

1. November 2012 14:07 by Jerry in C#, Win8 Development, Windows Phone Development

WP

[code language=C#]
byte[] frameBuffer;
BitmapImage.SetSource(new MemoryStream(frameBuffer, 0, frameBuffer.Length));
[/code]

Win8

[code language=C#]
 var ms = new Windows.Storage.Streams.InMemoryRandomAccessStream();
                        ms.AsStreamForWrite().Write(frameBuffer, 0, frameBuffer.Length);
                        ms.Seek(0);
                        BitmapImage.SetSource(ms);
[/code]

it looks to me that Win8 just making thing complicated:(

Translation between WP and Win8 Metro series: async anonymous method in Win8

1. November 2012 13:48 by Jerry in C#, Win8 Development, Windows Phone Development

As I mentioned previously, I'm trying to develop a Win8 Metro version of IP CAM Coontroller, so I'm basically translating the WP coding into Win8. I'm going to post a series of blog post to record (and so benefit those googler with same problem) some of the interesting issue and topic.

WP coding:

[code language=C#]
Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            //do something here
                        }
                        );
[/code]

WIN8

[code language=C#]
 Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
                Windows.UI.Core.CoreDispatcherPriority.Normal,
                new Windows.UI.Core.DispatchedHandler(() =>
                {
                    //do something here
                }));
[/code]

This is not end of the story, by using the RunAsync like above, you will get a compiler warning from VS2012, and it's interesting that if you assign the returning result (of RunAsync) to a variable, the warning goes away. So the final version is like:

[code language=C#]
 var dummy = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
                Windows.UI.Core.CoreDispatcherPriority.Normal,
                new Windows.UI.Core.DispatchedHandler(() =>
                {
                    //do something here
                }));
[/code]

just for fun: sleep sort

29. June 2011 15:02 by Jerry in C#

there are some other versions of implementation in different programming languages, here is my c# version and I believe this sort algorithm will be very hot soon:)

[code language=C#]
using System;
using System.Collections.Generic;
using System.Text;

namespace SleepSort
{
    class Program
    {
       
        static void Main(string[] args)
        {
            int[] ints = { 1, 4, 2, 6, 3 };
            foreach (int i in ints)
            {
                SleepSort ss = new SleepSort(i);
                System.Threading.Thread t = new System.Threading.Thread(ss.Sort);
                t.Start();
            }

        }

       
    }

    public class SleepSort
    {
        int i;
        public  SleepSort(int i)
        {
            this.i = i;
        }

        public void Sort()
        {
            System.Threading.Thread.Sleep(i);
            Console.WriteLine(i);
        }
    }
}
[/code]