Monday, 21 March 2011
Prezentace Moderní trendy ve vývoji aplikací
Přibližně před rokem jsem u dvou firem začínal sérii technologických kurzů subjektivním shrnutím změn (nejen) v aplikacích psaných v .Net Frameworku. Nedávno jsme ji s kolegou náhodou otevřeli a pobavili jsme se nad tím, jak je rok v IT stále dlouhá doba a že zde dvojnásobně platí “tempus fugit”. Napadlo mě, že se nad prezentací možná se pobaví i někdo další, hlavně v pasážích, kde jemně naznačuju zálibu Microsoftu v zařezávání technologií.
U prezentace je třeba mít na paměti:
- Jedná se jen o osnovu “přehledové“ a cca dvouhodinové přednášky.
- Témata, typy projektů a technologie jsou v přednášce voleny podle zájmu zákazníka.
- Snažil jsem se nebýt hned v této úvodní přednášce příliš ostrý a konfliktní.
- Zvolená témata se týkala oblastí, které jsme v dalších dnech probíraly detailněji na konkrétních projektech vytvořených na návazných kurzech. Po pár zkušenostech si myslím, že jediný smyslupný kurz zabývající se technologií či programovacím jazykem je ten, na kterém píšete před účastníky kód. Tato přednáška byla koncipována jako motivační úvod k dalším tématům.
Monday, 21 March 2011 13:11:41 (Central Europe Standard Time, UTC+01:00)
.NET Framework | ASP.NET | C# | Compact .Net Framework | LINQ | RX Extensions | Silverlight | Web Services | Windows Forms | WP7
Wednesday, 07 May 2008
Stále neopravený bug při volání metody HttpWebRequest.BeginGetResponse?
Ještě při psaní jedné aplikace běžící na .Net Framework verze 2.0 jsem objevil podivnou chybu, kdy se při asynchronním stahování stránek pomocí třídy HttpWebRquest asynchronní přístup skoro nelišil od synchronní verze. Metoda BeginGetResponse vrátila řízení volajícímu kódu teprve poté, co došlo ke stažení celé stránky. Dle Microsoftu se problém objevoval i ve verzi 1.1 a příčinou jsou "antipatie" mezi metodou BeginGetResponse a konfigurací DNS.
Myslel jsem si, že tento bug je ve verzi 3.5 odstraněn, ale dnes jsem zjistil, že bugy stejně jako kočky mají minimálně devět životů. U mě stačí -někdy-zadat adresu začínající na "www" a z asynchronního volání je volání synchronní. Zvláštní a k vzteku je, že že nelze stoprocentně napsat návod na reprodukci bugu (zkoušel jsem vyčistit i DNS cache). Bug se ale projevuje při připojení přes ADSL, O2 HSDPA i TMO GPRS/EDGE.
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
namespace WebTest
{
class Program
{
static void Main(string[] args)
{
bool done = false;
WebRequest req = WebRequest.Create("http://www.vyvojar.cz");
req.BeginGetResponse(delegate(IAsyncResult result)
{
done = true;
Console.WriteLine(String.Format("Done: {0}", DateTime.Now.ToLongTimeString()));
req.EndGetResponse(result).Close();
Console.WriteLine();
}
,null);
while(!done)
{
Console.WriteLine("Not done");
}
Console.WriteLine("Stop");
Console.ReadLine();
}
}
}
Jedinou obranou proti náhodným výkyvům v matrixu registrovaných služeb z předzjednaného řádu a Microsoftem sponzorované harmonie (Disclaimer: Tato obrana zabírá jen na popsaný bug, ale proti výkyvům univerza pocházejících od zeleného viru, a to i v jeho totálně dezorientované a nejméně hostilní mutaci "Džamila Stehlíková", je zcela bemocná ) je po mnoha mých pokusech nahrazení názvu domény v url adrese její IP adresou (jestliže máte pod kontrolou nastavení webového serveru, na kterém běží stránky-webové služby, protože jinak nemusí samozřejmě ip adresa v hlavičce HOST dostačovat...). Ip adresu zjistíme jednoduše voláním metod z třídy DNS. Volání metod třídy DNS kupodivu žádné zpoždění nevykazuje...
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Threading;
namespace WebTest
{
class Program
{
static void Main(string[] args)
{
bool done = false;
IPHostEntry address = Dns.GetHostEntry("www.vyvojar.cz");
HttpWebRequest req = WebRequest.Create(String.Format("http://{0}", address.AddressList[0].ToString())) as HttpWebRequest;
req.BeginGetResponse(delegate(IAsyncResult result)
{
done = true;
Console.WriteLine(String.Format("Done: {0}", DateTime.Now.ToLongTimeString()));
req.EndGetResponse(result).Close();
Console.WriteLine();
}
,null);
while(!done)
{
Console.WriteLine("Not done");
}
Console.WriteLine("Stop");
Console.ReadLine();
}
}
}
Wednesday, 07 May 2008 12:48:42 (Central Europe Standard Time, UTC+01:00)
.NET Framework | Web Services
Monday, 25 October 2004
Webové služby obohacené o SoapExtensionReflector
Když jsem psal článek o http modulech pro Interval s příkladem http modulu pro dynamické přidání dokumentace k operacím webových služeb, stále jsem trpěl obsedantní představou, že by mělo existovat lepší API pro práci s generovaným WSDL webové služby.
Představa lepšího API mě znovu přepadla při přípravě staršího spotu o http modulu pro změnu URL adresy webové služby.
A nepletl jsem se. Pro tyto účely je zde třída SoapExtensionReflector, i když její význam Microsoft cudně v MSDN skrývá pod nepřátelskou větu "The SoapExtensionReflector type supports the .NET Framework infrastructure and is not intended to be used directly from your code", která má ale na mě přesně opačný účinek, protože vyburcuje moji zvědavost lačně ohledávající vnitřnosti .Net Frameworku.;)
V potomku abstraktní třídy SoapExtensionReflector je nutné přepsat metodu ReflectMethod. Metoda ReflectMethod je volána pro každou metodu webové služby. Podstatné informace o právě zpracovávané webové metodě jsou uloženy v v zděděné vlastnosti ReflectionContext.
Příklad přidání dokumentace k webové službě v potomku třídy SoapExtensionReflector. Stejně jako v článku na Intervalu platí, že dokumentace k metodě musí být uložena v sekci appSettings, v elementu add, a že název klíče (key) musí být shodný s názvem metody, k němuž je přidán suffix Method, a text dokumentace tvoří hodnota atributu value.
using System;
using System.Collections;
using System.Configuration;
using System.Web.Services.Description;
namespace AddDocExtension
{
/// <summary>
/// Zkušební SoapExtensionReflector pro přidání dokumentace k webové metodě
/// </summary>
public class ImportDocExtension : SoapExtensionReflector
{
#region Private constants
private const string METHOD_KEY_SUFFIX = "Method";
#endregion Private constants
#region Private static fields
private static Hashtable m_operationsDoc;
#endregion Private fields
#region Constructors
/// <summary>
/// Statický konstruktor
/// </summary>
static ImportDocExtension()
{
readConfig();
}
/// <summary>
/// Konstruktor
/// </summary>
public ImportDocExtension() : base()
{
}
#endregion Constructors
#region Public methods
/// <summary>
/// Přidání dokumentace ke každé operaci
/// </summary>
public override void ReflectMethod()
{
string opName = ReflectionContext.Operation.Name;
if (m_operationsDoc.ContainsKey(opName))
{
ReflectionContext.Operation.Documentation = (string) m_operationsDoc[opName];
}
}
#endregion Public methods
#region Private static methods
/// <summary>
/// Načtení dokumentace k metodám z konfiguračního souboru
/// </summary>
private static void readConfig()
{
m_operationsDoc = new Hashtable();
string[]keys = ConfigurationSettings.AppSettings.AllKeys;
foreach (string key in keys)
{
if (key.EndsWith(METHOD_KEY_SUFFIX))
{
string hashKey = key.Substring(0, key.LastIndexOf(METHOD_KEY_SUFFIX));
string hashValue = ConfigurationSettings.AppSettings[key];
m_operationsDoc.Add(hashKey, hashValue);
}
}
}
#endregion Private static methods
}
}
SoapExtensionReflector musí být zaregistrován v konfiguračním souboru webové služby v sekci webServices.
<webServices>
<soapExtensionReflectorTypes>
<add type="AddDocExtension.ImportDocExtension,AddDocExtension" />
</soapExtensionReflectorTypes>
</webServices>
Monday, 25 October 2004 19:04:00 (Central Europe Standard Time, UTC+01:00)
Web Services
Monday, 13 September 2004
Http modul pro změnu URL adresy ve WSDL webové služby
Webové služby v ASP.NET generují dynamické WSDL, ve kterém je adresa služby (obsah elementu soap:address) dynamicky určena podle url původního požadavku. Například při použití reverzní proxy by se hodilo určit adresu ve wsdl dokumentu staticky a přitom stále ponechat na ASP.NET generování většiny elementů ve wsdl dokumentu.
K tomuto účelu jsem napsal http modul pro změnu adresy. V kódu se předpokládá, že nové url webové služby je zadáno ve web.config v sekci appSettings pod klíčem newUrl a že k službě je přistupováno pouze přes protokol SOAP.
using System;
using System.Web;
using System.IO;
using System.Xml;
using System.Diagnostics;
namespace RSTEIN.HttpModules
{
///
/// Modul pro změnu
///
public class ChangeUrlModule : IHttpModule
{
#region private constants
private const string WSDL_REQUEST = "wsdl";
private const string SOAP_NAMESPACE = "http://schemas.xmlsoap.org/wsdl/soap/";
private const string SOAP_PREFIX = "soap";
private const string LOCATION_NAME = "location";
private const string ADDRESS_NAME = "address";
#endregion private constants
#region private variables
private readonly string m_newServiceUrl;
#endregion private variables
#region Constructors
///
/// Konstruktor
///
public ChangeUrlModule()
{
m_newServiceUrl = System.Configuration.ConfigurationSettings.AppSettings["newUrl"];
}
#endregion Constructors
#region IHttpModule Members
///
/// Inicializace modulu - Součást rozhraní
///
///
public void Init(HttpApplication context)
{
if (m_newServiceUrl != String.Empty)
{
context.BeginRequest +=new EventHandler(context_BeginRequest);
context.EndRequest +=new EventHandler(context_EndRequest);
}
}
///
/// Součást rozhraní
///
public void Dispose()
{
}
#endregion
#region private methods
//Zapsání jiného URL
private void context_EndRequest(object sender, EventArgs e)
{
string path = HttpContext.Current.Request.RawUrl.ToLower();
if (isWSDLRequest())
changeUrl();
}
//Změna Url www služby
private void changeUrl()
{
HttpResponse response = HttpContext.Current.Response;
XmlDocument doc = new XmlDocument();
MemoryStream originalStream = ((FilterStream)response.Filter).InnerStream;
originalStream .Position = 0;
try
{
XmlTextReader reader = new XmlTextReader(originalStream);
doc.Load(reader);
}
catch (Exception e)
{
Trace.WriteLine("Invalid response");
return;
}
XmlNamespaceManager namManager = new XmlNamespaceManager(doc.NameTable);
namManager.AddNamespace(SOAP_PREFIX, SOAP_NAMESPACE);
XmlNode locationNode = getLocationAttribute(doc);
locationNode.Value = m_newServiceUrl;
response.Clear();
doc.Save(response.Output);
}
//Vyhledání atributu location elementu soap:address
private XmlNode getLocationAttribute(XmlDocument doc)
{
XmlNode addressNode = doc.GetElementsByTagName(ADDRESS_NAME, SOAP_NAMESPACE)[0];
return addressNode.Attributes["location"];
}
#endregion private methods
//přiřazení filtru na objekt Response
private void context_BeginRequest(object sender, EventArgs e)
{
if (isWSDLRequest())
HttpContext.Current.Response.Filter = new FilterStream(HttpContext.Current.Response.Filter);
}
//Kontrola, zda se jedná o WSDL požadavek
private bool isWSDLRequest()
{
string path = HttpContext.Current.Request.RawUrl.ToLower();
if (path.EndsWith(WSDL_REQUEST))
return true;
return false;
}
}
}
O významu http modulů a jejich registraci ve web.config se více dočtete v mém starším článku na Interval.cz.
Monday, 13 September 2004 15:12:00 (Central Europe Standard Time, UTC+01:00)
Web Services
Wednesday, 19 May 2004
Interval - článek Vývoj sofistikovaných WWW služeb v .Net Frameworku
Na Intervalu mi dnes vyšel článek, který vysvětluje vytváření WWW služeb s použitím nového API pro příjem a zasílání zpráv ve Web Services Enhancements 2.0. Článek je úvodem do světa WSE, v dalších článcích se chci se zaměřit na vysvětlení jednotlivých standardů (ws:addressing, ws:security, DIME atd.). Standardy implementované ve WSE konečně začínají zbavovat WWW služby etikety sice důležité, ale zatím nezralé technologie, které chybí například životně důležité standardy pro bezpečnou komunikaci. WWW služby určené k překonání komunikačních bariér mezi různými operačními systémy i aplikacemi paradoxně nové proprietární berlínské zdi vytvářely, protože každý dodavatel WWW služeb byl nucen autentizaci uživatelů nebo kryptování dat řešit individuálně a jeho volba byla limitována dostupnými prostředky preferovaného vývojového prostředí. V .Net Frameworku jsme si za tímto účelem vyvíjeli rozličné SOAP extenze nebo http moduly.
Microsoft si také chytře vývojem WSE ověřuje životaschopnost, výhody a slabiny nových standardů, aby v Longhornu mohl představit zralou technologii bez (doufejme) zásadních problémů. Jak asi víte, v Longhornu budou WWW služby součástí nového komunikační platformy s kódovým názvem Indigo. Potěšující je, že Indigo by mělo být dostupné i pro starší operační systémy Windows XP a Windows 2003, takže ihned vyvíjet budeme moci i pro zákazníky, kteří jsou při přechodu na nové technologie laxnější.:)
Od vás, čtenářů, bych rád věděl, jestli chcete, abych se v článcích zaměřil jen na praktické použití nových standardů. To znamená hlavně na to, jaké třídy a metody použiji na klientovi a serveru, když chci poslat přílohy nebo co všechno musím udělat/nastavit, abych obsah zprávy zakryptoval atd.. Nebo byste byli raději za hlubší ponor do hlubin standardů, takže bych popisoval i strukturu SOAP zpráv vyměňovaných mezi klientem a serverem a vy byste tak získali lepší vhled do (alespoň pro mě :) ) mimořádně vzrušujícího infrastrukturního pozadí WWW služeb?
Wednesday, 19 May 2004 19:59:00 (Central Europe Standard Time, UTC+01:00)
Web Services
Friday, 14 May 2004
Kniha Network programming for the Microsoft .Net Framework
Kniha Network programming for the Microsoft .Net Framework je úvodem do síťového programování. Slovo úvodem bych zdůraznil, protože žádné rozsáhlé případové studie v ní nenaleznete.
Po obligátním a povrchním úvodu do .Net Frameworku, nás autoři seznámí se “streamy” a pochopitelně se soustředí na třídu NetworkStream. Následuje popis práce s thready a ukázky asynchronního návrhového vzoru (metody Begin*, End*)- i když je problematice věnováno plných 19 stran, nečekejte žádné "best practices", ale spíše upovídaný přepis toho, co je v MSDN. Ukázek asynchronního návrhového vzoru je v celé knize hříšně opulentní množství , takže tato kapitola je jen "lákavou" návnadou.
Dále je v knize vysvětlen význam serializace a probrány jsou XML, binární a SOAP serializace. Když už je serializace probírána do takových detailů, jakými jsou XML atributy, mohla být zmíněna i dynamická redefinice atributů za asistence třídy XmlAttributeOverrides.
Lehký úvod do jmenného prostoru System.Net, jehož smysl mi v kompozici knihy uniká, je vystřídán popisem protokolů IPV4 a IPV6 a metod třídy DNS. Tato kapitola mi připadá z celé knihy nejpovedenější, protože z ní čiší, že její autor své téma podrobně zná, ale přitom dokáže na vyhrazeném prostoru vybrat to podstatné a nezabíhat do zdržujících detailů.
Následující dvě kapitoly tvoří jádro knihy, protože se zabývají klientskými a serverovými sokety a také jejich nadstavbami s jednodušším API (TcpClient, TcpListener). Bohužel tyto kapitoly trpí také největší nevyvážeností ve zpracování tématu. Přístup autorů kolísá od pasivního přejímání informací z MSDN k neustálému zdůrazňování, že pro většinu synchronních metod existují jejich asynchronní doplňky. Když jsem se tuto zajímavou informaci dověděl potřetí a prohlédl si další úmorný Step By Step příklad určený pravděpodobně programátorům po akutní lobotomii provedené brokovnicí, měl jsem chuť připojit se dobře cíleným výstřelem k zástupu šťastných idiotů, abych dokázal kapitoly dočíst. Tam, kde by měla být tématika zpracována velmi prodrobně i s ukázkami, se autoři omezí na shrnující tabulky, jejichž pravděpodobně jediným smyslem je rychlé navýšení počtu popsaných normostran. Moje výtka směřuje hlavně k zcela nedostatečné dokumentaci enumerace SocketOption.
Kromě TCP/IP protokolu jsou zde i ukázky UDP protokolu a implementace takzvaných "Raw" soketů. "Raw" sokety jsou vysvětleny na příkladu ICMP protokolu (což není nic jiného než všem důvěrně známý PING). Slušelo by se zmínit, že na Windows 2000 a XP mohou "Raw" sokety otevřít pouze administrátoři. (ping.exe může spustit každý uživatel, jde asi o jedinou výjimku).
Důležitost tříd WebClient, WebResponse a WebRequest je vyzdvižena v kapitole nazvané "Using the Network". Tato kapitola je povedená, i když zde asi nenaleznete nic překvapivého. Zmíněny jsou cookies, různé způsoby autentizace, certifikáty, SSL.
Z dalších kapitol rychle získáte pocit, že se autoři zavázali dodat dílko o vyšším počtu stran, a proto zařadili témata jako jsou Web Services a .Net Remoting. Sice jsou vždy naťuknuty pokročilé vlastnosti (SOAP extenze, Channel sinks), ale z jejich odfláknutého vysvětlení si začátečník bude brzy zoufat a slabší nátura se k těmto konceptům kvůli neumětelství autorů již nikdy nevrátí. Jako leitmotiv knihy:) se zde objevuje podrobné vysvětlení asynchronního volání WWW služeb.
Autoři se také s těžko pochopitelnou vervou pustí i do vysvětlování Code Acces Security. Jejich snaha se ale omezí na výčet oprávnění a hrubý přehled významu konstitutivních složek CAS, takže kdybych se s CAS setkal poprvé, získám mylný dojem, že CAS je nesmysl bez jakékoli užitné hodnoty. Jsme také poučeni, že bychom měli komunikaci mezi sokety kryptovat, protože svět plný hackerů čeká na naše pakety. Děkuji za osvětu, hned se cítím jako up-to-date vývojář, teď si najdu jen ve slovníku cizích slov význam termínu kryptovat, abych ty hackery svými programy sejmul. :)
Doporučení pro psaní výkonných aplikací jsou shrnuta v mozaice nazvané "Network performance and scalability. Zajímavá je hlavně část týkající se doporučení pro používání "Nagle" algoritmu, ale ani ostatní rady vašim aplikacím neublíží.
Zcela do počtu je kratičká poslední kapitola Advancements in .Net Framework programming, jejíž originální teze by se dala shrnout "Nebojte se, v příští verzi bude zase vše lepší, výkonnější a bezpečnější".
Co říci závěrem? Jestliže se sokety začínáte a jste úplní zelenáči, kniha se Vam bude hodit, i když si z ní odnesete hlavně poznatek, že sokety jsou tady proto, aby bylo na čem demonstrovat dokonalý asynchronní návrhový vzor. :) Jste-li pokročilý vývojář a v knize hledáte neotřelé rady starých zkušených harcovníků, schovejte peněženku, zamáčkněte slzu kanoucí za odpíraným poznáním a vyberte si jiný titul.
Anotace
Název: Network Programming For the Microsoft .Net Framework
Autoři: Jones, A; Ohlund, J; Olson, L;
Nakladatelství: Microsoft Press 2004
Friday, 14 May 2004 20:05:00 (Central Europe Standard Time, UTC+01:00)
.NET Framework | .Net Remoting | ASP.NET | Web Services