É um problema recorrente, você faz uma atualização, em um sistema, e de repente metade dos clientes tem problemas com a atualização e tudo é resolvido com uma simples limpeza de cache.  Isso ocorre quando alguma mudança envolve um script, os browsers guardam o cache dos scripts afim de agilizar o carregamento das páginas.

Solução simples

Para resolver não vamos limpar o cache do browser mas faze-lo baixar o arquivo.

É dessa forma que geralmente é inserido um script na página:

<script src="meu_script.js"></script>

Só o que precisamos fazer é incluir uma querystring no src da tag:

<script src="meu_script.js?v=2"></script>

Ou seja a cada vez que você mudar esse número o browser vai entender que esse arquivo é diferente do que ele já tem, não necessitando limpar o cache.

Eu particularmente adoro quando a solução é simples :)

Conforme prometido no post anterior, neste tutorial vou mostrar como criar um Helper para manipular coleções. 


Para começar caso você ainda não tenha feito, leia o post anterior que mostrar como eliminar os índices em coleções no ASP.NET MVC. Vou utilizar como exemplo as classes Pessoa (Person) e Telefones(Phone) onde pessoa pode ter 1 ou mais telefones, deve ser criada uma view separada para edição dos telefones isso é possível utilizando o Editor Templates do ASP.NET MVC.




Para utilizar você deve criar uma pasta chamada EditorTemplates, dentro da pasta você adiciona uma view com o mesmo nome do Model, que neste exemplo é Phone. Crie a view conforme o exemplo abaixo:


A divs que envolvem os campo não são obrigatórias.

Na view de criação, do modelo Person, você deve referenciar o editor dos telefones, conforme exemplo abaixo: 


Vamos agora a criação do Helper. Crie uma classe static com o nome de  HtmlHelpers. Dentro dessa classe crie um método conforme o exemplo abaixo:


Esse será o método responsável por adicionar mais um campo. Esse método é uma extenção da classe HtmlHelper, e recebe como parâmetros o nome que deve aparecer no link, o contêiner onde o novo campo será incluído, o nome da coleção e o tipo da coleção.

Na 1ª linha é criada uma instancia da coleção utilizando o tipo da mesma.


Na 2ª linha cria-se a view que será adicionada. Essa linha faz uma chamada para o método JsEnconde, que serve para fazer ajustes no html gerado, o código desse método é um pouco extenso e como o código será disponibilizando não vou mostrar ele aqui.


Na 3ª linha é feito um replace para adicionar o nome correto da propriedade ao campo.  

Na 4ª linha é criado a chamada da função Javascript que será a responsável por de fato adicionar o novo campo.

Conforme vimos acima o campo será adicionado via Javascript, para isso crie um script e adicione a seguinte função:


Voltando ao helper, adicione as linhas a seguir:

Nas linhas acima é feita a criação do elemento link, recebendo como parâmetros o nome do link e a chamada para a função Javascript. 

Na view faça referência ao helper e ao model.


Logo após faça a chamada do helper. Observe que o parâmetro referente ao contêiner nada mais é que o id de onde será adicionado os novos campos.

Na 2ª parte vou demostrar o procedimento para remover e as validações dos novos campos.

O projeto completo está aqui: https://github.com/rafaelguinho/AddRemove

Venho aqui trazer um assunto relativamente avançado, que a questão do Bind de coleções no ASP.NET MVC. Há duas forma de se recuperar coleções aninhadas da view no controller, a primeira é utilizado um índice sequencial:

Campos na view:



Recuperação no controller:

A segunda forma permite utilizar um índice não-sequencial alfanumérico:


Neste segundo exemplo é necessário incluir um campo do tipo "hidden", para cada campo de entrada de valor, com o value sendo o índice. Apesar dessa segunda opção ser mais versátil é limitada pois o índice ainda precisar ser único.  

Depois de estudar e pesquisar muito vi que era possível criar um bind customizado, então porque não criar um para eliminar os índices e recuperar as coleções?
No bind é possível ter acesso ao form que foi submetido, isso possibilitou ter acesso a todas as propriedades do formulário e seus valores:


Não vou me aprofundar no código do bind, o mesmo está disponível para estudo e melhorias no projeto: https://github.com/rafaelguinho/collectionbinder. Para utilizar copie a classe da pasta Binders para seu projeto e no Global.asax.cs adicione uma linha para cada coleção:

Na sua view as coleções agora podem ter todas o mesmo nome, que deve ser "NomeDaColeção.Atributo" conforme exemplo:

No próximo post eu vou mostrar como "automatizar" o processo de adicionar e remover utilizando um Helper. Até mais!

Porque é importante?

Como todos sabem, Programação Assíncrona é muito importante porque tem como objetivo principalmente aperfeiçoar a capacidade de resposta de nossas aplicações. O .NET sempre tem tentando apoiar esta forma desde sua primeira versão e sempre houveram novos recursos em cada release e apresentações de novas maneiras de assincronismo. Todas estas funcionalidades estão fora do escopo deste artigo, mas aqui estão vários recursos falando com detalhes sobre eles e descrevendo o seu uso com detalhes.
No entanto, nós desenvolvedores costumamos escrever métodos, eu digo métodos síncronos e tentamos chama-los assincronamente, de várias maneiras (Thread, ThreadStart, ThreadPool, BackgroundWorker, etc), mas a escrita de métodos assíncronos naturalmente foi difícil de fazer e manter.
O recurso pode ser resumido pelo seguinte exemplo: nós mudaremos o método para assíncrono naturalmente apenas alterando o seu tipo de retorno.

public static IEnumerable<int> getPrimes(int min, int count)
{
    return Enumerable.Range(min, count).Where
      (n => Enumerable.Range(2, (int)Math.Sqrt(n) - 1).All(i =>
        n % i > 0));
}

Dependendo dos parâmetros min e count esse método pode durar um bom tempo. Uma maneira de torna-lo assíncrono é simplesmente trocando o tipo de retorno como no exemplo a seguir:
 
public static Task<IEnumerable<int>> getPrimesAsync(int min, int count)
{
     return Task.Run (()=> Enumerable.Range(min, count).Where
      (n => Enumerable.Range(2, (int)Math.Sqrt(n) - 1).All(i =>
        n % i > 0)));
}

No exemplo acima, notem que nós mudamos o nome do próprio método adicionando Async como prefixo e essa é a regra que devemos seguir. Como vocês podem ver o retorno é uma Task, anteriormente era void e foi mudado para Task<T> onde T é o tipo de retorno do método.

O que é Task ?

Task é simplesmente uma implementação de  IAsyncResult .
Agora quando um método retorna Task<T> ele fica no estado awaitable isso significa que você pode chama-lo usando a keyword await, e sempre que você usar await o controle da execução voltará imediatamente e não haverá impacto na capacidade de resposta da sua aplicação.

Vamos ver como nós chamamos esses métodos acima:

private static void PrintPrimaryNumbers()
{
    for (int i = 0; i < 10; i++)
        getPrimes(i * 100000 + 1, i * 1000000)
            .ToList().
            ForEach(x => Trace.WriteLine(x));
}

PrintPrimaryNumbers() é um método que podemos chamar diretamente e tradicionalmente, neste exemplo estou chamando o método 10 vezes, ele será chamado consequentemente e nós veremos quanto tempo demora até ele ser finalizado.

private static async void PrintPrimaryNumbersAsync()
{ 
    for (int i = 0; i < 10; i++)
    {
        var result = await getPrimesAsync(i * 100000 + 1, i * 1000000);
        result.ToList().ForEach(x => Trace.WriteLine(x));
    }
}

Enquanto PrintPrimaryNumbersAsync() é decorado pela keyword async ele chama getPrimesAsync()” de forma assíncrona. Uma vez que é chamado, a execução imediatamente retorna para a thread principal e uma vez que qualquer uma das outras threads é finalizada, a thread principal terá o controle de volta (no nosso caso, escrever os números principais que podem ser encontrados no intervalo fornecido).


Agora veremos o código Main:
static void Main(string[] args)
{
 
    DateTime t1 = DateTime.Now;
    PrintPrimaryNumbers();
    var ts1 = DateTime.Now.Subtract(t1);
    Trace.WriteLine("Finished Sync and started Async");
    var t2 = DateTime.Now;
    PrintPrimaryNumbersAsync();
    var ts2 = DateTime.Now.Subtract(t2);
 
    Trace.WriteLine(string.Format(
      "It took {0} for the sync call and {1} for the Async one", ts1, ts2));
 
    Trace.WriteLine("Any Key to terminate!!");
  
}
 
Você pode me dizer a diferença entre ts1 e ts2 ?
Aqui está o resultado :
Finished Sync and started Async
 
Demorou 00:32:16.1627422 para a chamada síncrona e 00:00:00.0050003 para a chamada assíncrona.



Muitos já devem ter se deparado com situações onde se faz necessário que apenas não mais que uma coluna da tabela seja trazida, o Hibernate oferece uma solução pra isso usando HQL. Para isso vamos usar a Classe Consulta como exemplo, ela tem um relacionamento com a Classe médico e desejamos trazer todos os horário com consultas ativas de um determinado médico em um determinado dia.


Crie a seguinte query HQL:


StringBuffer hql = new StringBuffer();

hql.append("SELECT hora FROM Consulta ");

hql.append("WHERE crm_medico=:crm ");

hql.append("AND status=:status ");

hql.append("AND data=:data ");


Nessa query fazemos a seleção apenas da coluna hora, que é o dado buscado, e mais abaixo declaramos os parâmetros.


Crie a query e a transação:


Transaction tx = session.beginTransaction();

Query query = session.createQuery(hql.toString());


Passe os parâmetros:


SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");

query.setString("crm", crm);

query.setBoolean("status", true);

query.setString("data", sdf.format(data));


Note que usamos um SimpleDateFormat na data e passamos a mesma como string na nossa query.


Por fim faça o commit e passe a lista retornada para uma lista do tipo de dado buscado no nosso caso uma lista de Date.


tx.commit();

horarios=(List<Date>) query.list();

Category

Category

  • (1)
  • (1)
  • (1)
  • (1)
  • (1)
  • (1)

Category

Category