Fujiy

Blog sobre .NET, C#, ASP.NET entre outras tecnologias de desenvolvimento de software

A diferença que o C# 5.0 faz com o async/await

11/03/2013 20:51:02 Por Fujiy

A melhor forma de ver a grande diferença que o async faz é usando exemplos. Saindo de um código não só maior, mas muito mais complicado, com callbacks, tratamento de contexto e thread de execução, tratamento de erros aninhados com os callbacks, pra um código simples, como se fosse um código síncrono comum.

Código Antigo:

void ShowStuff()
{
    var client = new WebClient();
    var content = JsonValue.Parse(client.DownloadString("http://api.worldbank.org/countries?format=json&per_page=50"));
    int number_of_countries = content[0]["total"];
    int done = 0, error = 0;
 
    InvokeOnMainThread(() =>
    {
        CountriesLabel.Text = string.Format("Countries: {0} done: 0 error: 0", number_of_countries);
    });
 
    foreach (JsonObject c in content[1])
    {
        string country_url = string.Format("http://api.worldbank.org/countries/{0}/indicators/NY.GDP.MKTP.CD&format=json", (string)c["id"]);
        JsonValue json = null;
 
        try
        {
            json = JsonValue.Parse(client.DownloadString(country_url));
        }
        catch (Exception e)
        {
            ++error;
            InvokeOnMainThread(() => status.Text = "Got exception " + e);
            continue;
        }
 
        ThreadPool.QueueUserWorkItem(delegate
        {
            Map map = null;
            try
            {
                map = LoadCountryLogo(c["name"]).Result;
            }
            catch (Exception e)
            {
                ++error;
                InvokeOnMainThread(() => status.Text = "Got exception " + e);
            }
            if (map != null)
            {
                ThreadPool.QueueUserWorkItem(delegate
                {
                    Position position = null;
 
                    try
                    {
                        position = LookupCountryPosition(c["longitude"], c["latitude"]).Result;
                        if (position != null)
                            InvokeOnMainThread(() =>
                            {
                                AddPin(map, position);
                                ++done;
                                status.Text = json["name"];
 
                            });
                    }
                    catch (Exception e)
                    {
                        error++;
                        InvokeOnMainThread(() => status.Text = "Got exception " + e);
                    }
 
                });
            }
        });
 
        InvokeOnMainThread(() => CountriesLabel.Text = string.Format("Countries: {0} done: {1} error: {2}", number_of_countries, done, error));
    }
    InvokeOnMainThread(() =>
    {
        CountriesLabel.Text = string.Format("Countries: {0}", number_of_countries);
    });
}

Código usando C# 5.0:

async Task ShowStuffAsync()
{
    var client = new HttpClient();
 
    var content = JsonValue.Parse(await client.GetStringAsync("http://api.worldbank.org/countries?format=json"));
    int number_of_countries = content[0]["per_page"];
    int done = 0, error = 0;
 
    CountriesLabel.Text = string.Format("Countries: {0} done: 0 error: 0", number_of_countries);
 
    foreach (JsonObject c in content[1])
    {
        try
        {
            string country_url = string.Format("http://api.worldbank.org/countries/{0}/indicators/NY.GDP.MKTP.CD&format=json", (string)c["id"]);
            var json = JsonValue.Parse(await client.GetStringAsync(country_url));
            var map = await LoadCountryLogoAsync(json["name"]);
            if (map != null)
            {
                var position = await LookupCountryPositionAsync(c["longitude"], c["latitude"]);
                if (position != null)
                {
                    AddPin(map, position);
                    status.Text = json["name"];
                    ++done;
                }
            }
 
        }
        catch (Exception e)
        {
            ++error;
            status.Text = "Got exception " + e;
        }
        CountriesLabel.Text = string.Format("Countries: {0} done: {1} error: {2}", number_of_countries, done, error);
    }
    CountriesLabel.Text = string.Format("Countries: {0}", number_of_countries);
}

 

Unobtrusive jQuery Validation com forms dinâmicos

05/03/2013 21:53:00 Por Fujiy

Recentemente tive um problema ao usar um form dinâmico no ASP.NET MVC. A validação não "intrusiva" é processada assim que a página termina de carregar, e a partir daquele momento não é mais alterada. Porém eu tinha uma página que carregava todo o conteúdo do form via Ajax, e neste caso é ainda pior do que carregar um novo form, pois se o form já existia ele é marcado para não ser processado novamente, então preciso primeiro desmarca-lo e depois ativar a validação novamente. O código é simples, só não é algo suportado ou documentado, e depende de detalhes da implementação atual:

var form = $('#form-adiciona-entrega');

form.removeData('validator').removeData('unobtrusiveValidation');//Este passo só é necessário se o form já existia. Se o form em si é gerado dinamicamente, não precisa desse "reset"

$.validator.unobtrusive.parse(form);

 

Encontrei também este código, que diz fazer isso automaticamente a cada chamada ajax, mas que depende também de detalhes do ASP.NET MVC:

$(document).ajaxSuccess(function (event, xhr, settings) {
   if (settings.mvcTargetElement) {
       $(settings.mvcTargetElement.getAttribute("data-ajax-update")).each(function () {
          $.validator.unobtrusive.parse(this);
     });
  }
});

 

 

Fontes:

http://btburnett.com/2011/01/mvc-3-unobtrusive-ajax-improvements.html

http://stackoverflow.com/questions/11045256/jquery-client-side-validate-not-working

Poster WebApi HTTP Message Lifecycle

30/01/2013 22:47:44 Por Fujiy

Esse poster disponibilizado pela Microsoft mostra o fluxo de uma chamada e resposta HTTP pelo pipeline do WebApi, exibindo também os pontos de extensão onde você pode customizar o fluxo.

http://www.microsoft.com/en-us/download/details.aspx?id=36476

 

jQuery 1.9 RC1 and Migrate RC1

09/01/2013 22:03:36 Por Fujiy

Menos de um mês após o Beta 1 saiu a versão Release Candidate 1. A nova versão 1.9 é um marco na história do jQuery, a intenção é remover o "lixo" acumulado pra manter a compatibilidade com versões antigas, assim muitas partes que estavam obsoletas foram removidas do código.

Para manter funcionando a base de código atual eles disponibilizaram um plug-in chamado jquery-migrate que permite restaurar as funcionalidades obsoletas, emitindo um alerta no console de desenvolvimento, assim você pode ajustar os códigos conforme for possível.

Na versão seguinte, 2.0, será abandonado o suporte aos Internet Explorer´s 6, 7 e 8 que hoje são um problema, obrigando o time do jQuery a inserir diversos hacks pra funcionar como deveria. Assim a versão 2.0 será menor, mais rapida e com menos problemas causados por esses hacks.

Para fazer a migração é só substituir o seu script jQuery por estes:

<script src="http://code.jquery.com/jquery-1.9.0rc1.js"></script>
<script src="http://code.jquery.com/jquery-migrate-1.0.0rc1.js"></script>

Se você usa o jQuery 1.6.4 ou superior também pode incluir apenas o jquery-migrate para ver quais avisos aparecem.

Ao achar algum bug, você deve reportar no site http://bugs.jquery.com

MSDN Magazine - Janeiro de 2013

09/01/2013 21:59:04 Por Fujiy

A primeira edição do ano já está disponível. Com destaque para os artigos "TypeScript: Making .NET Developers Comfortable with JavaScript" e a segunda parte do "The C# Memory Model in Theory and Practice", a primeira parte está na edição de dezembro.

MSDN Magazine Janeiro de 2013. O PDF deve ficar disponível em breve.