export ASP.NET BNR
skip to the main content area of this page
Documentatia e luata de la http://www.danielcostea.info/blog/index.php/2010/01/cum-am-implementat-serviciul-web-asp-net-pentru-infovalutar-ro/ cu aprobarea autorului

La sugestia lui Andrei Ignat, am decis sa scriu un tutorial cu modul in care am folosit serviciul web pentru cursul valutar, serviciu web expus prin infovalutar.ro.

Am facut un tutorial despre cum am implementat serviciul web (expus prin infovalutar.ro) pentru site-ul de stiri www.portalsm.ro.

O modalitate imediata de a folosi un serviciu web ar fi asa:

01ro.infovalutar.www.Curs curs = new ro.infovalutar.www.Curs();
02 
03try
04{
05    Response.Write(string.Format("  1 EUR {0}<br />", curs.GetLatestValue("EUR")));
06    Response.Write(string.Format("  1 USD {0}<br />", curs.GetLatestValue("USD")));
07    Response.Write(string.Format("100 HUF {0}<br />", curs.GetLatestValue("HUF") * 100));
08    Response.Write(string.Format("  1 XAU {0}<br />", curs.GetLatestValue("XAU")));
09}
10catch (Exception)
11{
12    Response.Write("Something unexpected happened.");
13}

Quick and dirty as putea spune.

Am sa enumar doua cazuri in care aceasta metoda nu corespunde asteptarilor mai mari.
1. Daca serviciul web e indisponibil in momentul apelului, nu avem ce valori sa afisam.
2. Pentru fiecare afisare pagina cere date de la serviciul web. Cu cat pagina este afisata mai frecvent, cu atat overhead-ul va fi mai consistent.

Cazul 1.
Pentru momentele in care pagina nu poate aduce datele de la serviciul web, avem nevoie sa persistam (am preferat sa nu traduc acest termen pentru a nu pierde din sens) aceste date in format XML (dar pot fi folosite si alte formate structurate cum e JSON).

Exemplu: fisierul exchange.xml

01<?xml version="1.0" encoding="utf-8"?>
02<exchange_rate date="13.01.2010">
03  <currency>
04    <name>EUR</name>
05    <unit>1</unit>
06    <value>4.1215</value>
07    <percent>-0.34 %</percent>
08    <difference>-0.0140</difference>
09  </currency>
10  <currency>
11    <name>USD</name>
12    <unit>1</unit>
13    <value>2.8388</value>
14    <percent>-0.43 %</percent>
15    <difference>-0.0123</difference>
16  </currency>
17</exchange_rate>

Pentru tag-urile unit, name si value nu este necesara nici o explicatie, am sa ma opresc asupra ultimelor doua, percent si difference.
Percent reprezinta evolutia procentuala dintre valoarea curenta si valoarea precedenta a cursului valutar.
Difference reprezinta evolutia diferentiala dintre valoarea curenta si valoarea precedenta a cursului valutar.
Daca pentru valoarea curenta am folosit metoda curs.GetLatestValue(currency), pentru valoarea precedenta am folosit curs.GetValue(currentDate.AddDays(-1), currency), unde currentDate este data curenta intoarsa de sistem (atentie la diferentele de curs orar daca faceti hosting-ul pe servere din alte zone geografice), iar currency este valuta pentru care se doreste cursul.

Pentru cazul in care fisierul exchange.xml nu este creat sau s-a pierdut putem regenera acest fisier cu date generice furnizand aplicatiei un string cu continut XML, dupa cum urmeaza.

1string exchange = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
2 
3System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();
4 
5xmlDocument.LoadXml(exchange);
6 
7xmlDocument.Save(AppDomain.CurrentDomain.BaseDirectory + "/exchange.xml");

Pentru ca datele locale sa fie consistente cu cele de la serviciul web, le citesc la un interval de 30 de minute (poate fi ales orice interval dorit) in Global.asax cu o functie apelata pe un thread luat din ThreadPool si regenerez fisierul XML cu date proaspete. Exemplific prin portiunea de cod de mai jos.

1void Application_Start(object sender, EventArgs e)
2{
3    object stateExchange = null;
4 
5    System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(Functions.GetExchange), stateExchange);
6}

In acest moment m-am asigurat ca am datele in format XML pentru orice scenariu.

Cazul 2.
In cazul unui portal sau al unui ziar electronic unde pagina pe care avem cursul valutar este ceruta de zeci sau sute de ori pe secunda, este necesara pastrarea acestor date (intreg fisierul XML) in cache, atata timp cat fisierul XML ramane neschimbat. Nu este de dorit ca pagina sa faca citiri din fisierul XML prea des. (aici doresc sa multumesc pentru sugestii unui coleg din RONUA, Andrei Rinea pentru combinatia cu functii callback si caching)

01XmlDocument xmlDocument = HttpRuntime.Cache["exchange"] as XmlDocument;
02 
03if (xmlDocument == null)
04{
05    xmlDocument = new XmlDocument();
06 
07    if (File.Exists(Server.MapPath("~/exchange.xml")))
08        xmlDocument.Load(Server.MapPath("~/exchange.xml"));
09    else
10        xmlDocument.LoadXml("");
11 
12    HttpRuntime.Cache.Insert("exchange", xmlDocument, new CacheDependency(Server.MapPath("~/exchange.xml")), Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration);
13}

Am rezolvat si problema de performanta.

In continuare mai am doua sugestii utile, una legata de functionalitate si cealalta de design.
A) Daca avem un site in care cursul valutar apare in mai multe locuri (pagini), e de preferat sa incapsulam totul intr-un user control (aici ma refer la aducerea datelor din XML si pastrarea lor in cache).
B) In cazul in care cursul valutar urmeaza sa fie folosit pe pagini diferite din punct de vedere al design-ului, poate chiar pe site-uri diferite, putem sa separam partea de design de partea de date folosind XSLT ca in exemplul de mai jos.

1MemoryStream stream = new MemoryStream();
2XmlDocument XmlDoc = new XmlDocument();
3XmlDoc.Load(Server.MapPath("~/exchange.xml"));
4XslCompiledTransform XslDoc = new XslCompiledTransform();
5XslDoc.Load(Server.MapPath("~/exchange.xslt"));
6XslDoc.Transform(XmlDoc, null, stream);
7stream.Seek(0, SeekOrigin.Begin);
8StreamReader reader = new StreamReader(stream);
9exchange = reader.ReadToEnd();

Urmeaza fisierul exchange.xslt.

01<?xml version="1.0" encoding="utf-8"?>
02<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
03  <xsl:template match="*">
04    <div>
05      <h2>Curs valutar: <xsl:value-of select = "@date" /></h2>
06    </div>
07    <div>
08      <table cellpadding="1px" cellspacing="0" style="font-size:8pt; margin: 0 auto; padding: 5px 0; text-align:right;">
09        <xsl:apply-templates />
10      </table>
11    </div>
12  </xsl:template>
13 
14  <xsl:template match="currency">
15    <tr>
16      <td><xsl:value-of select = "unit" /></td>
17      <td><xsl:value-of select = "name" /></td>
18      <td><xsl:value-of select = "value" /></td>
19      <td>
20        <xsl:choose>
21          <xsl:when test = "difference &gt; 0">
22            <img src='http://www.portalsm.ro/Satu-Mare/Images/up-arrow.png' alt='' style='vertical-align: -2px;' />
23          </xsl:when>
24          <xsl:when test = "difference &lt; 0">
25            <img src='http://www.portalsm.ro/Satu-Mare/Images/down-arrow.png' alt='' style='vertical-align: -2px;' />
26          </xsl:when>
27          <xsl:when test = "difference = 0">
28            <img src='http://www.portalsm.ro/Satu-Mare/Images/stop.gif' alt='' style='vertical-align: -2px;' />
29          </xsl:when>
30        </xsl:choose>
31      </td>
32      <td><xsl:value-of select = "difference" />,</td>
33      <td><xsl:value-of select = "percent" /></td>
34    </tr>
35  </xsl:template>
36</xsl:stylesheet>

E in pregatire codul sursa pentru cei care sunt interesati.

Resurse pentru preluat cursurile BNR/BCE
de catre programatori / site-uri / oameni
obsolete
  • cursuri.rss
  • rss.aspx