Arquivo

Archive for the ‘ASP.NET MVC’ Category

jQuery DataTables obtendo dados no Api Controller com ASP NET MVC

Conhecimentos necessários:

* Ter conhecimento prévio de como funciona o data tables.

* Referenciar scripts e css necessários.

Página oficial jQuery Data Tables

grid jquery data tables

Grid do jQuery DataTables

Etapas:

  • Criar método para retornar os dados para o jquery data tables no seu controller. A assinatura do método é a seguinte.
  • Código no lado do servidor:
public class DataController : ApiController
{
public dynamic GetJdt(int sEcho,
int iDisplayStart,
int iDisplayLength,
string sSearch,
int iSortCol_0,
string sSortDir_0)
{
// Utilizando LINQ para fazer a consulta em uma Session do NHibernate</pre>
var consulta = sessao.Query<Objeto>().AsQueryable();

 // Seta os termos da busca
 if (!String.IsNullOrEmpty(sSearch))
 {
 consulta =
 consulta.Where(
 wh =>
 wh.Coluna1.ToLower().Contains(sSearch.ToLower()));

 }

// Total de registros para cálculo de paginação
 var quantidadeRegistrosSemFiltro = consulta.Count();

// Ordenação
 string colunaOrdenacao = "Id";
 switch (iSortCol_0)
 {
 case 0:
 colunaOrdenacao = "Id";
 break;
 case 1:
 colunaOrdenacao = "Coluna1";
 break;
 case 2:
 colunaOrdenacao = "Coluna2";
 break;
 case 3:
 colunaOrdenacao = "Coluna3";
 break;
 case 4:
 colunaOrdenacao = "Coluna4";
 break;
 case 5:
 colunaOrdenacao = "Coluna5";
 break;
 }

consulta = consulta.OrderByField(colunaOrdenacao, sSortDir_0 == "asc");
// Aqui eu usei um método de extensão para converter strings em uma expression linq:

//<a href="http://ronniediaz.com/2011/05/24/orderby-string-in-linq-c-net-dynamic-sorting-of-anonymous-types/">http://ronniediaz.com/2011/05/24/orderby-string-in-linq-c-net-dynamic-sorting-of-anonymous-types/</a>

// Adiciona paginação e já faz uma projeção dos dados através do select
 var resultadoConsulta = consulta.Skip(iDisplayStart).Take(iDisplayLength).Select(
 sel =>
 new
 {
 Id = sel.Id,
 Coluna1 = sel.Coluna1,
 Coluna2 = sel.Coluna2,
 Coluna3 = sel.Coluna3,
 Coluna4 = sel.Coluna4,
 Coluna5 = sel.Coluna5
 }
 ).ToArray();

var quantidadeTotalRegistrosAposPaginacao = resultadoConsulta.Count();

// pega o retorno e coloca em uma variável
var retorno = new
 {
 sEcho = sEcho,
 iTotalRecords = quantidadeRegistrosSemFiltro,
 iTotalDisplayRecords = quantidadeTotalRegistrosAposPaginacao,
 aaData = resultadoConsulta
 };

// retorna o objeto que é automaticamente convertido para JSON pelo API controller
return retorno;
}

}
  • Código no lado do cliente:
<script type="text/javascript">// <![CDATA[
 $(document).ready(function(){
 $('.dataTable').dataTable({
 "bJQueryUI": true,
 "bProcessing": true,
 "bServerSide": true,
 "sAjaxSource": "/api/produtos/getjdt",
 "aoColumns": [
 { "mDataProp": "Coluna1" },
 { "mDataProp": "Coluna2" },
 { "mDataProp": "Coluna3" },
 { "mDataProp": "Coluna4" },
 { "mDataProp": "Coluna5"}
 ]
 });
 });

// ]]></script>

Dessa forma o jQuery Data Table vai carregar os dados dinamicamente, com AJAX.

Importante:

  • Número de colunas da tabela deve ser o mesmo retornado nos dados e na criação da data table especificar as colunas através da propriedade aoColumns como mostrado acima., para evitar um erro semelhante a esse:

DataTables warning (table id = ‘myTable’): Requested unknown parameter ‘2’ from the data source for row 0

Referências:
JQuery Datatables warning: Requested unknow parameter…

Using MVC 4 Web Api with jQuery DataTables

Evitando Bind Injection com ASP.NET MVC

O título do post é sensacionalista, mas o conteúdo é sério.
O recurso de model binding nativo do ASP.NET MVC, oferece um sério risco, dependendo da forma que o desenvolvedor utilize o binding automático.

Imaginemos o seguinte senário:

Uma action que grava alterações no nome e e-mail de um usuário do sistema.
Há diversas formas de capturar no servidor os dados enviados pelo cliente.

Exemplo 1: Declarando na assinatura do método os parâmetros correspondentes aos campos postados no form:

public ActionResult Gravar(string Nome, string Email)
{
   // código de persistência
}

Exemplo 2: Obtendo os dados pelo objeto Request que contém os dados postados:

public ActionResult Gravar()
{
   string nome = Request["Nome"];
   string email = Request["Email"];
}

Exemplo 3: Setando o tipo do parâmetro para a classe que contém esses membros.

[HttpPost]
public ActionResult Gravar(User usuarioPostado)
{
   // código de persistência
}

Classe de domínio:

public class User
{
  public int Id { get; set; }
  public string Nome { get; set; }
  public string Email { get; set; }
  public bool IsAdmin { get; set; }
}

imagine que você criou uma view fortemente tipada, usando o gerador automático do Visual Studio, e sua view contém um campo que permite alterar a propriedade IsAdmin.

</pre>
<div class="editor-label">@Html.LabelFor(model => model.IsAdmin)</div>
<div class="editor-field">@Html.EditorFor(model => model.IsAdmin)
 @Html.ValidationMessageFor(model => model.IsAdmin)</div>
<pre>

Certamente você vai remover esse campo, ou marcá-lo como read only e deixá-lo lá na view.

Vulnerabilidade:
Alguém mal-intencionado pode postar essa informação livremente via GET, ou com um pouquinho mais de trabalho via POST, basta saber que existe esse campo no BD, e que o campo tem o nome de “isAdmin”, setar IS ADMIN = TRUE, e OBTER PERMISSÃO DE ADMINISTRADOR no seu sistema quando os dados forem persistidos.

Possíveis defesas:

Defesa 1: Utilizar o atributo Bind na classe de domínio.

[Bind(Exclude = "IsAdmin")] // É possível usar a propriedade Include, que informa quais membros são permitidos, ao invés de quais serão excluídos.
public class User
{
  public int Id { get; set; }
  public string Nome { get; set; }
  public string Email { get; set; }
  public bool IsAdmin { get; set; }
}

Defesa 2: Utilizar o atributo Bind no método de gravação.

[HttpPost]
public ActionResult Gravar([Bind(Exclude = "IsAdmin")] User usuarioPostado)
{
   // código de persistência
}

Defesa 3: Utilizar uma ViewModel para trocar dados entre a view e o seu controller:

public class UserInputViewModel
{
  public int Id { get; set; }
  public string Nome { get; set; }
  public string Email { get; set; }
}

[HttpPost]
public ActionResult Gravar(UserInputViewModel usuarioPostado)
{
   // converte a classe UserInputViewModel => em User
   // Uma dica é usar a biblioteca AutoMapper: https://github.com/AutoMapper/AutoMapper
   // efetua a persistência.
}

Existem mais defesas possíveis, e uma dica interessante que aprendi é:
“Trate qualquer HTTP request como malicioso até que se prove o contrário.”.

Fontes:
IronShay | Mass Assignment Vulnerability in ASP.NET MVC

6 Ways To Avoid Mass Assignment in ASP.NET MVC

Imagens no Oracle com NHibernate, Asp.net Mvc e C#

Cenário:
Um site de um concurso cultural, ao cadastrar uma promoção o usuário envia uma imagem que vai ser exibida com a promoção. Essa imagem é gravada no oracle com nhibernate, e é retornada sempre que a promoção é exibida ao usuário.

Exemplo resumido da classe Promoção:

public class Promocao
{
public virtual string Nome { get; set; }

public virtual string Desafio { get; set; }

public virtual string Regulamento { get; set; }

public virtual byte[] ImagemTopo { get; set; }
// Criamos a propriedade como um array de bytes -> byte[] que será persistido como binário.
}

Resumo da classe mapeada com Fluent NHibernate:

    public class PromocaoMap : ClassMap<Promocao>
    {
        public PromocaoMap()
        {
            .... omitido...            
            // Mapeei um campo para o regulamento da promoção e um campo para a imagem do topo
            Map(x => x.Regulamento).Length(1048576); // length de 1048576 bytes aproximadamente 1 mb -> será criado como NCLOB no oracle.
            Map(x => x.ImagemTopo).Length(5224880); // length 5224880 bytes aproximadamente 5 mb -> será criado como BLOB no oracle.
        }
    }

Gravando a imagem no banco

Código da Action que Recebe o Post do Form de Cadastro:

[HttpPost]
public ActionResult SavePromocao(Promocao promocaoGravar, HttpPostedFileBase ImagemTopoEnviar)
        {
            if (!ModelState.IsValid)
                return View("CadPromocao", promocaoGravar);

            using (var sessao = MvcApplication.ObterSessaoNh())
            {
                using (var transacao = sessao.BeginTransaction())
                {
                    try
                    {
                        var crud = new Dal.PromocaoDao(sessao);
                        if (promocaoGravar.Id <= 0)
                        {
                            crud.Incluir(promocaoGravar);
                        }
                        else
                        {
                            var objetoPersistido = crud.RetornaEntidade(promocaoGravar.Id);
                            objetoPersistido.Nome = promocaoGravar.Nome;

                            if (ImagemTopoEnviar != null)
                            {
                                // Converte stream do arquivo enviado para array de bytes[]
                                var memoryStream = new MemoryStream();
                                ImagemTopoEnviar.InputStream.CopyTo(memoryStream);

                                objetoPersistido.ImagemTopo = memoryStream.ToArray();
                            }

                            crud.Alterar(objetoPersistido);
                        }

                        transacao.Commit();
                    }
                    catch (Exception)
                    {
                        transacao.Rollback();
                    }
                }
            }

            return RedirectToAction("ListPromocoes");
        }

Dessa forma a imagem é persistida corretamente no Oracle.

Exibindo a imagem na view

Criar uma Action que busca a imagem no banco de dados e retorna via response

[HttpGet]
public ActionResult GetImagemPromocao(long idPromocao)
{
   byte[] imagemArray = null;

   using (var sessao = MvcApplication.ObterSessaoNh())
   {
	var crud = new Dal.PromocaoDao(sessao);
	imagemArray = crud.ObterImagem(idPromocao);
	if (imagemArray == null)
        {
		return null;
	}
	else
	{
		return new FileContentResult(imagemArray, "image/jpeg");
	} 
   }
} 

Código da View

// Minha View é TIPADA
<img src="@Url.Content("~/Admin/GetImagemPromocao?idPromocao = " + Model.Id)"/>

// O Helper Url.Content converte um Path Relativo para um Path Absoluto.

E assim a imagem é renderizada com sucesso na view.


Observações:

  1. Deve funcionar corretamente em outros SGBDS como MySql, PostgreSql e etc.
  2. Vale lembrar que o objeto byte[] armazena não somente imagems, mais qualquer outro tipo de arquivo, pois tudo é binário ok.
  3. Não inclui o tratamento de erros no exemplo.

Dúvidas deixe nos comentários que respondo.

Espero ter ajudado em seu projeto.


Referências:
Documentação do NHibernate – Tipos de Dados
Dica para converter Stream
no StackOverflow

Documentação Oficial de HTML Forms no W3C – World Wide Web Consortium.

jQuery Mobile com Asp.Net Mvc 4

Recentemente foi necessário desenvolver um módulo de um aplicativo .net Windows Forms, que fosse acessível via dispositivo touch / mobile. Para reutilizar todas as regras de negócio, classes de domínio e camada de conexão a dados utilizei ASP.NET MVC 4 com jQuery Mobile.

Vale a pena ler a documentação com atenção, para evitar problemas. http://jquerymobile.com/demos/1.1.1/

De cara posso destacar os seguintes pontos:

  • jQuery mobile utiliza fortemente o jQuery.
  • Utiliza navegação via ajax, que permite transição de páginas com efeitos de transição.
  • Forms com input de arquivo, não são suportados pelo Ajax, e por isso deve-se decorar o form de file send com o atributo: data-ajax="false", pois por padrão, o jQuery Mobile posta os forms via ajax.
  • No set de elementos visuais do jQuery Mobile faz falta um Date Picker para seleção de datas.

Como as páginas são injetadas via Ajax para facilitar a transição, debugar javascript fica complicado, então em modo de debug, eu desativo completamente o Ajax do jQuery mobile, usando o evento “mobileinit”, e setando ajaxEnabled = false.

Quando do release, eu ativo novamente o ajax.


        <script type="text/javascript">
            $(document).bind("mobileinit", function () {
                $.mobile.ajaxEnabled = false;
                $.mobile.defaultPageTransition = "slideup";
            });
        </script>

Para carregar dados na página assincronamente, pode-se utilizar API Controllers, e requisitar os dados com a função getJSON.

Exemplo do preenchimento de um ComboBox (vulgo Select) utilizando ajax e um api controller que retorna os UFs do país:


    <script type="text/javascript">
        $(document).ready(function () {
            // Envia requisição AJAX
            $.getJSON("/api/uf/", function (estados) {
                // Se for bem-sucedido, 'estados' contém os dados retornados
                $.each(estados, function (index, estado) {
                    $("<option value=" + estado.IdUf+ ">" + estado.Descricao + "</option>").appendTo($("#comboboxUf"));
                });
            });

/* ------- combobox que receberá os dados --------- */

<select name="selectUf" id="comboboxUf"></select>

Código da Controller:


    public class UfController : ApiController
    {
        // GET api/Uf
        public IEnumerable<Dominio.Uf> GetTodosEstados()
        {
            var sessaoNh = MvcApplication.ObterSessaoNh();
            var crud = new DAL.UfDao(sessaoNh);

            return crud.Listar().ToArray();
        }

No mais é só ler a documentação e utilizar os elementos visuais a vontade.
http://jquerymobile.com/demos/1.1.1/docs/forms/docs-forms.html

Acelerando desenvolvimento ASP.NET MVC com Twitter Bootstrap

Imagine o seguinte cenário:

Você precisa desenvolver um projeto web, mas não tem afinidade com CSS.

As possibilidades que imagino são:

1. Investir num designer profissional para o projeto.

2. Se aventurar no design.

3. Utilizar um template pronto.

4. Criar um novo design com o amigável Twitter Bootstrap.

Já estou utilizando em novos projetos. E é ótimo.

Há muitos pontos fortes como:

  • Sistema de grid. Muito fácil posicionar os elementos na página com ele.
  • Design responsivo: Suporte a tamanhos de tela diversos. (Mobile, Tablets etc.)
  • Tipografia
  • Blocos de Código: Facilita a inserção de blocos de código.
  • Tabelas: Estilização fácil de tabelas.
  • Formulários: Facilita a inserção de formulário com caixas de busca, checkboxes, selects etc. com estilos de validação dentre outros.
  • Botões: diversos estilos de botões.
  • Mini Ícones: mini ícones para utilizar livremente.
  • Componentes: Dentre diversos componentes para dropdowns, labels, badges, tipografia, thumbnails, alerts, progress bars, dentre outros.
  • Pugins Javascript: Bootstrap também acompanha atualmente 12 plug-ins jquery. * Requer a última versão do jQuery linkada na página.

Exemplo de tela construída com o Twitter Bootstrap:

 

Veja mais motivos pra utilizar o Twitter Bootstrap no Site Oficial

Conheça mais sites construídos com o bootstrap no tumblr Built with Bootstrap

 

Outros links:

Artigo em português sobre o Twitter Bootstrap: http://abruno.com/blog/twitter-bootstrap/

Hospedagem Grátis para sites ASP.NET

03 - 12 3 comentários

Se chama AppHarbor. https://appharbor.com/

Oferece um plano de hospedagem grátis e também planos pagos de acordo com a necessidade do cliente.

Permite deploy direto de repositórios GIT etc.

3 pontos chave:
What is AppHarbor? AppHarbor is a fully hosted .NET Platform as a Service. AppHarbor can deploy and scale any standard .NET application.

Who is AppHarbor for?
AppHarbor is used by thousands of developers and businesses to host anything from personal blogs to high traffic web applications.

Why use AppHarbor?
AppHarbor lets you instantly deploy and scale .NET applications using your favourite versioning tool. Installing add-ons is just as easy.

 Preços

O plano CANOE é grátis.

 

Renderizando uma Partial View com Ajax e jQuery MVC 3

11 - 11 3 comentários

Renderizar Partial Views com Ajax é útil pra acelerar e otimizar o carregamento da sua página.

No exemplo temos:

1 controller Home

1 view Mensagem

 

  • Código do Controller:
public class HomeController : Controller {
public ActionResult Mensagem() {
ViewBag.MensagemRenderizar = "Esta mensagem é renderizada na view parcial";
return PartialView();
}

 

  • Código da View:

<h2>@ViewBag.MensagemRenderizar</h2>

  • Código no _Layout.cshtml

<div id = “result”> </div>

<script type="text/javascript">
$(function () {
$('#result').load('/Home/Mensagem');
});
</script>

Utilizando o método Load do jQuery,  é feita uma requisição ajax e retornado o conteúdo da view especificada.

Mais informações: http://api.jquery.com/load/

Diferenças ViewBag e ViewData ASP.NET MVC 3

Não há uma grande diferença entre a utilização de ViewBag ou ViewData para troca de informações entre Controllers e Views mas deve ser observado alguns pontos:

1. Se atribuir valor a uma chave com espaços via ViewData não será possível acessá-lo via ViewBag.


@ViewData[&quot; Nome Do Cliente&quot;] = Gabriel

@ViewBag.Nome do Cliente //GERARÁ ERRO EM TEMPO DE COMPILAÇÃO

2. Não é possível passar um dynamic diretamente via parâmetros comuns, a menos que se faça um cast ou que se utilize ViewData:


@Html.TextBox(&quot;Nome&quot;, ViewBag.Nome) //ERRO

@Html.TextBox(&quot;Nome:&quot;, ViewData[&quot;Nome&quot;]); //ACESSANDO POR VIEWDATA

@Html.TextBox(&quot;Nome:&quot;, (string)ViewBag.Nome); // EFETUANDO TYPECAST

Evitando Java Script Injection ou HTML injection ASP.NET MVC 3

11 - 11 2 comentários

Evitando cross-site script injection XSS utilizando Html Encoding:

Segue um exemplo:

Controller: Cliente

public string Buscar(string Nome)
{
string nomeBuscado = HttpUtility.HtmlEncode("Nome buscado: " + Nome);
return nomeBuscado;
}

Utilizando o método HttpUtility.HtmlEncode, evita que código do tipo: /Cliente/Buscar?Nome=<script>alert(‘Hacker’)</script> seja passado via parâmetro.

Observação: Por padrão, expressões na view engine Razor são automaticamente HTML encoded.

Ex:
@{
var mensagem = “<script>alert(‘hackeado’)</script>”;
}
<span>@mensagem</span>

resultado:
<span>&lt;script&gt;alert(‘hackeado’);&lt;script&gt;</span>

O Script não será executado.

para permitir a incorporação de texto com código/marcação na view, utilize o método:
<span>@Html.Raw(mensagem)</span>
Nesse caso o alert javascript será exibido.

Ao escrever dentro de código javascript, utilize uma segunda proteção contra XSS, um Encode específico para Javascript:

<script type=”text/javascript”>
$(function () {
var boasvindas = ‘Ola @Ajax.JavaScriptStringEncode(ViewBag.LoginUsuario)’;
$(“#mensagem”).html(boasvindas).show(‘slow’);
});
</script>
guiaecologico.wordpress.com/

Despertando a consciência que preserva!

Viagem e Voo

Dicas para viagens, férias e voos nacionais e internacionais

Ivan Guimarães Meirelles

Analista Desenvolvedor

Void Podcast

Vazio e sem retorno de valor

Elemar DEV

Negócios, tecnologia e desenvolvimento

2,000 Things You Should Know About WPF

Everything a WPF Developer Needs to Know, in Bite-Sized Chunks

Gabriel RB.net

Blog técnico, com dicas, códigos, novidades e problemas do dia-a-dia programando.

Alexandre Valente's Blog

Experiências em tecnologia e assuntos diversos

%d blogueiros gostam disto: