O NeoMatrix Tech está de casa nova!

Você deverá ser redirecionado em 6 segundos. Se não, visite:
http://www.leonelfraga.com/neomatrixtech
e atualize seus favoritos.

Aviso IMPORTANTÍSSIMO!

Aviso aos navegantes:

O NeoMatrix Tech mudou de casa!!!

A partir de agora, acessem pelo novo endereço:

http://www.leonelfraga.com/neomatrixtech

Ué... mas é só o domínio mudou de lugar?

R: Na verdade, não é bem assim hehe. Este domínio que você acessa agora aponta para um blog hospedado no Blogger, enquanto no novo, aponta para um blog na plataforma Wordpress, hospedagem própria, muito mais rápida e com um layout mais agradável de ler ;)

Não vou fechar este domínio igual ao que eu fiz com o NM Light (que já está 100% na nova plataforma). Talvez beeeeeeem depois eu faça isso.

Todos os posts daqui se encontram lá, e novos posts serão colocados somente no novo endereço.
A única coisa que não consegui importar foram os comentários. Mas em breve vai ter um post contando sobre a epopéia que foi migrar o NeoMatrix Tech!

Somente vou fechar a área de comentários daqui. Caso queiram comentar, favor ver o post correspondente no "Novo NeoMatrix Tech" e comentem por lá. É bem melhor! (pena que os permalinks "amigáveis para SEO" não funcionam lá, dá erro 404 e não consigo fazer a configuração funcionar. E olha que eu já vi vários artigos falando desse assunto :( ).

Quem assina o feed, já está lendo o conteúdo do novo NeoMatrix Tech!

segunda-feira, 29 de setembro de 2008

Resolvendo a mensagem "Dados Inválidos" ao instalar driver a partir de arquivo .inf

Olá! Então, agora eu troquei de PC, agora sim com uma máquina muito boa :p Depois eu comento sobre ela.

Mas agora a pouco (mesmo, no dia 29/09/2008 às 21:00) estava atualizando o driver do monitor. Possuo um monitor LCD da LG modelo L196WTQ (é o que a etiqueta na parte traseira diz), e como não achei o CD com drivers, acabei baixando da net.
Instalei o driver de um outro modelo, tudo funcionou normal, mas o aplicativo ForteManager da LG não funcionava, estava tudo desabilitado.
Resolvi desinstalar o driver atual, peguei o driver correto do zip que eu baixei e eis que surge a mensagem que não foi possível instalar o hardware e a mensagem "Os dados estão inválidos".

Eis que procurando na net pela mensagem em questão, relacionada aos arquivos .inf e que encontro a seguinte solução neste site: http://btwincap.sourceforge.net/faq.html

"A: The "invalid data" error, or the refusal of the system to install a new driver is caused by a bug of Win2000/WinXP... The only way to fix it is to use the registry editor... Open regedt32, go to HKEY_LOCAL_MACHINE\System\CurrentControlSet, right click "CurrentControlSet" on the left pane and a contextual menu will open. Select "Permissions", select the "Administrators" group, make sure Full Control and Read is ALLOWED, Go to "Advanced", And check "Replace permissions entries...", Hit OK., OK. Perhaps an error will show... Just ignore it. Now reinstall the btwincap driver."

Não tem nada a ver com o monitor em questão, mas traduzindo os principais passos, por causa da mensagem ao instalar driver a partir de um arquivo .inf, essa solução funcionou para mim:

- Abra o Editor de Registro (regedit);
- Localize a chave HKLM\System\CurrentControlSet e clique com o botão direito sobre ela.
- Selecione Permissões e certifique-se de que o grupo Administradores estão com Controle Total e Leitura.
- Clique em Avançado e marque o checkbox "Substituir as entradas de permissão...";
- Clique OK. Se aparecer uma mensagem de erro, ignore-a dando OK.
- Agora tente reinstalar o driver.

Pelo menos nessa eu fui feliz :-)

Leia o restante deste post...

sábado, 13 de setembro de 2008

Controle de Usuários para Sistemas ASP.NET - Parte 5 - Implementação nos Sistemas

Olá pessoal! Aqui estamos nós com a última parte do tutorial de como implementar um controle de acesso em um site ASP.NET. Na primeira parte, modelamos a base de dados, nas segunda e terceira partes implementamos as classes que irão manipular o controle de usuários e na quarta parte construímos sua interface web.

Nesta quinta e última parte iremos implementar nossa solução em uma página. Lembra do tutorial sobre fazer as linhas de um gridview mudarem de cor ao repousar do mouse? Vamos controlar o acesso dele por este sistema!

Mas primeiro vamos ver como é feito o login: para isso abra o arquivo Login.aspx do nosso site exemplo, que pode ser obtido através da nossa página de suporte do link para download no final da postagem. Nele temos apenas dois textboxes, onde informaremos o nosso login e senha e um botão para efetuar o login.

Importante: No Banco de dados alguns dados já devem ser pré-cadastrados, tais como todas as páginas web que compõem o sistema, exceto as páginas de login e o aviso de não permitido; um perfil com acesso a todas as páginas do sistema E suas respectivas ligações na tabela PERFIL_MODULOS e um usuário com este perfil.

Agora já dá para começar a brincadeira :-)

Vamos examinar o código do evento OnClick do botão btnLogin:

   1: protected void btnLogin_Click(object sender, EventArgs e)
   2: { 
   3:     string msg = "";
   4:     TUsuario u = TUsuario.Autenticar(tbLogin.Text, tbSenha.Text, out msg);
   5:     if (u != null)
   6:     {
   7:         Session.Add("USUARIO", u);
   8:         Response.Redirect("Default.aspx");
   9:     }
  10:     else
  11:     {
  12:         ScriptManager.RegisterStartupScript(this, this.GetType(), "alerta", Consts.JavaScript.Alert(Consts.Funcoes.Replacer4js(msg), false), true);
  13:     }
  14: }

Verificamos que esse código é bem simples: Chamamos o método estático Autenticar da classe TUsuario. Passamos neste método um login, uma senha e uma variável que irá capturar a mensagem de retorno, se o login foi bem sucedido ou não.

Se a autenticação for bem sucedida, o método retorna uma instância de TUsuario, que contém todos os dados do mesmo e do perfil, inclusive cada página que ele possui acesso, caso contrário, retornará null.

Em seguida verificamos esse retorno. Se for diferente de null, a instância de TUsuario retornada será armazenada em uma variável de sessão chamada USUARIO e em seguida é feito o redirecionamento para a página padrão do sistema. Se for null, é disparada uma mensagem através de um alert em javascript (a função Consts.JavaScript.Alert é um "wrapper" para o comando alert; ele monta uma string com esse comando e a mensagem, e a função Consts.Funcoes.Replacer4js faz o escape de caracteres especiais do JS, por exemplo, para que o renderizador entenda que "\n" não é para quebrar a linha, e sim escrever a string "\n" na página).

Vamos fazer a verificação em cada página agora :-D ?

Para fazer esta verificação, precisamos pegar somente o nome da página que está sendo carregada e ver se este nome existe dentro da propriedade Perfil.Modulos de nossa variável de sessão USUARIO. Isto é feito através do método TemAcesso, que varre a coleção Perfil.Modulos:

   1: //Verifica se o usuário terá acesso a esta página
   2: if (Session["USUARIO"] == null)
   3: {
   4:     Response.Redirect("naopermitido.aspx");
   5: }
   6: else
   7: {
   8:     TUsuario u = (TUsuario)Session["USUARIO"];
   9:     lbInfo.Text = "<b>Usuário:&nbsp;</b>" + u.Nome + "&nbsp;&nbsp;<b>Perfil</b>&nbsp;" + u.Perfil.Descricao;
  10:     if(!u.Perfil.TemAcesso(Consts.Funcoes.FormName(Request.Url.AbsolutePath)))
  11:     {
  12:         Response.Redirect("naopermitido.aspx");
  13:     }
  14: }

Este bloco de código se encontra nas primeiras linhas do método Page_Load(), de modo que ele primeiro verifique o perfil e somente depois carregue as outras informações.
Se a nossa variável de sessão USUARIO for nula, significa que quem tentou acessar a página (caso tenha tentado fazer o acesso sem passar pela página de login) não está logado, e imediatamente redirecionamos para a página que indica "Acesso não permitido".

Caso o usuário esteja devidamente logado em nosso sistema, passamos somente o nome do formulário .aspx para o método Perfil.TemAcesso de nossa variável de sessão. A propriedade Request.Url.AbsolutePath retorna a URL completa. Passaremos ele para a função Consts.Funcoes.FormName, que nos retornará apenas o nome a página.

Se o método de verificação de acesso returnar true, o carregamento da página tem continuidade, caso contrário, o usuário é redirecionado para a página "naopermitido.aspx".

Beleza, muito simples. Mas se o sistema for grande, preciso colar este código em TODAS as páginas?

Aí vai depender de como o seu site foi construído. Se ele utilizar o .NET Framework 2.0 (duh, as classes são estritamente para o FW 2.0, visto que ele faz uso de Generic List... Mas, ele também pode ser implementado com o Framework 1.x também, alterando os Lists para ArrayList)  e utilizar master pages (que faz herança visual E de código no ASP.NET) , este código somente precisa ser colocado na(s) master page(s) do site. Caso contrário, terá que ser um a um.

Porém esse método apresenta uma desvantagem devido ao fluxo de execução e renderização da página: Primeiro, são executados todos os eventos da página "filha", por exemplo, o Page_Load e o método de postback invocado, para só aí executar o código da master page e a renderização da página em si. Com isso, caso tenha alguma carga de dados no evento PageLoad, esta será executada primeiro em relação à verificação de permissão de acesso.

Download:
Exemplo Sistema de Login em ASP.NET (com BD Firebird)  (289 kB)

Enfim, terminou! Um grande abraço a todos e espero que tenham aproveitado! :-)

[Update 26/02/2008: Para facilitar o download, ao invés da página de suporte hospedada no Geocities, estarei movendo os arquivos para hospedagem própria, diretamente no domínio leonelfraga.com e colocando os links diretos para o arquivo.]

Leia o restante deste post...

sábado, 6 de setembro de 2008

Controle de Usuários para Sistemas ASP.NET - Parte 4 - Interface de cadastro de Perfis/Usuários

Olá pessoal! Enfim, já modelamos o banco de dados e as classes que farão parte do nosso controle de usuários para sistemas ASP.NET, o exemplo já se encontra na Página de Suporte, e agora vamos falar sobre as telas de cadastro.

O cadastramento de perfis e usuários será feito de uma maneira que chamo de "single page module", ou seja, TODO o módulo estará em apenas UMA página. Ela é construída utilizando panels para controlar a visualização das grades de pesquisa e por janelas modais que são as telas de cadastro em si.

Esta página, assim como as outras do nosso exemplo, fazem herança visual e de código (veremos como a parte de herança de código será importante na parte 5) de uma master page. Portanto, não estranhem a ausência das tags de header, body e form :-)

Quando o módulo de Cadastro de Perfis/Usuários for acessado, é mostrado em primeiro lugar a grade de pesquisa de Perfis de Usuário. Observem o código desta parte da página, que mostra as grades dos cadastros, acompanhado de seu code-behind:

   1: <div id="dvSelModulo" style="text-align:center;width:100%">
   2:     <span class="textotitulos">Selecione o módulo desejado</span><br />
   3:     <asp:DropDownList runat="server" ID="ddlSelecionaModulo" AutoPostBack="true" OnSelectedIndexChanged="ddlSelecionaModulo_SelectedIndexChanged">
   4:         <asp:ListItem Text="Cadastro de Perfis de Usuário" Value="1"></asp:ListItem>
   5:         <asp:ListItem Text="Cadastro de Usuários" Value="2"></asp:ListItem>
   6:     </asp:DropDownList>
   7: </div>
   8: <div id="dvPesqCadPerfil" runat="server">
   9:     <asp:UpdatePanel runat="server" ID="UpdPesqCadP">
  10:         <ContentTemplate>
  11:             <div class="divtitulo">
  12:                 <span>Cadastro de Perfis de Usuário - Pesquisa</span>
  13:             </div>
  14:             <div>
  15:                 <div style="position:absolute;width:250px;">
  16:                     <span class="textotitulos">Descrição:</span><br />
  17:                     <asp:TextBox runat="server" ID="tbxPesquisaDescPerfil"></asp:TextBox>
  18:                 </div>
  19:                 <div style="width:150px;left:260px;position:relative;top:6px;">
  20:                     <asp:Button runat="server" ID="btnPesquisarPerfil" Text="Pesquisar Perfil" OnClick="btnPesquisarPerfil_Click" />
  21:                 </div>
  22:             </div><br />
  23:             <div style="text-align:center;width:100%;border-top:solid 2px black">
  24:                 <asp:Button runat="server" ID="btnInserirPerfil" Text="Inserir Novo Perfil" OnClick="btnInserirPerfil_Click" />
  25:             </div>
  26:             <div>
  27:                 <asp:GridView runat="server" ID="gvCadPerfil" AutoGenerateColumns="false" OnRowDataBound="gvCadPerfil_RowDataBound" Width="100%">
  28:                 <HeaderStyle CssClass="gridheader" />
  29:                 <RowStyle CssClass="gridnormal" />
  30:                     <Columns>
  31:                         <asp:BoundField HeaderText="Código" DataField="PerfilId" />
  32:                         <asp:BoundField HeaderText="Descrição" DataField="Descricao" />
  33:                         <asp:TemplateField>
  34:                             <ItemTemplate>
  35:                                 <asp:Button runat="server" ID="btnEditarPerfil" Text="Editar" OnClick="btnEditarPerfil_Click" />
  36:                                 <asp:Button runat="server" ID="btnExcluirPerfil" Text="Excluir" OnClientClick="return confirm('Senta o dedo na bagaça?');"
  37:                                     OnClick="btnExcluirPerfil_Click" />
  38:                             </ItemTemplate>
  39:                         </asp:TemplateField>
  40:                     </Columns>
  41:                 </asp:GridView>
  42:             </div>
  43:         </ContentTemplate>
  44:     </asp:UpdatePanel>
  45: </div>
  46: <div id="dvPesqCadUsu" style="display: none;" runat="server">
  47:     <asp:UpdatePanel runat="server" ID="UpdPesqCadUsu">
  48:         <ContentTemplate>
  49:             <div class="divtitulo">
  50:                 <span>Cadastro de Usuários - Pesquisa</span>
  51:             </div>
  52:             <div>
  53:                 <div style="position:absolute;width:150px;">
  54:                     <span class="textotitulos">Nome Completo:</span><br />
  55:                     <asp:TextBox runat="server" ID="tbxPesqNomeUsu" CssClass="textboxes"></asp:TextBox>
  56:                 </div>
  57:                 <div style="width:150px;left:160px;position:absolute;">
  58:                     <span class="textotitulos">Login:</span><br />
  59:                     <asp:TextBox runat="server" ID="tbxPesqLoginUsu" CssClass="textboxes"></asp:TextBox>
  60:                 </div>
  61:                 <div style="width:150px;position:absolute;left:320px;">
  62:                     <span class="textotitulos">Perfil:</span><br />
  63:                     <asp:DropDownList runat="server" ID="ddlPesqPerfilUsu" CssClass="textboxes">
  64:                     </asp:DropDownList>
  65:                 </div>
  66:                 <div style="width:100px;position:absolute;left:480px;">
  67:                     <span class="textotitulos">Status:</span><br />
  68:                     <asp:DropDownList runat="server" ID="ddlPesqStatusUsu" CssClass="textboxes">
  69:                         <asp:ListItem Value="" Text="--TODOS--"></asp:ListItem>
  70:                         <asp:ListItem Value="A" Text="ATIVO"></asp:ListItem>
  71:                         <asp:ListItem Value="I" Text="INATIVO"></asp:ListItem>
  72:                     </asp:DropDownList>
  73:                 </div>
  74:                 <div style="position:relative;left:620px;width:100px;top:8px;">
  75:                     <asp:Button runat="server" ID="btnPesquisarUsu" Text="Pesquisar Usuário" OnClick="btnPesquisarUsu_Click" />
  76:                 </div>
  77:             </div><br />
  78:             <div style="width:100%;text-align:center;border-top:solid 2px black;">
  79:                 <asp:Button runat="server" ID="btnInserirUsuario" Text="Inserir Novo Usuário" OnClick="btnInserirUsuario_Click" />
  80:             </div>
  81:             <div>
  82:                 <asp:GridView runat="server" ID="gvPesqUsuarios" AutoGenerateColumns="false" OnRowDataBound="gvPesqUsuarios_RowDataBound" Width="100%">
  83:                 <HeaderStyle CssClass="gridheader" />
  84:                 <RowStyle CssClass="gridnormal" />
  85:                     <Columns>
  86:                         <asp:BoundField DataField="Login" HeaderText="Login" />
  87:                         <asp:BoundField DataField="Nome" HeaderText="Nome Completo" />
  88:                         <asp:BoundField DataField="Status" HeaderText="Status" />
  89:                         <asp:TemplateField HeaderText="Perfil">
  90:                             <ItemTemplate>
  91:                                 <asp:Label runat="server" ID="lbPerfil"></asp:Label>
  92:                             </ItemTemplate>
  93:                         </asp:TemplateField>
  94:                         <asp:TemplateField>
  95:                             <ItemTemplate>
  96:                                 <asp:Button runat="server" ID="btnEditarUsuario" Text="Editar" OnClick="btnEditarUsuario_Click" />
  97:                                 <asp:Button runat="server" ID="btnExcluirUsuario" Text="Excluir" OnClientClick="return confirm('Senta o dedo na bagaça?');"
  98:                                     OnClick="btnExcluirUsuario_Click" />
  99:                             </ItemTemplate>
 100:                         </asp:TemplateField>
 101:                     </Columns>
 102:                 </asp:GridView>
 103:             </div>
 104:         </ContentTemplate>
 105:     </asp:UpdatePanel>
 106: </div>

Code Behind:

   1: protected void Page_Load(object sender, EventArgs e)
   2: {
   3:     if (!IsPostBack)
   4:     {
   5:         ViewState.Add("CodigoPerfil", "0");
   6:         ViewState.Add("UsuID", "0");
   7:  
   8:         //Populando o combo-box de Pesquisa de Perfil
   9:         ddlPesqPerfilUsu.DataSource = TPerfilUsuario.ListarPerfis("");
  10:         ddlPesqPerfilUsu.DataValueField = "PerfilId";
  11:         ddlPesqPerfilUsu.DataTextField = "Descricao";
  12:         ddlPesqPerfilUsu.DataBind();
  13:         ddlPesqPerfilUsu.Items.Insert(0, new ListItem("--TODOS--", "0"));
  14:  
  15:         //Populando o combo-box de seleção de perfil do cadastro de usuários
  16:         ddlPerfilUsuario.DataSource = TPerfilUsuario.ListarPerfis("");
  17:         ddlPerfilUsuario.DataValueField = "PerfilId";
  18:         ddlPerfilUsuario.DataTextField = "Descricao";
  19:         ddlPerfilUsuario.DataBind();
  20:     }
  21: }
  22:  
  23: protected void ddlSelecionaModulo_SelectedIndexChanged(object sender, EventArgs e)
  24: {
  25:     switch ((sender as DropDownList).SelectedIndex)
  26:     {
  27:         case 0: { dvPesqCadPerfil.Style[HtmlTextWriterStyle.Display] = ""; dvPesqCadUsu.Style[HtmlTextWriterStyle.Display] = "none"; break; }
  28:         case 1: { dvPesqCadPerfil.Style[HtmlTextWriterStyle.Display] = "none"; dvPesqCadUsu.Style[HtmlTextWriterStyle.Display] = ""; break; }
  29:     }
  30: }

Como vocês podem ver, cada gridview está contido dentro de um div, com o atributo runat=server. O div correspondente ao grid de perfil se encontra visível, e o de usuários oculto. Um drop down permite alternar a visibilidade destes divs, conforme o método SelectedIndexChanged do mesmo: De acordo com a opção, seto o atributo Display para vazio ou none. E note também que cada div contém seu próprio UpdatePanel.

Cada cadastro tem seus próprios filtros de pesquisa e controles também, de forma que sejam completamente independentes um do outro.

No evento PageLoad, faço a pré-carga dos combo-boxes do filtro de pesquisa de perfil e do combo de seleção de perfil do cadastro de usuários, além de inicializar dois Viewstates que são utilizados para controlar o ID do registro selecionado dos grids.

Vamos detalhar agora o cadastro de Perfil de Usuário, com a sua janela e o code-behind correspondente:

   1: <div id="dvDetCadPerfil" class="jqmWindow">
   2:     <asp:UpdatePanel runat="server" ID="UpdatePanel1">
   3:         <ContentTemplate>
   4:             <div class="divtitulo">
   5:                 <span>Cadastro de Perfis de Usuário</span>
   6:             </div>
   7:             <fieldset>
   8:                 <span class="textotitulos">Código:</span><br />
   9:                 <asp:TextBox runat="server" ID="tbxCodigoPerfil" ReadOnly="true" CssClass="textboxes"></asp:TextBox><br />
  10:                 <span class="textotitulos">Descrição</span><br />
  11:                 <asp:TextBox runat="server" ID="tbxDescricaoPerfil" CssClass="textboxes"></asp:TextBox><br />
  12:                 <div>
  13:                     <asp:Button runat="server" ID="btnCancelarCadPerfil" Text="Cancelar" OnClick="btnCancelarCadPerfil_Click" />
  14:                     <asp:Button runat="server" ID="btnSalvarPerfil" Text="Salvar" OnClick="btnSalvarPerfil_Click" />
  15:                 </div>
  16:             </fieldset>
  17:             <div class="divtitulos">
  18:                 <span>Módulos que este perfil pode acessar</span>
  19:             </div>
  20:             <asp:GridView runat="server" ID="gvModulosPerfil" AutoGenerateColumns="false" OnRowDataBound="gvModulosPerfil_RowDataBound" Width="100%">
  21:                 <HeaderStyle CssClass="gridheader" />
  22:                 <RowStyle CssClass="gridnormal" />
  23:                 <Columns>
  24:                     <asp:BoundField HeaderText="Código do Módulo" DataField="ModuloId" />
  25:                     <asp:BoundField HeaderText="Descrição do Módulo" DataField="Descricao" />
  26:                     <asp:TemplateField HeaderText="Tem Acesso?">
  27:                         <ItemTemplate>
  28:                             <asp:CheckBox runat="server" ID="chkPermissaoModulo" />
  29:                         </ItemTemplate>
  30:                     </asp:TemplateField>
  31:                 </Columns>
  32:             </asp:GridView>
  33:         </ContentTemplate>
  34:     </asp:UpdatePanel>
  35: </div>

   1: protected void gvCadPerfil_RowDataBound(object sender, GridViewRowEventArgs e)
   2: {
   3:     if (e.Row.RowIndex > -1)
   4:     {
   5:         (e.Row.FindControl("btnEditarPerfil") as Button).CommandArgument = e.Row.RowIndex.ToString();
   6:         (e.Row.FindControl("btnExcluirPerfil") as Button).CommandArgument = e.Row.RowIndex.ToString();
   7:     }
   8: }
   9:  
  10: protected void gvModulosPerfil_RowDataBound(object sender, GridViewRowEventArgs e)
  11: {
  12:     if (e.Row.RowIndex > -1)
  13:     {
  14:         (e.Row.FindControl("chkPermissaoModulo") as CheckBox).Checked = (e.Row.DataItem as TPerfilModulo).PodeAcessar.Equals(1);
  15:     }
  16: }
  17:  
  18: private void SalvarDadosPerfil()
  19: {
  20:     TPerfilUsuario oTUsrPerfil = new TPerfilUsuario();
  21:     bool ok = false;
  22:     string script = "";
  23:     try
  24:     {
  25:         oTUsrPerfil.PerfilId = tbxCodigoPerfil.Text.Equals("") ? 0 : Int32.Parse(tbxCodigoPerfil.Text);
  26:         oTUsrPerfil.Descricao = tbxDescricaoPerfil.Text;
  27:  
  28:         //Atribui os valores selecionados no gridview nos módulos que pode acessar
  29:         foreach (GridViewRow r in gvModulosPerfil.Rows)
  30:         {
  31:             if (r.RowType.Equals(DataControlRowType.DataRow))
  32:             {
  33:                 oTUsrPerfil.Modulos[r.RowIndex].PodeAcessar = (r.FindControl("chkPermissaoModulo") as CheckBox).Checked ? 1 : 0;
  34:             }
  35:         }
  36:  
  37:         ok = (ViewState["CodigoPerfil"].ToString().Equals("0") ? oTUsrPerfil.Inserir() : oTUsrPerfil.Atualizar());
  38:         if (ok)
  39:         {
  40:             ViewState["CodigoPerfil"] = oTUsrPerfil.PerfilId.ToString();
  41:             tbxCodigoPerfil.Text = oTUsrPerfil.PerfilId.ToString();
  42:             PesquisarPerfil();
  43:             //Populando o combo-box de Pesquisa de Perfil
  44:             ddlPesqPerfilUsu.DataSource = TPerfilUsuario.ListarPerfis("");
  45:             ddlPesqPerfilUsu.DataValueField = "PerfilId";
  46:             ddlPesqPerfilUsu.DataTextField = "Descricao";
  47:             ddlPesqPerfilUsu.DataBind();
  48:             ddlPesqPerfilUsu.Items.Insert(0, new ListItem("--TODOS--", "0"));
  49:  
  50:             //Populando o combo-box de seleção de perfil do cadastro de usuários
  51:             ddlPerfilUsuario.DataSource = TPerfilUsuario.ListarPerfis("");
  52:             ddlPerfilUsuario.DataValueField = "PerfilId";
  53:             ddlPerfilUsuario.DataTextField = "Descricao";
  54:             ddlPerfilUsuario.DataBind();
  55:  
  56:         }
  57:         script = Consts.JavaScript.Alert(Consts.Funcoes.Replacer4js(oTUsrPerfil.MsgInfo), false);
  58:     }
  59:     finally
  60:     {
  61:         oTUsrPerfil.Dispose();
  62:     }
  63:     ScriptManager.RegisterStartupScript(this, this.GetType(), "alerta", script, true);
  64: }
  65:  
  66: private void ExibirDadosPerfil(string pID)
  67: {
  68:     TPerfilUsuario oTUsrPerfil = new TPerfilUsuario();
  69:     try
  70:     {
  71:         oTUsrPerfil.PerfilId = Int32.Parse(pID);
  72:         oTUsrPerfil.SetByID();
  73:         tbxCodigoPerfil.Text = oTUsrPerfil.PerfilId.ToString();
  74:         tbxDescricaoPerfil.Text = oTUsrPerfil.Descricao.ToString();
  75:         ViewState["CodigoPerfil"] = oTUsrPerfil.PerfilId.ToString();
  76:         
  77:         //Grid de módulos com acesso
  78:         gvModulosPerfil.DataSource = oTUsrPerfil.Modulos;
  79:         gvModulosPerfil.DataKeyNames = new string[1] { "ModuloID" };
  80:         gvModulosPerfil.DataBind();
  81:         
  82:         string script = "$dvModalLoader.jqmHide();$dvDetCadPerfil.jqmShow();";
  83:         ScriptManager.RegisterStartupScript(this, this.GetType(), "abre", script, true);
  84:     }
  85:     finally
  86:     {
  87:         oTUsrPerfil.Dispose();
  88:     }
  89: }
  90:  
  91: private void PesquisarPerfil()
  92: {
  93:     gvCadPerfil.DataSource = TPerfilUsuario.ListarPerfis(tbxPesquisaDescPerfil.Text.ToUpper());
  94:     gvCadPerfil.DataKeyNames = new string[1] { "PerfilId" };
  95:     gvCadPerfil.DataBind();
  96: }
  97:  
  98: protected void btnInserirPerfil_Click(object sender, EventArgs e)
  99: {
 100:     tbxCodigoPerfil.Text = "";
 101:     tbxDescricaoPerfil.Text = "";
 102:     ViewState["CodigoPerfil"] = "0";
 103:  
 104:     //Grid de módulos com acesso
 105:     TPerfilUsuario pu = new TPerfilUsuario();
 106:     try
 107:     {
 108:         gvModulosPerfil.DataSource = pu.Modulos;
 109:         gvModulosPerfil.DataKeyNames = new string[1] { "ModuloID" };
 110:         gvModulosPerfil.DataBind();
 111:     }
 112:     finally
 113:     {
 114:         pu.Dispose();
 115:     }
 116:     
 117:     string script = "$dvModalLoader.jqmHide();$dvDetCadPerfil.jqmShow();";
 118:     ScriptManager.RegisterStartupScript(this, this.GetType(), "abre", script, true);
 119: }
 120:  
 121: protected void btnSalvarPerfil_Click(object sender, EventArgs e)
 122: {
 123:     SalvarDadosPerfil();
 124: }
 125:  
 126: protected void btnCancelarCadPerfil_Click(object sender, EventArgs e)
 127: {
 128:     ViewState["CodigoPerfil"] = "0";
 129:     string script = "$dvDetCadPerfil.jqmHide();";
 130:     ScriptManager.RegisterStartupScript(this, this.GetType(), "abre", script, true);
 131: }
 132:  
 133: protected void btnPesquisarPerfil_Click(object sender, EventArgs e)
 134: {
 135:     PesquisarPerfil();
 136: }
 137:  
 138: protected void btnEditarPerfil_Click(object sender, EventArgs e)
 139: {
 140:     string id = gvCadPerfil.DataKeys[Int32.Parse((sender as Button).CommandArgument)].Value.ToString();
 141:     ExibirDadosPerfil(id);
 142: }
 143:  
 144: protected void btnExcluirPerfil_Click(object sender, EventArgs e)
 145: {
 146:     string msg = "";
 147:     if (TPerfilUsuario.Excluir(Int32.Parse(gvCadPerfil.DataKeys[Int32.Parse((sender as Button).CommandArgument)].Value.ToString()), out msg))
 148:     {
 149:         PesquisarPerfil();
 150:     }
 151:     string script = Consts.JavaScript.Alert(Consts.Funcoes.Replacer4js(msg), false);
 152:     ScriptManager.RegisterStartupScript(this, this.GetType(), "alerta", script, true);
 153: }

Como já adiantado, a janela de detalhes do perfil de usuário é uma janela modal construída pelo plugin jqModal do jQuery (as bibliotecas estão declaradas na master page e os modais foram inicializados no final da página do módulo); nela estão os controles que permitem alterar os dados do registro.

Quando clicamos no botão btnInserirPerfil ou btnEditarPerfil, registramos o script que oculta o modal da requisição AJAX (lembra... no artigo sobre como resolver alguns pepinos quando misturamos jQuery e ASP.NET Ajax?) e exibe o cadastro. Nestes botões também colocamos a chave do registro a ser exibido no ViewState "CodigoPerfil". No botão Inserir, colocamos como chave o valor "0" e colocamos alguns valores padrão dentro dos textboxes.

Para obtermos o ID do registro que queremos editar a partir do grid de pesquisa, guardamos esse ID na propriedade CommandArgument dos botões de Editar e Excluir. Isto pode ser feito no evento OnRowDataBound deste grid, usando um FindControl para pegarmos o controle desejado, e guardar o DataKey da linha no CommandArgument. Depois, nos métodos OnClick destes botões, recuperamos este valor.

Note que há nesta janela um gridview que lista os módulos que este perfil pode acessar. Este gridview é alimentado através da propriedade Modulos da classe TPerfilUsuario. Esta propriedade é um List de objetos do tipo TPerfilModulo. No evento RowDataBound deste grid, alteramos a propriedade Checked do checkbox em uma coluna template, baseando-se na propriedade PodeAcessar do objeto TPerfilModulo da linha que está sendo "bindada": Se for 1, o checkbox tem o Checked = true.

As diferenças entre o botão de inserir e atualizar são que no primeiro, não inicializamos valores em um objeto de TPerfilUsuario, ao contrário do segundo, o qual chamamos o método SetByID baseando-se no valor alimentado no viewstate "CodigoPerfil".

Os métodos de pesquisa e exclusão, não apresentam novidades: Instanciamos a classe e chamamos os respectivos comandos. Ao ser aplicados, dão um "refresh" nos dados do grid.

O método SalvarDadosPerfil merece um pouquinho de atenção: Antes de salvarmos o perfil, varremos o gridview com os módulos através de um laço foreach, e pegamos o valor do checkbox em cada linha do grid. Este valor é alimentado na propriedade PodeAcessar da coleção Modulos do perfil que estamos salvando. É como se fosse o "inverso" do que fazemos no RowDataBound do grid de listagem dos módulos.

Feito isso, damos o comando de Inserir ou Atualizar do perfil. Caso o nosso ViewState "CodigoPerfil" for zero, insere; caso contrário, atualiza.
Por fim, atualizamos o ViewState com o ID do registro que acabamos de gravar, o grid da tela inicial e os combo-boxes de seleção de perfil do cadastro de usuários e damos um alert com o resultado da operação.

O cadastro de Usuários tem funcionamento semelhante ao cadastro de Perfil, dispensando maiores explicações (são só a classe instanciada e os nomes dos componentes que mudam hehehe).

Na próxima parte do artigo, faremos a implementação do controle de acesso em um sistema.

Download:
Exemplo Sistema de Login em ASP.NET (com BD Firebird)  (289 kB)

Abraços a todos!

[Update 26/02/2008: Para facilitar o download, ao invés da página de suporte hospedada no Geocities, estarei movendo os arquivos para hospedagem própria, diretamente no domínio leonelfraga.com e colocando os links diretos para o arquivo.]

Leia o restante deste post...

Sobre o NeoMatrix Tech

Meu blog para assuntos profissionais, ligado com tecnologia.
Dicas de programação (grande parte de C# e ASP.NET, mas não limitado a essa plataforma :-) ), dicas de utilitários, análises de equipamentos e serviços, resenhas sobre sites que eu visito, relacionados com tecnologia, opinião sobre mercado de trabalho, metodologias de desenvolvimento, comportamento no mundo tecnológico...

NeoMatrix Light

  © Blogger templates ProBlogger Template by Ourblogtemplates.com 2008 - Editado e configurado por Leonel F.

Voltar ao TOPO