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);

 

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.

System.Runtime error en WP8 y librerías portables

Un caso raro es cuando usamos librerías portables y Microsoft.Bcl no da un error de compilación System.Runtime. En un primer momento no tenemos muy claro de que se trata y tampoco nos da ninguna pista de que puede ser.

Después de buscar y buscar resulta ser un bug de NuGet en que te pone una redirección en el archivo app.config

 

<dependentAssembly>

<assemblyIdentity name=”System.Runtime” publicKeyToken=”b03f5f7f11d50a3a” culture=”neutral” />

        <bindingRedirect oldVersion=”0.0.0.0-2.6.3.0″ newVersion=”2.6.3.0″ />

</dependentAssembly>

 

De modo que debes eliminar esa línea para que todo funcione correctamente otra vez.

<dependentAssembly>

<assemblyIdentity name=”System.Runtime” publicKeyToken=”b03f5f7f11d50a3a” culture=”neutral” />

</dependentAssembly>

Llibreries portables i Thread UI

Amb .NET 4 apareixen les llibreries portables que penso que són fantàstiques per poder fer una programació completament reutilitzable en les diferents tecnologies que tenim disponibles amb Microsoft .NET : Windows Apps, Windows 8 Store, Windows Phone i Silverlight.

Hem de saber però que aquest tipus de llibreries utilitzen un subconjunt de les característiques que poden tenir en comú les diferents tecnologies i abans de posar-nos a fer res hem de consultar quines funcionalitats ens permeten fer les llibreries portables.

Hi ha un aspecte que sempre ens trobem que és com fem referència al Thread UI de l’aplicació. El Dispatcher no el podem fer servir des de les llibreries portables. Tenim la clase SynchronizationContext per fer-ho.

De fet, l’ús és molt senzill, declarem una variable a nivell de classe com aquesta

#región Fields

private SynchronizationContext _context = SynchronizationContext.Current;

#endregion

 

I llavors sempre que vulguem assegurar-nos que una funció s’executi al mateix thread que ha creat la classe llavors:

if (SynchronizationContext.Current == _context)

{

/*Do something */

}

else

{

/*El thread actual no és el mateix */

_context.Post(obj =>

{

/*Do something */

},null);

}

Fixa’t que el que mira és si el thread actual és el mateix que ha creat la classe, per tant l’únic que ens hem de preocupar és que el Thread UI creí la classe.
Més informació:

Portable Class Library and ObservableCollection, updating UI Thread

Portable class library equivalent of Dispatcher.Invoke or Dispatcher.RunAsync

 

 

 

Ajax i download file

descarga

Amb .Net utilitzar Ajax és super senzill, tant sols hem de col·locar un control UpdatePanel i tota la resta és el mateix.

Però hi ha un cas que no deixa de ser curiós. Quan un postback retorna una cadena binaria que representa un fitxer els UpdatePanels fan que no funcioni adequadament. Normal, hem de tenir present que els UpdatePanel serveixen perquè el contingut del seu interior s’actualitzi i no pas per descarregar fitxers. Hi hi algunes tècniques que ho poden fer però no deixa de ser alternatives sobre les eines que disposes.

Una de les maneres més senzilles és dir-l’hi a l’UpdatePanel que al accionar el botó de descarrega executi un Postback enlloc de un AsyncPostback. Per això té el triggers, per assignar controls de la pàgina per tal de que provoquin un postback complet de la pàgina.

Però en el cas de tenir un ListView o qualsevol altre control que encapsuli controls la unica manera és fer-ho des de codi. Però els update panels no els hi agrada massa que els hi toquis els triggers per codi. Que no et fa cas vaja.

Llavors ens queda una opció que per mi és molt fina i neta. Utilitzar ScriptManager per indicar que l’event click del botó es fagi per Postback i no pas per AsyncPostback
ScriptManager.GetCurrent(this.Page).RegisterPostBackControl(this.lnkDownload);

Posa aquest tros de codi en l’event DataBound del teu control ListView. Fàcil i funciona.

 

Més informació:

Download feature not working within update panel in asp.net

Simple way to do File download with UpdatePanel and overlay ProgressIndicator