Calling service using SOAP message (.NET)

If you need to call a web service at low-level this is a good post for you.

For this purpose, you have to use HttpWebRequest and HttpWebResponse for treating the call. With Visual Studio’s auto-generated proxy for calling web methods of a web service hides the communication language between client and server. You do not have any control about the SOAP message generated. The only way is to call web methods using low-level protocol (HttpRequest)

Look an example below:


HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("<<Url of your web method>>");

request.Headers["SOAPAction"] = <<web method URI>>;
request.ContentType = "text/xml;charset=\"utf-8\"";
request.Accept = "text/xml";
request.Method = "POST";

As you can see I have created the request using the information related to the web service. Next step is to build the SOAP Envelope

//Global variable for helping

static string soapEnvelope = @"<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'><soap:Header></soap:Header><soap:Body></soap:Body></soap:Envelope>";


StringBuilder sb = new StringBuilder(soapEnvelope);
sb.Insert(sb.ToString().IndexOf("</soap:Header>"), String.Format("<AuthorizationToken xmlns=\"<<some URI>>"><Token>{0}</Token></AuthorizationToken>", authToken.Token));
sb.Insert(sb.ToString().IndexOf("</soap:Body>"), String.Format("<YOURMethod xmlns=\"<<some URI>>"><Parameter1>{0}</Parameter1><Parameter2>{1}</Parameter2></YOURMethod>", serviceName, methodName));

XDocument soapEnvelopeXml = XDocument.Parse(sb.ToString());

 

And finally, make the call


IAsyncResult result = request.BeginGetRequestStream((IAsyncResult asynchronousResult) =>
{

//inserting soap message in the request

using (Stream postStream = request.EndGetRequestStream(asynchronousResult))
{
soapEnvelope.Save(postStream);
postStream.Close();
}

request.BeginGetResponse(new AsyncCallback(asyncresult =>
{
XElement res = null;
HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
XDocument res = XDocument.Parse(responseString);
XNamespace ns = "<<your namespace>>";

streamResponse.Close();
streamRead.Close();

response.Close();

XElement results = res.Descendants(ns + "<<your method name>>Response").FirstOrDefault();
if (results == null)
{
}
else
{
res =  results.Elements().FirstOrDefault();
}
}), request);
}, null);

 

Anuncis

DataContractSerializer no deserialitza correctament

Hi poden haver moltes raons perquè el DataContractSerializer no deserialitzi bé. Però he pensat que era el millor títol que podia donar ja que en realitat és un problema que sembli exactament el que diu: Que no deserialitza correctament.

Però en realitat no és així, el problema està en què no sabem a vegades com funciona del tot.

Aquesta és la instrucció:


Countries = MVVMUtils.DataContractDeserializeObject<Countries>(e.Result.ToString());

I aquesta és la classe Countries


[CollectionDataContract(Namespace="")]
public class Countries : List<Country> { }

[DataContract(Namespace = "")]
public class Country {
[DataMember]
public string cty_key { get; set; }

[DataMember]
public string cty_code { get; set; }

[DataMember]
public string cty_idd_code { get; set; }
}

I aquest el fitxer XML que volem deserialitzar


<Countries xmlns="">
<Country>
<cty_key>8C445CE2-5AF6-48B6-BDDA-B10B77724566</cty_key>
<cty_code>United States</cty_code>
<cty_idd_code>1</cty_idd_code>
</Country>
<Country>
<cty_key>18227E69-725D-4A17-8245-4E2683094ED0</cty_key>
<cty_code>Canada</cty_code>
<cty_idd_code>1</cty_idd_code>
</Country>
<Country>

Si observes bé les propietats no estan ordenades alfabèticament. Aquest XML s’ha extret d’un altre sistema de serialització. Si s’hagués fet amb el DataContractSerializer estarien completament ordenades.

Aquest és el problema.DataContractSerializer necessita que les propietats estiguin ordenades i quan això no és possible llavors hem de indicar un atribut més al model : Order

Per tant el model hauria de ser:


[CollectionDataContract(Namespace="")]
public class Countries : List<Country> { }

[DataContract(Namespace = "")]
public class Country {
[DataMember(Order=1)]
public string cty_key { get; set; }

[DataMember(Order = 2)]
public string cty_code { get; set; }

[DataMember(Order = 3)]
public string cty_idd_code { get; set; }
}

Més informació:
Why needs DataContractSerializer alphabetically sorted XML?

Millorar ObservableCollection

A StackOverflow s’ha publicat un exemple de com es pot fer un ObservableCollection més efectiu.

ObservableCollection és una llista genèrica que implementa INotifyPropertyChanged i per tant avisa a la UI dels canvis que hi ha dins la llista. Bàsicament si s’afegeix o es borra algun element.

El problema és que no és Thread safe ni tampoc Thread Affinity. Per tant, quan un Thread que no és l’UI actualitza aquesta llista es genera una excepció.

El segon, és que per cada operació d’afegir o borrar es llencen els events corresponent per notificar a UI del canvi sense l’opció de poder-los agrupar i que només es faci una vegada la notificació després d’un conjunt d’operacions.

Consulteu l’exemple que és força interessant.

Fast performing and thread safe observable collection

 

 

internal member

En orientació objectes tenim la capacitat de marcar la visibilitat de les propietats, camps o mètodes.

Els més coneguts: public, protected i private

Potser no tant conegut és internal. Internal significa que un membre és només public dins del seu enssamblat. Fora d’ell és completament privat. És molt útil quan construïm llibreries de classes que son suport d’altres projectes i volem protegir propietats per tal de que no ens facin un mal ús fora del nostre projecte.

El problema, el podem tenir quan necessitem serialitzar una classe que té una propietat d’aquest tipus. L’error que ens pot sortir és semblant a aquest:

The data contract type ‘Secondary.Project.MVVM.ViewModel.ViewModelBase’ cannot be deserialized because the property ‘DisplayName’ does not have a public setter. Adding a public setter will fix this error. Alternatively, you can make it internal, and use the InternalsVisibleToAttribute attribute on your assembly in order to enable serialization of internal members – see documentation for more details. Be aware that doing so has certain security implications.

Tal com diu, l’internal port ser la causa de l’error i per resoldre’l ens demana de posar un atribut dins assembly.cs que ens permet marcar enssamblats de confiança per tal de que l’internal passi a ser una propietat publica per ell.

Personalment pensó que es una mica arriscart però pot ser útil quan no hi ha més possiblitats.

[assembly: InternalsVisibleTo("Main.Project")]

D’aquesta manera estic marcant que el projecte Main.Project és de confiança i per tant tindrà aquest membre com a public.

Pot ser interessant saber-ho, pot ser útil usar-lo.

OnDeserialized/OnSerialized Attributes

In .NET we can serialize and deserialize objects for saving state from memory to storage or for transfering complex structures through the Internet.
DataContractAttribute and SerializableAttribute are the options that we have to achieve this goal. The basic differences between them are that DataContract is WCF technology and Serialization is older than DataContract. A great feature of DataContract is that it can serialize private fields. (FYI : In Windows Phone it cannot)
Private fields or private properties or non-serializable fields could be a problem for us. Fortunately, we have OnDeserializedAttribute / OnDeserializingAttribute and OnSerializedAttribute / OnSerializingAttribute that when applied to a method, specifies that the method is called immediately after / during  deserialization or serialization of an object.
Here, there are the examples from MSDN


[OnSerializing()] internal void OnSerializingMethod(StreamingContext context) {

member2 = "This value went into the data file during serialization.";

}

[OnSerialized()] internal void OnSerializedMethod(StreamingContext context) {

member2 = "This value was reset after serialization.";

}

[OnDeserializing()] internal void OnDeserializingMethod(StreamingContext context) {

member3 = "This value was set during deserialization";

}

[OnDeserialized()] internal void OnDeserializedMethod(StreamingContext context) {

member4 = "This value was set after deserialization.";

}

More information

OnDeserializingAttribute Class

OnDeserializedAttribute Class

OnSerializingAttribute Class

OnSerializedAttribute Class

LINQ a XML

Dejadme que os hable un poco de Linq a XML porque Linq es un tipo de lenguaje que personalmente me gusta mucho y creo que siempre estoy hablando de el para acceder a base de datos pero nunca para acceder a documentos XML.

Hasta el Framework 3.5 SP1 para poder trabajar con documentos XML utilizabas la clase System.Xml.XmlDocument que construía en memoria una representación del archivo en modo de árbol. Este árbol tenía sus nodos – clase XmlNode – que podían ser de distintos tipos – System.Xml.XmlElement, Sys-tem.Xml.XmlText, System.Xml.XmlAttribute, … -. La forma de trabajar de estas clases no era compleja – pues para realizar una búsqueda de un nodo o atributo dentro de esta estructura usabas XPath – pero si que complicaba un poco el construir la estructura en si.

Linq a Xml permite ejecutar consultas Linq en estructuras XML, que al igual, residen en memoria y trabajan bien con XPath pero con operadores específicos que permiten la navegación – Descendants, Ancestors, Siblings – como si fuera una expresión XPath.

Las clases que se utilizan en Linq a Xml son System.Xml.Linq.XDocument, System.Xml.Linq.XElement y System.Xml.Linq.XAttribute, System.Xml.Linq.XName y algunos otros más.

Las claves

Linq a Xml permite cargar documentos XML desde ficheros o directamente desde cadenas de texto con formato y permite a su vez serializar el contenido a ficheros o stream. La creación de los arboles XML en memoria se hacen de una forma simple y rápida. La manipulación de la estructura es en memoria y soporta las consultas Linq.

XElement y XAttribute

Los elementos y los atributos están representados por estas dos clases XElement y XAttribute usando una sintaxis muy natural para poder construir los nodos. Los constructores utilizan XName como parámetro que implícitamente se crea con una cadena de texto. XName provee de un fácil uso de los identificadores del espacio de nombres.

En el siguiente ejemplo ves como crear la estructura XML

<br /><br />&lt;Person KeenOnGolf=”true”&gt;<br /><br />&lt;Name&gt;Steve&lt;/Name&gt;<br /><br />&lt;Age&gt;52&lt;/Age&gt;<br /><br />&lt;/Person&gt;<br /><br />

es

C#

<br /><br />var e = new XElement("Person",<br /><br />new XAttribute("KeenOnGolf", true),<br /><br />new XElement("Name", "Steve"),<br /><br />new XElement("Age", 52));<br /><br />

Los elementos XML se pueden construir de otras formas:

Usando un XmlReader

<br /><br />var e1 = XElement.Load(xmlReader);<br /><br />

Usando un fichero

<br /><br />var e2 = XElement.Load(@"c:\miDocumento.xml");<br /><br />

Usando una cadena de texto

<br /><br />var e3 = XElement.Parse(@"&lt;Person KeenOnGolf='true'&gt;<br /><br />&lt;Name&gt;Steve&lt;/Name&gt;<br /><br />&lt;Age&gt;52&lt;/Age&gt;<br /><br />&lt;/Person&gt;");<br /><br />

Aplicando Linq a XElement

Cuando aplicas consultas Linq a este tipo de estructuras el resultado es un IEnumerable de XElement. El trato debe ser el mismo que en colecciones internas con la particularidad de que aquí estás tratando con elemento de tipo XElement.

El siguiente ejemplo se muestra como recuperar la persona que es aficionado al golf (KeenOnGolf a true). Para ello se utiliza una estructura XML definida como:

<br /><br />var people = new XElement("Persons",<br /><br />new XElement("Person",<br /><br />new XAttribute("KeenOnGolf", true),<br /><br />new XElement("Name", "Steve"),<br /><br />new XElement("Age", 52)),<br /><br />new XElement("Person",<br /><br />new XAttribute("KeenOnGolf", false),<br /><br />new XElement("Name", "Peter"),<br /><br />new XElement("Age", 30)),<br /><br />new XElement("Person",<br /><br />new XAttribute("KeenOnGolf", false),<br /><br />new XElement("Name", "John"),<br /><br />new XElement("Age", 44)),<br /><br />new XElement("Person",<br /><br />new XAttribute("KeenOnGolf", false),<br /><br />new XElement("Name", "Mike"),<br /><br />new XElement("Age", 50))<br /><br />);<br /><br />

La consulta Linq seria:

<br /><br />var query= from p in people.Elements("Person")<br /><br />where bool.Parse(p.Attribute("KeenOnGolf").Value)==true<br /><br />select p; foreach (XElement person in query) {<br /><br />}<br /><br />

Construyendo elementos XML De la misma forma que puedes consultar los valores de los elementos de una estructura en XML también puedes crear nuevas estructuras usando Linq. Este es una de las características que ya he hablado en este libro de Linq – permitir crear estructuras nuevas a partir de otras en una consulta -. Así pues en el ejemplo siguiente ves como puedes crear otros elementos XElement.

<br /><br />var query2 = from p in people.Elements("Person")<br /><br />where bool.Parse(p.Attribute("KeenOnGolf").Value) == false<br /><br />select new Xelement("PersonsNonKeen",<br /><br />new Xelement("Name",p.Element("Name").Value),<br /><br />new XElement("Age",p.Element("Age").Value));<br /><br />foreach (XElement person in query2) {}<br /><br />

El resultado seria la estructura siguiente:

<br /><br />&lt;PersonsNonKeen&gt;<br /><br />&lt;Person KeenOnGolf=”false”&gt;<br /><br />&lt;Name&gt;Peter&lt;/Name&gt;<br /><br />&lt;Age&gt;30&lt;/Age&gt;<br /><br />&lt;/Person&gt;<br /><br />&lt;Person KeenOnGolf=”false”&gt;<br /><br />&lt;Name&gt;John&lt;/Name&gt;<br /><br />&lt;Age&gt;44&lt;/Age&gt;<br /><br />&lt;/Person&gt;<br /><br />&lt;Person KeenOnGolf=”false”&gt;<br /><br />&lt;Name&gt;Mike&lt;/Name&gt;<br /><br />&lt;Age&gt;50&lt;/Age&gt;<br /><br />&lt;/Person&gt;<br /><br />&lt;/PersonsNonKeen&gt;<br /><br />

Más información

Para más información puedes comprar mi libro Guia Práctica de Asp.net

Threading Considerations for Binding and Change Notification in XAML

I read a very similar article about how to work with MVVM and multithreading aspects. The problem is well known; in XAML’s Binding features, if you want to communicate any change to UI through Binding object, you need to implement INotifyPropertyChanged on model class, this interface has an event named PropertyChanged that is needed to update the UI, however in multithreading scenarios, you could have secondary threads modifying the model and this implies that the PropertyChanged event will be caught on a secondary thread and then you will the following exception:

Threads other than the UI thread are not allowed to access or manipulate UI objects

In this article you can read how to solve the problem in Silverlight (for WPF and WP as well) but it is not suitable for Portable Library scenarios. In Portable Library we have neither the Deployment class or even the Dispatcher class, so we have to take the SynchronizationContext class.

Implementation is really easy, you need to declare a global class field as follows

private SynchronizationContext _context = SynchronizationContext.Current;

Now, you have in _context the thread which created the class, you need to ensure that this is the same as controls’ thread: Thread UI

The next step is :


protected virtual void OnPropertyChanged(string propertyName)

{

PropertyChangedEventHandler handler = this.PropertyChanged;

if (handler != null)

{

var e = new PropertyChangedEventArgs(propertyName);

if (SynchronizationContext.Current == _context)

{

handler(this, e);

}

else

{

_context.Post(obj =>

{

handler(this, e);

}, null);

}

}

}

_context.Post is called only if the current thread is not the same as the creator thread.