pátek 3. prosince 2010

Vývoj pro WP7 - seminář

Tento týden jsem se zúčastnil semináře o vývoji aplikací pro Windows Phone 7. Chvilku jsem musel všechny ty informace vstřebat, protože prvotní reakce na některé věci byly u mě dost infarktové ;-) Nejvíc mě dostalo prohlášení od člověka z Microsoftu, když říkal jak je česká pobočka brána v potaz v centrále. Hned jsem si připadal jak člověk s kyjem žijící v jeskyni... škoda mluvit.
Během celého semináře bylo dost často slyšet, jak jsou jednotlivé možnosti inspirované ostatními platformami (iPhone, Android). Neříkám, že je to špatně, ale je to dobře? Např. taková nemožnost multitaskingu pro 3.stranu alá iPhone (dřívější verze) mi přijde dost zcestná a doufám, že to chlapci v Microsoftu přehodnotí. I když se přednášející snažil nás přesvědčit, jak se mu tento přístup líbí, jelikož prý jeho HD2 se často jen tak zamyslí a nic se na něm nedá dělat. Tento stav údajně způsobují aplikace na pozadí, které si žijí svým životem. Jenže jako příklad takovéto aplikace použil klienta pro MS Office Communicator, což je aplikace od Microsoftu. Zvláštní, že by Microsoft neuměl udělat správnou aplikaci pro WM :-D Já bych problém hledal spíš v kvalitě aplikace než v architektuře systému.
Každopádně na mě momentální verze Windows Phone 7 působí jako drahé zařízení s nadupaným HW, které však slouží jen jako terminál pro webové a cloudové aplikace. Toto jen podtrhuje neexistence MS SQL Compact, i když údajně tato databáze je uvnitř systému použita.

Co se mi líbilo
Vývoj je prakticky stejný jako vývoj kterékoliv Silverlight aplikace. Na jednu stranu jednoduché, ale na druhou i omezující.
Už vím, proč některé aplikace po návratu zachovají svůj předchozí obsah a některé ne. Samozřejmě je to opět o vývojářích. V této verzi OS je na vývojáři, jestli uloží aktuální stav aplikace při přechodu na jinou aplikaci a při návratu zase vrátí aplikaci do původního stavu. Existují na to události (OnActivate, OnDeactivate), ve kterých lze stav aplikace uložit buď do paměti a nebo do IsolatedStorage. Výhoda druhého je v persistentním uložení i pro další spuštění aplikace.
Líbí se mi ovládací prvky Pivot a Panorama, které jsou použity v hubech, sice vypadají dost podobně, ale mají trochu jinou logiku použití.

Co nelíbilo
To hlavní je nemožnost ukládání dat do nějaké databáze. V tuto chvíli je jediná možnost, pro persistentní uložení dat, IsolatedStorage, které lze nastavit buď do režimu ukládání key/value nebo file system, kdy lze ukládat xml soubory. No a pak samozřejmě kamkoli mimo WP7.
Momentálně nelze vytvářet záznamy pro jiné aplikace bez toho, aniž by tato aplikace byla spuštěna. Např. potřebuji vytvořit nový úkol automaticky, ale to nejde. Musím zavolat aplikaci, která slouží pro úkoly, a té tyto informace předat. Uživatel pak musí tento záznam uložit sám. Argumenty, že je to tak bezpečnější, neberu. Každopádně je to uživatelsky méně přívětivé. Jelikož uživatel musí stejně při instalaci aplikace souhlasit s tím, že aplikace bude využívat další služby (alá Android).

Ještě k systémovým službám
Údajně jsou nyní 2 možnosti, jak může aplikace v pravidelných intervalech provádět nějakou činnost:
1) aplikace musí být uživatelem vytažena na hlavní obrazovku jako Live Tile a pak může provádět v určité časové periodě něco. Existuje tu ale několik omezení ohledně max. času zpracování a reakce.
2) pomocí push notifikací, které jsou ale taky omezené

Seminář byl velmi povedený, dozvěděl jsem se na něm spousty zajímavých informací. Nejdůležitější byla ta, že zatím čeští vývojáři nemají možnost aplikace umisťovat na market a ani jim Microsoft neumožní odblokovat telefon pro vývoj. Takže nezbývá než čekat, prý do léta příštího roku, kdy by mohl být market vývojářům zpřístupněn. Snad bude pak i přístupný uživatelům v ČR.
Takže uvidíme...

pondělí 15. listopadu 2010

Chyba WCF "An error occurred when verifying security for the message."

Vrátím se ještě k předchozímu příspěvku, kde jsem popisoval UserNamePasswordValidator při ověřování klienta ve WCF službě. Setkal jsem se totiž s jedním problémem při přesunu na testovací server, který mi zabral pár hodin zkoumání.
Nastavil jsem na testovacím serveru vše potřebné včetně certifikátu. Po spuštění klienta jsem ale neustále dostával tu samou nic neříkající chybovou zprávu "An error occurred when verifying security for the message.". Pátral jsem po webu, co by to mohlo být. Zhruba 90% všech nalezených řešení, spojených s touto chybou, se týkalo špatně nastaveného času mezi klientem a serverem - defaultně se toleruje odchylka max. 5 minut, ale dá se pomocí konfigurace WCF změnit nastavením MaxClockSkew. Toto ale nebyl můj případ, jelikož hodiny byli na obou stranách komunikace synchronizované automaticky a nerozcházely se.
Pak jsem narazil na jeden příspěvek, který řešil stejný problém, ale příčina chyby nebyla v čase nýbrž ve velikosti zprávy. To mě přivedlo na myšlenku, že ta chyba může být vlastně libovolná a chybová zpráva neodpovídá skutečné příčině chyby. A měl jsem pravdu. Po chvilce laborování jsem našel špatně nastavené připojení do databáze, takže při ověřování klienta se nepodařilo připojit k SQL serveru a přitom se vygenerovala tato nic neříkající chyba.
Takže jaký je závěr? Dokud není sestaveno spojení, tak nelze věřit plně chybovým zprávám. Vypadá to, že někdy se některé chyby spolknou a k vám se dostane až nějaká další chyba, která při sestavování komunikace vznikla.
I programátoři jsou jen lidé, i když ne každý tomu věří ;-)

středa 3. listopadu 2010

WCF a UserNamePasswordValidator

Laboroval jsem teď nějakou chvíli s ověřováním uživatelů ve WCF. Potřeboval jsem kontrolovat, že uživatel volající metody WCF služby, má právo je využívat. Bohužel jsem byl předem omezen mantinely:
  • credentials uživatelů v MS SQL
  • basicHttpBinding
  • služba hostovaná v IISku
Použitý binding je omezující v tom, že komunikace musí být vždy zabezpečená pomocí certifikátu, bez něj to prostě nejde. Zajímavé je, že to nemusí být na IISku definované jako "required". Ale i když jsem definoval referenci služby bez https, tak se generoval endpoint s https. Je to někde "natvrdo" nastavené a bez https to nefunguje.
Jsou asi jen 2 možnosti, jak ověřovat uživatele:
  • využít ASP.NET providera
  • využít třídu UserNamePasswordValidator
Rozdíl je asi jen v komplexnosti, co od toho očekáváte. Výhoda ASP.NET providera je v tom, že lze použít i návazné role a profily. 
Mě stačilo jednoduché ověření uživatele. Také proto, že jsem měl jinou strukturu DB pro uživatele a tím pádem bych musel psát vlastního ASP.NET providera, jsem se rozhodl pro využití UserNamePasswordValidator. Odvodil jsem si vlastní třídu a přepsal metodu Validate - jednoduchý příklad je v MSDN.
Největší problém byl s konfigurací, aby validátor správně fungoval a nepoužívalo se ověřování Windows. Nastavení WCF služby:

<system.serviceModel>
<services>
<service name="ServiceLibrary.Service" behaviorConfiguration="CoopServiceBehavior">
<!-- Service Endpoints -->
                 <endpoint address="" binding="basicHttpBinding" bindingConfiguration="MyBinding" contract="ServiceLibrary.IService"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="MyBinding">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="CoopServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<serviceCredentials>
<serviceCertificate findValue="CN=zeleny5" storeName="CertificateAuthority" x509FindType="FindByIssuerName"/>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="ServiceLibrary.CustomUserNameValidator, ServiceLibrary"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>

Na IISku si vygenerujete certifikát, který by měl být podepsaný nějakou certifikační autoritou (CA). Na klientovi musí být certifikát CA nainstalován mezi důvěryhodnými kořenovými certifikačními úřady. Jinak bude při komunikaci vyvolána chyba. Dále je potřeba na serveru udělit práva na čtení k certifikátu. Na adresáři C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys nastavte práva na čtení pro Network Service, pod kterým běží služba v IISku (nastaveno v aplikačním poolu). Může to hlásit chyby typu Access Denied, ale to nevadí, protože to stejně bude fungovat ;-) Na webu, kde poběží služba, je potřeba definovat vazbu na HTTPS s vygenerovaným a podepsaným certifikátem. Není potřeba nastavovat vyžadování SSL.

Když je vše správně nakonfigurované, tak by to mělo fungovat... klient se připojí ke službě, ta ho ověří a dovolí mu vyvolat požadovanou metodu. V opačném případě dojde k chybě - v závislosti na implementaci v metodě Validate.

pátek 29. října 2010

Windows Phone 7 a ti druzí

Microsoft nám konečně představil svůj nový systém, který vzbudil celkem dosti značnou vlnu emocí. Ohlasy jsou  pozitivní i negativní. Přeci jen je poznat, že systém ještě není úplně dokončen, ale Microsoft slibuje jeho další vylepšování. Podle mého je na jednoznačné závěry ještě moc brzy, obzvlášť v našich končinách, kde je systém zatím nepodporován - nelze nakupovat aplikace přes market a jiným způsobem je nelze instalovat do zařízení.
Starému systému (WM) byla vyčítána roztříštěnost, problémy s výkonem, složitost atd. Toto vše má nový systém řešit. Microsoft vydal minimální požadavky na HW (tzv. chassis), které musí výrobci dodržet. Při představení systému byly také představeny první reálné přístroje dle specifikace chassis 1. Recenze na rychlost zařízení jsou pozitivní, takže by již neměly být problémy s výkonem. UI je na první pohled jednoduché a přehledné, ale nelíbí se každému podle reakcí recenzentů a prvních uživatelů.

První výtka, která se objevuje, je chybějící podpora multitaskingu pro aplikace třetích stran. Problémem ale je i nemožnost návratu na jakoukoliv dříve spuštěnou aplikaci. Tlačítko "zpět" prostě jde vždy o jeden krok zpátky. Systém ale ukazuje, že multitasking umí, jelikož některé systémové aplikace fungují i na pozadí - přehrávač hudby.
Dalším problémem je chybějící možnost Copy/Paste. Zvláštní opět je, že systém podporuje např. kopírování označeného slova a jeho přenesení do vyhledávače.
Toto podle mého jen potvrzuje, že je systém ještě nedodělaný a chybějící funkce jsou rozdělané nebo neprošly testy a tím pádem jsou v tuto chvíli zakázané. Takže určitě budou doplněny později.

Velkou vlnu nevole vzbudila chybějící podpora pro výměnné karty. Ze začátku mi to přišlo také jako podstatný nedostatek, pak jsem si ale uvědomil, že mám v telefonu 16GB kartu a od té doby jsem ji nevytáhl. Hlavním důvodem je nevhodné umístění pod krytem batere (HTC Touch Pro). Myslím si, že když bude mít telefon dostatek paměti - min.16GB - tak to není nedostatek, ale budu to brát jako výhodu, protože pak nebudou existovat aplikace, které jsou svázané s kartou - iGO, Smartmaps. Nakonec ale stejně vyšlo najevo, že z představených zařízení 2 určitě mají slot na micro SD karty (Samsung, HTC HD7) a u dalšího se to předpokládá (Dell). Samsung má kartu přístupnou, kdežto HD7 ne. Ale vzhledem k tomu jak se s kartou pracuje, resp. jak je integrovaná v systému - JBOD, tak je jasné, že karta není pro vyměňování. Údajně lze u Samsungu kartu vyměnit, ale po výměně se provede hard reset zařízení, aby se karta připojila k integrované paměti zařízení. U HD7 zatím tato možnost nebyla ověřena, ale povedlo se vyměnit kartu o stejné velikosti s jinou class (původní class 2 vyměněna za class 6). Ale vzhledem k tomu, že se HD7 prodává s různou velikostí paměti (USA 8GB, Evropa 16GB), tak je prakticky jisté, že to jde.

Zkusím si porovnat nový WP7 s největšími konkurenty iPhone a Android.

WP7 diktuje výrobcům min. HW, který musí použít. iPhone dělá jen jeden typ, který se liší ve velikosti paměti. Android má typů strašně moc. Přijde mi, že diktování HW podmínek výrobcům je dobré. Rozhodně bych to uvítal i u Androidu, jelikož vznikají zařízení, které nemají podporované rozlišení displeje a používají slabý procesor nebo málo paměti - tímto mi teď dost připomínají staré WM, přesně tato roztříštěnost jim byla vyčítána. Ohledně podpory výměnných karet nemá smysl vůbec mluvit o iPhonu. U Androidu byly karty do verze 2.1 prakticky použitené jen napůl vzhledem k tomu, že se na ně nedaly instalovat aplikace, ale jen ukládat data. Ostatně i teď, když výrobce aplikace neprovede úpravu, tak si musíte vystačit s vestavěnou pamětí, které není nikdy dost.
Někde jsem četl, že novému WP7 chybí podpora flashe, ale není to pravda. Flash je možné přehrát stejným způsobem jako to podporuje např. Android do verze 2.1, tj. spustí se externí aplikace.

Líbí se mi, že WP7 má stále úvodní obrazovku, na které je přehledný souhrn informací - nepřečtené zprávy, nadcházející události a další, které lze přidat. Přiznám se, že systém widgetů na Androidu mi přijde nepřehledný, ani tolik vychvalovaný Mobile Shell na WM mi nepřišel přehledný. iPhone žádnou takovouto přehlednou obrazovku nemá - alespoň o tom nevím - a docela mě mrzí, že ani BB nic podobného nemá.

Dovolím si závěr, který je pouze za mě.
Čekal jsem, jaký WP7 bude. Nejenom proto, že WM používám již dost dlouho a také jsem pro něj udělal pár aplikací, ale rád bych věděl jaký bude můj další telefon. Zkusil jsem si Android a nenadchl mě. Mám ho jako pracovní telefon a stále s ním bojuji. Podpora Googlu je dobrá, ale jak je možné, že Google stále ignoruje úkoly? Toto skutečně nechápu a ta parodie na odškrtávání textů mě vůbec neuspokojuje. iPhone vůbec nepřichází v úvahu, ale musím uznat, že 4.generace má nádherný display. Myslel jsem, že BB by mohl být ten správný favorit, ale ani to není úplně ono. Chybí mi jednoduchý přehled informací.
Jestli se Microsoftu podaří dodělat chybějící funkce, hlavně multitasking pro třetí stranu, zpřístupní market pro naší republiku, tak by to mohlo být zase to pravé pro mě. Zatím ale zůstanu u svého WM a uvidím příští rok, kam se to celé pohne...

úterý 21. září 2010

WCF RIA Services - update datového zdroje

Hraju si teď trochu s WCF RIA Services. Vcelku zajímavá technologie, ale má i své nedokonalosti. Jako první a asi i dost podstatná je nemožnost změny datového modelu nějakým hezkým automatickým způsobem ;-)
O co jde? Mám vytvořený databázový model, entity model a domain service. Někdy v průběhu vývoje zjistím, že je potřeba udělat nějaké změny a rozšíření v DB. Není problém udělat update v databázi. Entity model lze také jednoduše upravit (v edmx souboru přes pravé tlačítko myši). Jenže co s domain service? Tady jsem zatím narazil. Žádná automatika není (nebo jo? :-O). Trochu jsem po tom pátrat a našel jsem jen takový work around. Vytvořit nový dočasný domain service pouze pro novou tabulku. Jeho obsah následně přenést do původního domain service a dočasný smazat. Stejným způsobem přenést i informace o metadatech. V případě změny struktury tabulky se to musí udělat podobně, ale stačí jen takto upravit metadata.
Řešení zatím nic moc, snad se dočkáme v další verzi nějakého pokroku v tomto směru. Na druhou stranu ani ta automatika nebude úplně dokonalá, protože v případě doplnění domain service o vlastní metody a nepoužití partial class, by mohlo dojít ke ztrátě těchto metod.

úterý 22. června 2010

Zjištění velikosti jednotlivých tabulek v DB

Dneska jsem potřeboval zjistit velikosti jednotlivých tabulek v databázi. Sice jsem v SQL Manageru našel možnost zobrazení nějakého takového reportu, ale selhalo to na chybě. Kolega mi poskytl zajímavý skriptík, který hezky přehledně zobrazí jednotlivé velikosti tabulek v databázi. Člověk hned zjistí, která z tabulek je ta nenasytná ;-)


DECLARE @DATABASE varchar(100)
DECLARE @tablename varchar(100)
DECLARE @Space TABLE (name varchar(100), rows varchar(100), reserved varchar(100), DATA varchar(100), index_size varchar(100), unused varchar(100))

SET @DATABASE =  DB_NAME()

DECLARE State_Cursor CURSOR FOR
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'   AND TABLE_CATALOG = @DATABASE ORDER BY TABLE_NAME
OPEN State_Cursor
FETCH NEXT FROM State_Cursor INTO @tablename
WHILE @@FETCH_STATUS = 0
BEGIN
  INSERT INTO @Space EXEC sp_spaceused @tablename
  FETCH NEXT FROM State_Cursor INTO @tablename
END
CLOSE State_Cursor
DEALLOCATE State_Cursor

SELECT * FROM @Space

neděle 20. června 2010

Subversion na Asus WL500gP

Je to až k neuvěření, co všechno tento router dokáže. Pomocí tohoto návodu se mi podařilo zprovoznit Subversion. Nečekal jsem od toho žádný extra výkon vzhledem k hardware, ale byl jsem příjemně překvapen, že se s tím dá v pohodě pracovat. Jeden uživatel sice není žádná zátěž, ale i tak je to dostačující. Zatím jediný problém, na který jsem přišel, je při odpojení disku. Samba to nějak nerozdýchá a zkolabuje, takže při opětovném připojení disku se musí provést reboot. Škoda, musím nějak vymyslet, jak to obejít, aby se na noc dal disk vypínat a zbytečně neběžel.

úterý 15. června 2010

Povolení MSDTC se vzdáleným MS SQL

Potřeboval jsem zapnout distribuované transakce mezi vývojovým počítačem a MS SQL databází, která běží na jiném stroji. Chyba ve VS byla celkem jasně popsaná, ale kdyby MS před náma neměl neustále nějaké tajnosti :-/ V XP je to celkem jednoduché. Přes Správu počítače se tam dá dostat. Bohužel u Vist je to jiné. Musí se ručně spustit comexp.msc. Následně se ve stromečku vybere Služba komponent -> Počítače -> Tento počítač -> Koordinátor distribuovaných transakcí -> Místní koordinátor DTC. Na poslední položce zvolit Vlastnosti. Na kartě Zabezpečení nastavit vše dle obrázku.
Tím je první část hotovo, ale ještě není vše vyřešeno ;-) Ještě je potřeba povolit na firewallu patřičný port pro komunikaci. Když se jedná o standardní systémový firewall od MS, tak to lze nastavit následovně. V Ovládacích panelech se vybere Centrum zabezpečení. V levé nabídce zvolit Brána firewall systému Windows. V dalším okně opět zleva vybrat Povolit program v bráně firewall systému Windows. Na záložce Výjimky nejprve Přidat program..., kde pomocí Procházet... se musí vybrat ze systémového adresáře windows - tj. %windir%\system32 - soubor msdtc.exe. Potvrdit a poté Přidat port..., kde se doplní nějaký název - např. MSDTC - nastaví se číslo portu 135 a zvolí protokol TCP. Všechno potvrdit, zavřít a když pánbůh dá (rozuměj Bill Gates ;-)) tak to začne fungovat :-D

pátek 21. května 2010

Chyba WCF při velkém počtu záznamů

Nedávno jsem řešil zajímavou chybu ve WCF. Při zobrazení jedné statistiky nahodile padala služba. V logu byla následující chyba:
Maximální počet položek, které lze serializovat nebo převést ze sériového tvaru v grafu objektů, je 65536. Změňte graf objektů nebo zvyšte kvótu MaxItemsInObjectGraph.

Hned bylo jasné, že počet přenášených záznamů je moc velký. Zkoušel jsem měnit konfiguraci dle MSDN, ale nakonec to nebylo tak jednoduché, jak jsem si myslel. Pro ukázku, jak to lze řešit. Důležité je nastavit parametr jak na serveru, tak i na klientovi.
Ukázková konfigurace serveru:

<system.serviceModel>
  <services>
    <service behaviorConfiguration="Umea.se.EventReactor.ServiceTier.ServiceViewEventBehavior" name="Umea.se.EventReactor.ServiceTier.ServiceViewEvent">
      <endpoint address="" binding="wsHttpBinding" contract="Umea.se.EventReactor.ServiceTier.IServiceViewEvent">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
      <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <behavior name="Umea.se.EventReactor.ServiceTier.ServiceViewEventBehavior">
        <serviceMetadata httpGetEnabled="true" />
        <serviceDebug includeExceptionDetailInFaults="false" />
        <dataContractSerializer maxItemsInObjectGraph="2147483647" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>


A odpovídající konfigurace pro klienta:

<system.serviceModel>
  <client>
    <endpoint address="http://localhost:3379/ServiceViewEvent.svc" behaviorConfiguration="ServiceViewEventBehavior" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IServiceViewEvent" contract="ServiceReferenceViewEvent.IServiceViewEvent" name="WSHttpBinding_IServiceViewEvent">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
  </client>
  <behaviors>
    <endpointBehaviors>
      <behavior name="ServiceViewEventBehavior">
        <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
      </behavior>
    </endpointBehaviors>
  </behaviors>
</system.serviceModel>


Na klientovy je potřeba definovat atribut behaviorConfiguration pro všechny endpointy.