Ááá

Další web používající WordPress

Lis

8

Flush DNS cache změnou NSSETu 0

Při nasazení jistého webu jsem řešil tenhle problém: Jedna subdoména měla být na jiném serveru, ale ještě před vytvořením CNAME záznamu jsem tu doménu omylem zadal do prohlížeče. Tím pádem se do různých DNS keší dostala IP adresa z A záznamu.

Bohužel i po několika hodinách servery mého poskytovatele stále resorvovaly starou IPku a subdoména tak nefungovala mně (to bych skousl) ani jiným uživatelům O2 (to je horší).

Nakonec pomohla registrace a přiřazení zbrusu nového NSSET, s těmi samými name servery. Během okamžiku subdoména fungovala.

Třeba to někomu pomůže.

Čvc

24

PRG místo GET formulářů (ASP.NET MVC) 0

PRG, neboli post-redirect-get, se obvykle používá k zamezení vícenásobného odeslání formuláře, který mění data. Také se ale používá jako náhrada GET formulářů, pokud chcete mít kontrolu nad URL různých filtrovaných výpisů, vyhledávání (/search/fráze místo /search?query=fráze) apod.

Prostě se formuláři nastaví metoda POST a po odeslání se přesměruje metodou GET na správně sestavené URL.

V nejjednodušších případech se to dá realizovat nějak takto:

public class HomeController : Controller
{
    /// <summary>
    /// GET: /Log
    /// </summary>
    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult List(ListViewModel model)
    {
        return View(model);
    }

    /// <summary>
    /// POST: /Log
    /// </summary>
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult List(ListViewModel model)
    {
        return RedirectToAction("List", model);
    }

Potíže mohou nastat ve složitějších případech. Například pokud viewmodel obsahuje nějaké veřejné properties, které se nebindují. Tomu se ale z několika důvodů vyhýbám. Pro úplnost:

public class HomeController : Controller
{
    /// <summary>
    /// GET: /Log
    /// </summary>
    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult List([Bind(Include = "CategoryFilter,YearFilter")]ListViewModel model)
    {
        return View(model);
    }

    /// <summary>
    /// POST: /Log
    /// </summary>
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult List([Bind(Include = "CategoryFilter,YearFilter")]ListViewModel model)
    {
        return RedirectToAction("List", new {
            CategoryFilter = model.CategoryFilter,
            YearFilter = model.YearFilter
        });
    }

Snad chápete, proč (mimo jiné) se tomu vyhýbám. Uplatňuju zásadu, že pouze vstup může být u viewmodelu veřejnou property.

Další nepříjemnost nastává, když výchozí hodnota některé property není null, třeba číslo stránky u stránkovaných výpisů. Nepříjemnost tkví v tom, že se nám tyto výchozí hodnoty dostávají do URL a to nepůsobí nejlepším dojmem (?page=1).

Tento problém se ale týká tvorby odkazů obecně (a nejen v ASP.NET MVC). Myslím, že mám takové polovičaté řešení (jestli mi zase nedojde, že to je blbost), ale je třeba na tom ještě trochu zapracovat, takže si to nechám pro příště.

Čer

21

Jak vynutit generování LINQ to SQL tříd 0

Narazil jsem na jeden starý bug v LINQ to SQL designeru ve Visual Web Developeru, díky kterému mi po změně DBML souboru zmizí .designer.cs soubor a nový se nevygeneruje.

Bohužel nevím jak chybu reprodukovat, protože nikdy dřív jsem se změnami v DBML žádný problém neměl. Asi se to vyskytuje jenom někdy.

Naštěstí jsem našel funkční workaround: Když DBML soubor v Solution Exploreru přejmenuju, tak se příslušný .designer.cs přegeneruje. Přejmenuju zpátky a je to.

Kvě

31

Import dat z MySQL do SQL Serveru 0

Dneska trochu praktičtěji. Jak na localhostu přenést data z MySQL do SQL Server Express.

Je to vpodstatě jednoduché, nejdřív nainstalujete MySQL Connector ODBC, pak si vytvoříte DSN („Zdroje dat (ODBC)“, součást Windows) a nakonec se proklikáte wizardem „Import and Export Data“, který je součástí SQL Serveru:

Jediné úskalí je v tom, že v konfiguraci MySQL (soubor my.ini) musíte nejdřív nastavit sql-mode="ANSI". Jinak se při pokusu o import dočkáte syntax error.

Stručně v obrázcích:

1.

mysql-odbc-configuration1.png

2.

zdroje-dat-odbc.png

3.

myini-sqlmode-ansi.png

4.

import-choose-data-source.png

Naimportuje to i strukturu, ovšem bez klíčů. Takže jako další krok je nutné nově vytvořenou databázi si projít a doupravit. Na to lze doporučit třeba SQL Server Management Studio Express, které je zdarma a nainstalujete ho nejsnáz přes Web Platform Installer.

Kvě

24

Co mám proti MVC 7

Posledních pár týdnů jsem na programování kašlal, trochu jsem přehodnocoval priority a nakonec jsem se rozhodl, že přejdu na ASP.NET MVC. Nejdřív ale popíšu, co se mi na něm (a taky na Nette, Rails a dalších) tolik nelíbí.

Přes půl století panuje snaha přiblížit „počítačové jazyky“ jazykům lidským. Zlatým grálem programování je, aby i úplný debil mohl vytvořit program prostě tím, že ho vlastními slovy popíše. Přiblížení k tomuto cíli bylo motivací pro vznik všemožných abstrakcí, které umožňují popsat počítači určitý problém zas o něco přirozeněji než dřív.

Jak byste laicky popsali webovou aplikaci (představte si, že jste BFU)? Jako soustavu controllerů, na kterých je možné volat akce, které vrací view? To asi ne. Já bych mluvil o soustavě stránek, na kterých jsou odkazy a formuláře, jejichž odkliknutím lze vykonat nějakou akci a případně přejít na jinou stránku. Něco v tom smyslu.

Připadá mi, že Rails a jeho následníci zavádí nepřirozenou abstrakci. Programátor si to musí v hlavě tlumočit, například: „Chci přidat stránku → chci přidat akci a view“. Při komunikaci s uživateli budete mluvit opět o stránkách (aby vám rozuměli) a v duchu si to překládat na nepřirozené „akce“…

Podle mě přístup MVC/MVP, jak se začal prosazovat v posledních pár letech, je šlápnutím vedle. Ale uvědomil jsem si, že já nechci psát žádný framework, takže musím nutně vybírat z toho, co tu je. Proto jsem opustil koncept svého vlastního frameworku a psaní frameworků rád přenechávám jiným.

Přes koncepční výhrady, ASP.NET MVC je momentálně prostě nejlepší…

Bře

28

LINQ to SQL a změny v databázi 1

LINQ to SQL je skvělá věc, ale pár věcí by ještě bylo potřeba dotáhnout. Pokud provedete změny v databázové struktuře, Visual Studio nenabízí žádnou pomůcku, která by je vám pomohla reflektovat ve vašich LINQ to SQL třídách.

V počátečních fázích vývoje může stačit v takovém případě prostě patřičné entity z DBML souboru odstranit a tabulky tam natahat znovu, ale jakmile si začnete mapování přizpůsobovat (přejmenovávat entity, přejmenovávat sloupce, navěšovat události apod.), tak tahle možnost už nepřichází v úvahu.

Existuje komerční add-in Huagati DBML/EDMX Tools (od $50), který kromě pár dalších věcí umí i přenášet změny z databáze do LINQ to SQL tříd. Jenže Express edice Visual Studia nemají podporu add-inů, takže nic pro mě.

Jediná možnost, na kterou jsem přišel (tady), spočívá v tom, že si do designéru přetáhnu novou kopii změněné tabulky, změny do té staré přenesu copy-pastováním a novou smažu:

dbml-copy.png

Bohužel takhle snadno nelze kopírovat vazby mezi entitama, na to už musíte otevřít zdrojový kód DBML souboru. Lišta Design / Split / Source, známá z Web Form editoru, tady bohužel chybí, ale když na soubor kliknete pravým myšítkem v Solution Exploreru, máte tam i volbu Open With…, která vám umožní soubor otevřít v XML editoru (DBML není nic než XML):

dbml-open-with.png

Moc nadšený z toho nejsem. Nezbývá než doufat, že s tím něco udělají ve VS 2010…

Bře

21

Další podivnost ve VWD 1

Visual Web Developer si na mě nachystal další překvápko, z ničeho nic mi začal hlásit zvláštní chybu asi tak na stovce míst v kódu:

Error 59 The call is ambiguous between the following methods or properties: 'PokerZpravy.ControlExtension_GetPublicParameters.GetPublicParameters(System.Web.UI.Control)' and 'PokerZpravy.ControlExtension_GetPublicParameters.GetPublicParameters(System.Web.UI.Control)' C:\Users\Václav\Documents\Visual Studio 2008\Projects\PokerZpravy\Tests\GetPublicParametersTest.cs 40 25 PokerZpravy

Přeložené do češtiny to znamená asi to, že kompilátor neví, jestli chcete volat A nebo A.

Celý probém byl nakonec v tom, že se mi nějakým záhadným způsobem do referencí projektu dostalo assembly projektu samotného. Nejspíš se to povedlo při přidání custom controlů do toolbaru. Stačilo odstranit referenci a zase všechno funguje. :-)

Bře

21

Error creating control 0

Tak na tomhle jsem se zasekl na pěkných pár dnů:

error-creating-control.png

Je to nějaká chyba v .NET Frameworku 3.5 SP1, která způsobuje, že po přeložení a refreshování custom web controlu se místo něj v editoru zobrazí podobná hláška. Na různých stránkách Microsoftu je tento problém popsaný: Něco se člověk dočte na code.msdn.micro­soft.com, něco na support.micro­soft.com a něco na connect.micro­soft.com, hotové puzzle…

Nakonec jsem postupně nainstaloval tyto hotfixy:

  • KB961847 – „Error creating control- [text] property“ ASP.NET server cntls in VS. Podle názvu a popisu jsem v něj vkládal největší naděje, ale problém přetrvával i potom.
  • KB961864 --_pendingCallbac­ks[…].async' is null on ASP.NET 2.0 AJAX site. Vůbec netuším, co s tím má společného, ale tohle KB číslo bylo zmíněné jako řešení na relevantní stránce podpory. Efekt se opět nedostavil.
  • KB967535 – IIS 7.0 Request.Tran­smitFile / Request.WriteFile not working expected. Další oprava řešící něco úplně jiného, tento byl prozměnu poraděn v Microsofťáckém bugtrackeru jako workaround. Nicméně po nainstalování této aktualizace konečně problém zmizel a já můžu pokračovat v započaté práci.

Nevím, jestli první dva hotfixy něčemu pomohli, spíš bych řekl, že ne. Ale kdo ví…

Úno

8

Jak simulovat paralelní přístupy? 11

Myslel jsem, že už to mám, ale byla to slepá cesta.

Můj postup byl takový, že jsem si vytvořil testy v Selenium IDE, nastavil Selenium Core a pak vytvořil dávku, která ty testy dokázala spustit v předem určeném počtu Firefoxů, pokaždé s jiným prázdným profilem:

@ECHO OFF
SETLOCAL

REM Nastavení.
SET count=20
SET firefox_path="c:\Program Files\Mozilla Firefox\firefox.exe"
SET testUrl="http://localhost:12345/Selenium/core/TestRunner.html?test=../tests/TestSuite.html&resultsUrl=../postResults&auto=true"
SET profilePrefix=%TEMP%\TestProfile


REM Spuštění %count% instancí Firefoxu.
FOR /L %%i IN (1,1,%count%) DO MKDIR "%profilePrefix%%%i"
FOR /L %%i IN (1,1,%count%) DO ECHO user_pref("browser.shell.checkDefaultBrowser", false); user_pref("browser.startup.homepage_override.mstone", "rv:1.9.0.3"); > "%profilePrefix%%%i\prefs.js"
FOR /L %%i IN (1,1,%count%) DO %firefox_path% -no-remote -profile "%profilePrefix%%%i" %testUrl%


ECHO Ted chvilku pockejte na dobehnuti vsech testu.
PAUSE


REM Úklid.
TASKKILL /IM firefox.exe /T /F
FOR /L %%i IN (1,1,%count%) DO RMDIR /S /Q "%profilePrefix%%%i"
ENDLOCAL

Takhle s dvaceti okny to ještě ujde, obsazení paměti mi vyšplhá jenom na nějakých 85%:

clipboard01.png

Jenže 20 je málo. To už se na podobné testování můžu rovnou vykašlat, jako všichni ostatní. Zkusil jsem nastavit 50 (i to je pořád málo), během chvilky se počítač stal totálně nepoužitelným a trvalo půl hodiny, než se mi podařilo přerušit tu dávku a taskkillnout ty firefox.exe procesy…

Takže tudy cesta nevede. :-(

Úno

4

Thread-safety a webové aplikace 0

Jeden z nejdůležitějších aspektů, jeden z nejméně testovaných.

Prolog

Představte si modelovou situaci:

  • Zpřístupníte světu webovou aplikaci, kterou jste pečlivě ze všech stran otestovali a jste si jistí, že funguje správně.
  • Ze začátku o ni není velký zájem, ale těch pár lidí, co ji občas použije, si ji nemůže vynachválit a tak časem začne uživatelů přibývat. Word of mouth.
  • Pak se stane něco divného. Nějaká data se ztratí, nějaký uživatel dostane cizí data, něco se uloží dvakrát apod.
  • Zaboha nemáte tušení, čím to bylo. Nakonec to svedete na skvrny na slunci a pustíte to z hlavy.
  • S rostoucí popularitou podobných situací začne přibývat.
  • Jak podobých incidentů začne přibývat, začne se šířit pověst o nespolehlivé aplikaci. Popularita a důvěra klesá. Word of mouth.

Takhle můžete dopadnout, když nevěnujete dostatečnou pozornost tomu, co se všechno může stát, pokud k vaší aplikaci přistupuje více lidí zároveň.

Na co dávat pozor

Pozor je potřeba dávat vždy, když přistupujete k nějakým sdíleným zdrojům. Sdílené zdroje = cokoli mimo kontext aktuálního HTTP požadavku. Příkladem sdílených zdrojů jsou hlavně soubory a databáze, ale zdaleka nejen.

V některých prostředích, včetně ASP.NET, také statické členy tříd. Přestože pro každý požadavek se vytváří nová instance stránky, nový HttpContext a spousta dalších věcí, samotné třídy jsou v celé aplikaci sdílené (rozdíl od PHP). Lze snadno ověřit:

<%@ Page Language="C#" Inherits="System.Web.UI.Page" %>
<script runat="server">
    static string Blah = "Default value.";
</script>

<html>
<body>
    <p>
        <%= Blah %>
        <% Blah = "Changed value."; %>
    </p>
</body>
</html>

Při prvním spuštění vypíše „Default value“, při každém dalším obnovení stránky „Changed value“, až do restartu aplikace. Ovšem lze kód upravit tak, aby ten člen byl „statický“ jen v rámci aktuálního požadavku:

static string Blah
{
    get { return HttpContext.Current.Items["Blah"] as string; }
    set { HttpContext.Current.Items["Blah"] = value; }
}

HttpContext.Current je sice také statická property, ale používá různé instance HttpContext podle toho, z kterého ji voláme threadu.

Přístupy ke sdíleným zdrojům je nutné nějak synchronizovat. Aby například během procesu zápisu do souboru (od otevření až do zavření), žádný jiný thread nemohl ten soubor číst. Ale to teď nechám být, teď mi jde jenom o odhalení těch přístupů.

Dávat pozor nestačí

Jenže dávat pozor nestačí.

Často si nemusíte uvědomit, že zdroj, ke kterému přistupujete, je sdílený. Někdy to ani nemusí být moc zřejmé (třeba nějaké knihovny třetích stran můžou používat statické členy vnitřně). Nebo si nemusíte uvědomit, že některá operace není atomická.

Před třemi lety bych vůbec nepřemýšlel, jestli PHP funkce file_put_contents() je nebo není atomická. Kdyby mě to bylo napadlo, tak bych býval během chvilky splácl jednoduchý test, ale mě to ani nenapadlo… Udělal jsem za tu dobu dostatečný pokrok, abych se mohl spolehnout jen na svůj úsudek? Na to bych nespoléhal.

Epilog

Logicky tedy vyvstává potřeba nějak testovat chování aplikace při více uživatelích naráz. Zkoušel jsem najít nějaké nástroje a postupy, které by v tomhle pomáhali, ale asi jsem špatně hledal.

Představuju si to asi tak, že nadefinuju uživatelské kroky, které pak nechám provést třeba 50 robotů zároveň.

Nakonec jsem si vytvořil takovou jednoduchou utilitku sám. Používá Příkazový řádek, Selenium a spoustu Firefoxů… Až udělám nějaké screenshoty, sepíšu o tom článek a hodím to sem.

Ale už teď mě zajímá: Testujete nějak chování aplikace pod palbou uživatelských akcí, ještě před jejím vypuštěním?

« Previous Entries
Další možnosti...

Blogroll

  • Blog vývojářů
  • Česká verze
  • Dokumentace
  • Fórum podpory
  • Motivy vzhledu
  • Pluginy
  • Vaše nápady
  • WordPress Planet
  • Pages

    • Diakritika v doméně? WTF?
    • O těchto stránkách

Your List

  • Your list items
  • Your list items
  • Your list items
  • Your list items
  • Your list items

© Ááá * WordPress * LoseMyMind * Feed feed