Oi de novo. Raro isso, duas postagens em um dia. Essa vai ser mais curta.
A segunda coisa que fui ver no MVC4 foi a parte de display mode. Agora você simplesmente cria uma view com o mesmo nome da original e .mobile antes da extensão e o MVC magicamente detecta se a requisição vem de um celular, e direciona para a view certa. Bom demais pra ser verdade?
Pois é. Criei a aplicação MVC4, criei minhas views, publiquei a aplicação no meu IIS para ver do celular. Tenho um android e meu browser é o firefox lá também. Não funcionou. Procurei a achei uma variável que retorna se é Mobile*. Trazia false.
Mas há uma solução para que você adicione seus próprios display modes. Vi que o user agent do meu browser no celular: "Mozilla 5.0 (Android; Mobile; rv:14.0) (...)". Coloquei no Global.asax, no Application_Start, como ensinado em vários sites:
DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("mobile")
{
ContextCondition = (context => context.Request.UserAgent.IndexOf
("mobile", StringComparison.OrdinalIgnoreCase) >= 0)
});
Funcionou. Chamou a view que tinha antes da extensão ".mobile". Agora, o celular da minha irmã, só para fazer um teste final... Não funcionou. A palavra mobile não está no user agent. Ela tem um samsung que não é android. O browser é o que veio com o próprio SO. Baixei novamente o browser que veio no meu android: Dolphin. Este possuía a palavra mobile na descrição.
Tentando evitar problemas, uma das soluções que achei é testar, além de mobile, mais alguns nomes de aparecem em celulares. Encontrei uma pequena lista neste artigo: http://www.add-digital.com.br/blog/como-acessar-a-versao-mobile-do-seu-site-atraves-do-javascript/. Caso o artigo saia do ar, aqui está a lista:
nokia, iphone, blackberry, sony, lg, htc_tattoo, samsung, symbian, SymbianOS, palm, series60, windows ce, android, obigo, netfront, openwave, mobilexplorer, operamini
So, that's all for now, folks!
* na view - ViewContext.HttpContext.GetOverriddenBrowser().IsMobileDevice
terça-feira, 10 de julho de 2012
segunda-feira, 9 de julho de 2012
MVC4 - Async
Bom dia... Faz tempo que não posto alguma coisa. Enfim.
Estou vendo MVC4 agora. No momento, mexendo com a parte de chamadas assíncronas.
A primeira coisa é que queria construir algum exemplo simples, para entender melhor. Os que achei envolviam serviços e eu não queria criar um serviço para depois testar o que eu precisava.
Meu primeiro problema foi que o .NET 4.0 não conhece as keywords novas, async e await. Instalei o 4.5. Mas o Visual Studio 2010 não conhece o 4.5. Tentei até mudar no arquivo csproj em um editor de texto, mas não funcionou. Tive que instalar o VS2012 RC (http://www.microsoft.com/visualstudio/11/en-us). Se quer um conselho, não resolva instalar às 21h da sexta-feira.
Vamos à programação. Descobri que eu tinha que criar um método que chamasse qualquer outra coisa assíncrona. Pelo que li, já no 4.0 foram implementados métodos assíncronos no .NET. Tentei com chamada para a internet, mas retornava muito rápido.
O que resolvi usar foi leitura de um arquivo grande (precisava ser grande para testar o tempo, se realmente diminuiria). Meu computador é um core i5, 2,3 GHz, 4gB de ram, 64bit. Dois arquivos de mais ou menos 130mB foram usados.
Usei a classe StreamReader para ler, o método ReadToEndAsync. Para o método ser assíncrono, deve ser colocada a keyword async antes do tipo do método. Os métodos assíncronos que forem chamados dentro dele devem ser chamados com a keyword await antes, se for necessário aguardar o retorno deles para continuar.
Para o retorno do método, se usa a classe Task. Sozinha se for um void, como generic se houver algum tipo de retorno (passando o tipo do retorno real para a Task).
Meu método de leitura:
private async Task<String> readAsync(String filename)
{
var reader = new StreamReader(filename);
return await reader.ReadToEndAsync();
}
Chegou a me passar pela cabeça: se ele chama o método assíncrono e fica esperando o retorno, qual a diferença de fazer isso ou chamar o convencional mesmo? Eis a resposta:
var first = readAsync(firstFile);
await readAsync(secondFile);
await first;
Chamamos o primeiro, esperamos a execução do segundo, então esperamos a do primeiro (provavelmente ele já terá terminado). O primeiro fica executando ao mesmo tempo que o segundo. Uma economia de mais de 25% do tempo. Testei com 3 arquivos, cada qual em torno de 80mB. Quase 45% de ganho.
Problemas que esbarrei, para tomar cuidado:
Meu ponto de partida foi este artigo: http://www.asp.net/whitepapers/mvc4-release-notes#_Toc303253813. A parte do timeout que cita não consegui fazer funcionar. Ele até retorna um erro de timeout, mas não redireciona para a view (nem trocando o tipo do erro para o que aparece na tela amarela) e executa o processo inteiro antes de retornar o timeout. Não me parece muito útil desse jeito.
* using (var reader = new StreamReader(filename))
Estou vendo MVC4 agora. No momento, mexendo com a parte de chamadas assíncronas.
A primeira coisa é que queria construir algum exemplo simples, para entender melhor. Os que achei envolviam serviços e eu não queria criar um serviço para depois testar o que eu precisava.
Meu primeiro problema foi que o .NET 4.0 não conhece as keywords novas, async e await. Instalei o 4.5. Mas o Visual Studio 2010 não conhece o 4.5. Tentei até mudar no arquivo csproj em um editor de texto, mas não funcionou. Tive que instalar o VS2012 RC (http://www.microsoft.com/visualstudio/11/en-us). Se quer um conselho, não resolva instalar às 21h da sexta-feira.
Vamos à programação. Descobri que eu tinha que criar um método que chamasse qualquer outra coisa assíncrona. Pelo que li, já no 4.0 foram implementados métodos assíncronos no .NET. Tentei com chamada para a internet, mas retornava muito rápido.
O que resolvi usar foi leitura de um arquivo grande (precisava ser grande para testar o tempo, se realmente diminuiria). Meu computador é um core i5, 2,3 GHz, 4gB de ram, 64bit. Dois arquivos de mais ou menos 130mB foram usados.
Usei a classe StreamReader para ler, o método ReadToEndAsync. Para o método ser assíncrono, deve ser colocada a keyword async antes do tipo do método. Os métodos assíncronos que forem chamados dentro dele devem ser chamados com a keyword await antes, se for necessário aguardar o retorno deles para continuar.
Para o retorno do método, se usa a classe Task. Sozinha se for um void, como generic se houver algum tipo de retorno (passando o tipo do retorno real para a Task).
Meu método de leitura:
private async Task<String> readAsync(String filename)
{
var reader = new StreamReader(filename);
return await reader.ReadToEndAsync();
}
Chegou a me passar pela cabeça: se ele chama o método assíncrono e fica esperando o retorno, qual a diferença de fazer isso ou chamar o convencional mesmo? Eis a resposta:
var first = readAsync(firstFile);
await readAsync(secondFile);
await first;
Chamamos o primeiro, esperamos a execução do segundo, então esperamos a do primeiro (provavelmente ele já terá terminado). O primeiro fica executando ao mesmo tempo que o segundo. Uma economia de mais de 25% do tempo. Testei com 3 arquivos, cada qual em torno de 80mB. Quase 45% de ganho.
Problemas que esbarrei, para tomar cuidado:
- Tentei fazer com três arquivos, dos maiores. Recebi uma bela OutOfMemoryException. Precisa de um pouco de cuidado, não pedir muita coisa ao mesmo tempo;
- Tentei abrir o StreamReader com using*, mas ele fechou o arquivo antes de ler, por ser assíncrono. Então, cuidado quando faz dispose de objetos, sendo assíncrono você nunca sabe quando vai realmente usá-los, a menos que use await.
Meu ponto de partida foi este artigo: http://www.asp.net/whitepapers/mvc4-release-notes#_Toc303253813. A parte do timeout que cita não consegui fazer funcionar. Ele até retorna um erro de timeout, mas não redireciona para a view (nem trocando o tipo do erro para o que aparece na tela amarela) e executa o processo inteiro antes de retornar o timeout. Não me parece muito útil desse jeito.
* using (var reader = new StreamReader(filename))
Assinar:
Postagens (Atom)