Pingy – mokomės Windows Azure kuriant realią aplikaciją

Parašė Sergejus | 2010-09-02 21:23

Taip, ir vėl aš pradedu straipsnių ciklą, skirtą Windows Azure programavimui. Daugiau nei prieš pusmetį parašiau 7 dalių įvadą į Windows Azure:

Įvadas į Windows Azure – 1 dalis (Pagrindinės sąvokos)
Įvadas į Windows Azure – 2 dalis (Windows Azure Hello World ASP.NET puslapio kūrimas)
Įvadas į Windows Azure – 3 dalis (lokalios objektinės Windows Azure saugyklos konfigūravimas)
Įvadas į Windows Azure – 4 dalis (lokalios BLOB saugyklos panaudojimas)
Įvadas į Windows Azure – 5 dalis (lokalios BLOB saugyklos perkėlimas į Windows Azure)
Įvadas į Windows Azure – 6 dalis (esybių lentelių saugyklos panaudojimas)
Įvadas į Windows Azure – 7 dalis (XDrive panaudojimas)

Kas atsimena, po 7 dalies iš manęs staiga atėmė testinį Windows Azure prisijungimą. Kurį laiką bandžiau jį atgauti ir tik prieš kelis mėnesius per MVP kanalą Windows Azure grupė suteikė man naują prisijungimą. Vėl atsiradus galimybei, nusprendžiau pratęsti pažintį su Windows Azure, bet šį kartą kuriant realią aplikaciją.

Tie, kas užsiima Web programavimu .NET platformoje, tikriausiai yra susidūrę su viena IIS problema – po tam tikro neveikimo laiko jis tiesiog „užmiega“, dėl ko pirma HTTP užklausa užtrunka pakankamai ilgai. Yra keletas galimų būdų šiai problemai apeiti: AppPool Recycling; Windows servisas, kuris kas nustatytą laiką kreipiasi į nurodytą Web aplikaciją ir t.t. Aš nusprendžiau sukurti paslaugą (servisą), kuri leistų vartotojui nurodyti į kokį URL kokiu dažnumu reikia kreiptis. Tuo pačiu būtų kaupiama ir serverio veikimo statistika, pavyzdžiui, atsakos laikas, atsakymo HTTP kodas ir pan.

Tikrai žinau, kad panašios paslaugos egzistuoja (ir žymiai geresnės), bet mano tikslas yra kitas – geriau išmokti Windows Azure. Aplikaciją pavadinau Pingy (nuo angl. ping), kitame straipsnyje aš trumpai aprašysiu jos architektūrą, pateiksiu sekų diagramą bei paaiškinsiu kaip bus siekiama ypatingai geros greitaveikos bei plečiamumo (angl. scalability), kurį įgalina Windows Azure platformą.

Windows 7 Ultimate nemokamai #5 - laimėtojas paaiškėjo

Parašė Sergejus | 2010-09-01 18:43

Štai ir atėjo laikas atiduoti paskutinį Windows 7 Ultimate diską, kurį laimėjo…

winner

… skaitytojas vardu benjaminas. Nuoširdžiai sveikinu ir prašau susisiekti su manimi. Nors kompaktų daugiau ir nebeliko, bet tai nereiškia, kad nebus naujų konkursų. Laukite tęsinio!

Paprastas būdas atvaizduoti Twitter pranešimus

Parašė Sergejus | 2010-08-31 14:03

Twitter pranešimų atvaizdavimas puslapiuose nėra naujas uždavinys. Egzistuoja bent keletas būdų kaip tai galima atlikti (įskaitant ir gatavus komponentus). Šiandien man prisireikė atvaizduoti su tam tikra hash žyme susijusius pranešimus ir padaryti tai norėjosi kuo paprasčiau (kad daugiau žmonių suprastų kas ir kaip yra daroma).

Pirmas dalykas kurį verta išnagrinėti – Twitter API dokumentaciją. Norint gauti su tam tikra hash žyme susijusius pranešimus, užtenka pasinaudoti metodu Search. Iš reikalingų metodo parametrų mums bus reikalingi keli:

  • callback – mūsų atveju tai bus anoniminė funkcija, todėl užrašas atrodys taip: callback=?
  • rpp – grąžinamų pranešimų skaičius
  • q – paieškos žymė, kur vietoje grotelių reikia rašyti %23, pvz., %23mvc (bus ieškoma #mvc)

Sakykime, mes turime tokį HTML kodą:

<div id="sidebar">
    <ul>
        <li>
            <h2>Info</h2>
            Blog: http://sergejus.blogas.lt </li>
        <li>
            <h2>Twitter</h2>
            <ul id="tweets">
            </ul>
        </li>
    </ul>
</div>

Norėdami į elementą tweets pakrauti Twitter pranešimus, aprašykime tokią JavaScript funciją:

function loadTweets(container, search) {
    var url = 'http://search.twitter.com/search.json?callback=?&rpp=10&q=' + search;
    $.getJSON(url, function (data) {
        var html = '';
        $.each(data.results, function (i, tweet) {
            html += '<li><a href="http://twitter.com/' + tweet.from_user + '">'
                 + tweet.from_user + '</a> ' + tweet.text + '</li>';
        });
        $(container).html(html);
    });
}

Kaip matyti, viskas labai paprasta:

  • kreipimąsi į Twitter API
  • gaunamas JavaScript objektas
  • suformuojamas LI elementas
  • galutinis HTML įrašomas į UL elementą

Svarbu tai, kad ši JavaScript funkcija gali ieškoti bet ką. Mūsų atveju loadTweets panaudojimas atrodytų taip:

<script type="text/javascript">
    $(document).ready(function () {
        loadTweets('#tweets', '%23pingy');
    });
</script>

Štai ir viskas – greitai, paprastai, suprantamai.

Atostogos

Parašė Sergejus | 2010-08-06 16:51

Atėjo ir mano laikas dviem savaitėms pasitraukti nuo programavimo, Interneto ir kitų IT naujienų. Pradedant nuo kitos savaitės, išvykstu atostogauti, o tai reiškia, kad ir nebus naujų straipsnių. Iki susitikimo rugpjūčio pabaigoje!

WebMatrix ir Visual Studio LightSwitch – kur juda Microsoft?

Parašė Sergejus | 2010-08-04 15:12

Kažkur prieš mėnesį ScottGu anonsavo WebMatrix. Kas dar nesate girdėję apie šį produktą, rekomenduoju perskaityti ScottGu straipsnį. Trumpai apibendrinant – tai kelių technologijų rinkinys: SQL CE 4.0 (Compact Edition), IIS Developer Express, naujasis ASP.NET atvaizdavimo variklis (angl. View Engine) Razor bei WebMatrix kūrimo aplinka. Nors visos minėtos technologijos ir pristatomos kartu, realiai jos yra nepriklausomos ir gali būti naudojamos atskirai. Taip, greičiausiai, IIS Developer Express pakeis esamą Visual Studio Web serverį (dar žinomą kodiniu pavadinimu Cassini), Razor bus ASP.NET MVC 3 dalimi, o SQL CE visada ir taip buvo nepriklausomas. Kas tikrai yra įdomu – WebMatrix kūrimo aplinka. Padirbęs su ja porą valandų galiu teigti, kad ji tikrai nėra tinkama kiek didesnių Web aplikacijų kūrimui, bet jos paskirtis ir nėra tokia. Pirmą kartą Microsoft žengia į sau naują auditoriją – naujokų (skaityk neprofesionalų) gretas. Nesunku suprasti, kad taip bandoma atgauti iš PHP dalį pradedančiųjų Web programuotojų. Ar tai gerai? Apie tai kiek vėliau…

WebMatrix

Kitas įdomus anonsas įvyko vakar – Microsoft pristatė Visual Studio LiveSwitch. Bendram įsivaizdavimui labai rekomenduoju perskaityti JasonZ straipsnį. Visual Studio LiveSwitch – tai (ir vėl) kūrimo aplinka, skirta taip vadinamų Line of Business (LOB) programų kūrimui. Pagrindinė naujo produkto užduotis – įgalinti neprofesionalius programuotojus (dažniausiai verslo konsultantus ar techninio palaikymo skyriaus darbuotojus) kurti nesudėtingas, padalinio darbui reikalingas programas. Tokios programos iš dalies panašios į Access programas: turi UI su daug laukų, naudoja duomenis iš heterogeninių šaltinių, lokalius duomenis saugo vidinėje duomenų bazėse. Akivaizdu, kad Access + VBS yra keičiami Silverlight + WCF RIA Services + SQL CE. Taipogi akivaizdu, kad vis daugiau neprogramuotojų pradės kurti programas…

LOB

Kaip matyti, tiek WebMatrix, tiek Visual Studio LightSwitch yra skirti neprofesionaliems programuotojams. Ar tai gerai? Žinoma! Kai aš pradėjau programuoti, neturėjau jokio suvokimo apie OOP, gerąsias praktikas, architektūrą ir pan. Bet tuo metu man to ir nereikėjo, aš tiesiog norėjau pradėti programuoti. Iš kitos pusės, aš bijau ilgainiui gali atsirasti vis daugiau mėgėjiškų programų, kurių kokybė gali neigiamai įtakoti .NET Framework vardą. Taip kadaise įvyko PHP ir ilgą laiką buvo laikoma, kad PHP nėra tinkamas Enterprise aplikacijoms.

Būtų labai įdomu išgirsti jūsų nuomonę apie šiuos produktus ir naują Microsoft judėjimo kryptį.

Windows 7 Ultimate nemokamai #5

Parašė Sergejus | 2010-08-01 22:40

IMG_0088

Taisyklės:

Šio straipsnio komentaruose parašykite savo vardą ir pavardę arba slapyvardį. Kadangi rugpjūtį aš atostogausiu ir nebūsiu Lietuvoje, rašyti komentartuose galite iki paskutinės mėnesio dienos. Rugsėjo 1-ą atsitiktine tvarka išrinksiu vieną nugalėtoją, kuriam ir atiteks paskutinė dovana. Kompaktą galėsiu perduoti tik VILNIUJE ir KAUNE. Jeigu esate iš kito miesto – teks patiems atvažiuoti į Vilnių.

Jeigu akcija patinka, nepamirštame paspausti ‘Patiko’.

Windows 7 Ultimate nemokamai #4 - laimėtojas paaiškėjo

Parašė Sergejus | 2010-08-01 22:36

Taigi pasibaigė mėnuo, o tai reiškia, kad antrą Windows 7 Ultimate diską laimėjo…

results

…skaitytojas vardu Gediminas G. Prašau susisiekti su manimi el. paštu (ar parašykite savo) ir aš perduosiu prizą. Nenusiminkite kam nepasisekė, nes dar liko vienas Windows 7 Ultimate DVD diskas.

ASP.NET MVC klaidų apdorojimas iš JavaScript

Parašė Sergejus | 2010-07-27 22:23

Šiais laikais praktiškai sunku įsivaizduoti Web aplikaciją, kuri nenaudotų Ajax technologijos. Vienas iš tradicinių Ajax panaudojimo pavyzdžių – asinchroninis duomenų pakrovimas (kuris su ASP.NET MVC ir jQuery tapo kaip niekada paprastas). Sakykime, mes turime kontrolerį Home:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult GetList()
    {
        throw new HttpException((int)HttpStatusCode.NotImplemented, "This method is not yet implemented");
    }
}

Ir turime puslapį Index.aspx:

<!DOCTYPE>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>ASP.NET MVC serverinių klaidų apdorojimas iš JavaScript</title>
    <script type="text/javascript" src="http://ajax.microsoft.com/ajax/jQuery/jquery-1.4.1.js"></script>
</head>
<body>
    <div id="list_content"></div>
</body>
<script type="text/javascript">
    $.ajax({
        url: '/Home/GetList',
        cache: false,
        success: function (data) {
            $('#list_content').html(data);
        }
    });
</script>
</html>

Kaip matyti iš pateikto kodo, pasikrauna tuščias puslapis, kuris bando į DIV elementą asinchroniškai pakrauti duomenis kviečiant kontrolerio Home metodą GetList (kuris pas mus išmeta klaidą). Kaip teisingai pagauti ir apdoroti serverio klaidas iš JavaScript?

Pirma reikia papildyti mūsų kontrolerį perrašant metodą OnException (šią logiką aš dažniausiai iškeliu į bazinį kontrolerį):

protected override void OnException(ExceptionContext filterContext)
{
    if (filterContext.HttpContext.Request.IsAjaxRequest())
    {
        var statusCode = filterContext.Exception is HttpException ?
                        (filterContext.Exception as HttpException).GetHttpCode() :
                        (int)HttpStatusCode.InternalServerError;
        filterContext.HttpContext.Response.StatusCode = statusCode;
        filterContext.Result = new JsonResult
        {
            JsonRequestBehavior = JsonRequestBehavior.AllowGet,
            Data = new
            {
                filterContext.Exception.Message,
                filterContext.Exception.StackTrace,
                Url = filterContext.HttpContext.Request.RawUrl
            }
        };
        filterContext.ExceptionHandled = true;
    }
}

Išnagrinėkime kas yra daroma. Pirma patikrinama ar klaida kilo asinchroninio kreipinio metu. Jeigu taip – patikrinama ar tai HTTP klaida ir jeigu ne, suteikiamas HTTP501 (Internal Server Error) klaidos kodas. Galiausiai yra sudaromas JSON atsakymas, kuriame yra talpinama visa su klaida susijusi informacija (galima papildyti pagal poreikį). Tokiu būdu, vykdant asinchroninį kreipinį, kurio metu serveryje įvyksta klaida, mes gauname klaidos JSON objektą. Beliko šį objektą apdoroti HTML pusėje, tam papildysime jQuery ajax metodą:

<script type="text/javascript">
    $.ajax({
        url: '/Home/GetList',
        cache: false,
        success: function (data) {
            $('#list_content').html(data);
        },
        error: function (response) {
            var ex = $.parseJSON(response.responseText);
            alert("HTTP" + response.status + ": " + ex.Message);
        }
    });
</script>

Įvykus klaidai serverio pusėje, mes gauname klaidos JSON objektą (objekto response savybė responseText), kuriuo toliau galime operuoti apdorojant klaidą.

Tiek mano patirties iš ASP.NET MVC klaidų apdorojimo iš JavaScript. O kokius dar “triukus” jus taikote JavaScript klaidų apdorojimui?

Patogesnis darbas su ConfigurationManager klase

Parašė Sergejus | 2010-07-16 23:45

ConfigurationManager yra viena svarbiausių dažniausiai naudojamų .NET klasių, nes būtent ji yra naudojama nustatymų iš web.config ar app.config nuskaitymui. Vienas dalykas kuris paskutiniu metu šioje klasėje man nepatinka – kodo ilgis, reikalingas pasiekti nustatymą iš appSettings skilties ar prisijungimo eilutę iš connectionStrings skilties. Pavyzdžiui, norint nuskaityti nustatymą Name, reikia tokio kodo:

var name = ConfigurationManager.AppSettings["Name"];

PrisijungimoEilutės Connection nuskaitymas reikalauja dar daugiau kodo:

var connection = ConfigurationManager.ConnectionStrings["Connection"].ConnectionString;

Šiandien noriu pasiūlyti jums supaprastiną ConfigurationManager klasę Config. Klasės interfeisus (reikalavimus) aprašiau kaip testus:

[TestClass]
public class ConfigTest
{
    [TestMethod]
    public void NamePropertyReturnsSameValueAsAppSettings()
    {
        var actual = Config.Current.Name;
        var expected = ConfigurationManager.AppSettings["Name"];

        Assert.AreEqual(expected, actual);
    }

    [TestMethod]
    public void ConnectionPropertyReturnsSameValueAsConnectionStringWhenNoAppSettingsWithSameKeyExist()
    {
        var actual = Config.Current.Connection;
        var expected = ConfigurationManager.ConnectionStrings["Connection"].ConnectionString;

        Assert.AreEqual(expected, actual);
    }

    [TestMethod]
    public void DatabasePropertyReturnsSameValueAsAppSettingsEvenWhenConnectionStringWithSameKeyExist()
    {
        var actual = Config.Current.Database;
        var expected = ConfigurationManager.AppSettings["Database"];

        Assert.AreEqual(expected, actual);
    }

    [TestMethod]
    public void NewInstanceOfConfigCanBeCreatedAndUsedToAccessAppSettingsWithKeyName()
    {
        dynamic config = new Config();
        var actual = config.Name;
        var expected = ConfigurationManager.AppSettings["Name"];

        Assert.AreEqual(expected, actual);
    }

    [TestMethod]
    [ExpectedException(typeof(RuntimeBinderException))]
    public void NonExistingAppSettingsKeyAndConnectionStringKeyThrowsException()
    {
        var actual = Config.Current.NonExisting;
    }
}

Testams naudojamas toks app.config failas:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add name="Connection" connectionString="StubConnectionString"/>
    <add name="Database" connectionString="StubDatabaseConnectionString"/>
  </connectionStrings>
  <appSettings>
    <add key="Name" value="Sergejus"/>
    <add key="Database" value="StubDatabaseSetting"/>
    <add key="Age" value="25"/>
  </appSettings>
</configuration>

Kaip matote, pagrindinis noras buvo pasiekti tiek AppSettings, tiek ConnectionStrings nustatymus kaip savybes. Tai ypač lengva realizuoti naudojant C# 4.0 dinaminius objektus:

public class Config : DynamicObject
{
    private static readonly Config config = new Config();

    public static dynamic Current
    {
        get
        {
            return config;
        }
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = ConfigurationManager.AppSettings[binder.Name];

        if (result == null && ConfigurationManager.ConnectionStrings[binder.Name] != null)
        {
            result = ConfigurationManager.ConnectionStrings[binder.Name].ConnectionString;
        }

        return result != null;
    }
}

O ką jus manote apie tokios klasės naudą? Kaip visada laukiu komentarų…

Windows 7 Ultimate nemokamai #4

Parašė Sergejus | 2010-07-16 16:48

IMG_0088

Taisyklės:

Šio straipsnio komentaruose parašykite savo vardą ir pavardę arba slapyvardį. Kiekvieno mėnesio 15-ą bei paskutinę dieną atsitiktine tvarka išrinksiu vieną nugalėtoją, kuriam ir atiteks dovana. Kompaktą galėsiu perduoti tik VILNIUJE ir KAUNE. Jeigu esate iš kito miesto – teks patiems atvažiuoti į Vilnių.

Jeigu akcija patinka, nepamirštame paspausti ‘Patiko’.