sexta-feira, 30 de outubro de 2009

Acessando o Active Directory (LDAP) com ASP.Net - Parte 4 - Adicionando Dados a um atributo

Fala, galera!!

Segue mais um código para manipulação de informações em base LDAP utilizando o .net.

O código é bem parecido com o código para atualização de dados. Mas ao invés de alterarmos um valor existente, iremos adicionar um novo valor ao atributo.

Dim recurso As New DirectoryEntry("LDAP://10.190.1.25")
Dim busca As New DirectorySearcher(recurso)
Dim resultado As SearchResult

'Você pode alterar o critério da busca para o critério que for melhor para sua aplicação.
busca.Filter = "(sAMAccountName=RafaelMaia)"
resultado = busca.FindOne()


'Adicionando o valor
Dim oDe As DirectoryEntry = Resultado.GetDirectoryEntry
oDe.Properties("mail").add("rafael@email.com.br")
oDe.CommitChanges()
oDe.Close()



Um abraço e até a próxima!!

segunda-feira, 26 de outubro de 2009

LDAP - Lista completa de atributos

Fala, galera!!

Segue um site com a lista completa de todos os atributos de uma base LDAP.

http://www4.nau.edu/its/sia/metadir/attributes.html

Essa aqui também é muito boa.
http://www.computerperformance.co.uk/Logon/LDAP_attributes_active_directory.htm

Um abraço e até a próxima!!

sábado, 24 de outubro de 2009

LINQ to XML - Consultando arquivos XML

Fala, galera!!

O Framework 3.5 nos oferece mais uma feature para lermos arquivos XML: O LINQ to XML.
O Linq to XML utilizar menos recursos de memória do que o tradicional System.XML.
Além de oferecer uma sintaxe mais simples o mesmo oferece melhor performance.

Considere o seguinte arquivo xml. Vamos chamá-lo de arquivo.xml.


<?xml version="1.0" encoding="utf-8" ?>
<Usuarios>
    <Usuario codigo="1">
        <nome>Usuario 1</nome>
        <email>usuario1@email.com</email>
    </Usuario>
    <Usuario codigo="2">
        <nome>Usuario 2</nome>
        <email>usuario2@email.com</email>
    </Usuario>
</Usuarios>


Vamos fazer uma consulta neste arquivo utilizando o Linq to XML.


       Dim xmldoc As System.Xml.Linq.XDocument
        xmldoc = XDocument.Load(Server.MapPath("./arquivo.xml"))
        Dim usuario = From c In xmldoc...<Usuario> _
                      Where c.@codigo = 1 _
                      Select c...<email>

        For i = 0 To usuario.Count - 1
            Response.Write(usuario(i).Value)
        Next

O resultado será: usuario1@email.com

Simples, não?

Você pode criar sua própria consulta LINQ da mesma forma que já está acostumado a fazer quando consulta dados no banco de dados.

Atenção: O Linq to XML é case-sensitive!!

Um abraço e até a próxima!!

Verificando um processo existente

Fala, galera!!

Certa vez precisei desenvolver uma console application que seria schedulada no windows para se executada a cada 10 minutos.

No entanto, eu não poderia permitir que uma nova execução se iniciasse enquanto a anterior não estivesse finalizada.
Para isso, foi necessário verificar se o processo anterior havia sido finalizado.

Segue o código para a verificação do processo.


'Obtem a lista de processos com nome "NomeDaAplicacao"
        Dim proc() As Process
        proc = Process.GetProcessesByName("NomeDaAplicacao")
        'Se existir mais de um processo com o mesmo nome, a ultima instância é cancelada.
        If proc.Length > 1 Then
            'Exibe alerta para o usuário
            MsgBox("O Programa já está sendo executado!")
            'Encerra a última instância aberta
            proc(0).Kill()
        End If


Um abraço e até a próxima!!

quinta-feira, 22 de outubro de 2009

Conectando em uma base de dados Oracle utilizando o Provider da Oracle para .Net

Fala, galera!!

Hoje estarei postando um código de acesso à um banco de dados Oracle.
O código é simples. Não foge do que já estamos acostumados a fazer com bases SQL Server.

A intenção deste post é apresentar o Provider da Oracle para .Net.

Assim como a Microsoft fornece um provider para conexões com base SQL Server, a Oracle também fornece seu provider. Porém, o mesmo não é nativo e precisa ser baixado aqui.

A vantagem de se utilizar provider específicos para uma base de dados é que o acesso é otimizado, promovendo ganhos de performance no acesso.
A desvantagem é que se um dia você resolver alterar o banco de dados da sua aplicação, você terá um trabalho maior alterando os providers da sua aplicação.

Vamos para o código.

Adicione no seu projeto a referência à DLL Oracle.DataAccess.dll
Em seguida, importe o namespace Oracle.DataAccess.Client

Imports Oracle.DataAccess.Client


Segue o código para se conectar:

Dim Conn as new OracleConnection
Conn.ConnectionString = "String de Conexão"
Conn.Open()

É isso ae!

Um abraço e até a próxima!!

sexta-feira, 16 de outubro de 2009

Redimensionando imagens sem perder qualidade

Fala, galera!!

Segue um código útil para quem precisa trabalhar com imagens em uma aplicação .Net.

O código abaixo utiliza a classe Drawing para redimensionar imagens sem perder a qualidade.


Sub Redimensionar(ByVal CaminhoImagem As String, Optional ByVal MaxLargura As Integer = 0, Optional ByVal MaxAltura As Integer = 0)

        Dim Arquivo As String = CaminhoImagem
        Dim MaxH As Integer = MaxAltura
        Dim MaxW As Integer = MaxLargura
        Dim pageContext As System.Web.HttpContext
        pageContext = System.Web.HttpContext.Current

        Dim OriImg As System.Drawing.Image
        OriImg = Image.FromFile(CaminhoImagem)


        If OriImg.Width > OriImg.Height Then
            'Padrão Paisagem
            If OriImg.Width > MaxW Then
                MaxH = Convert.ToInt32(OriImg.Height * MaxW / OriImg.Width)
            Else
                MaxW = OriImg.Width
                MaxH = OriImg.Height
            End If
        Else
            'Padrão Retrato
            If OriImg.Height > MaxH Then
                'MaxH = OriImg.Height
                MaxW = Convert.ToInt32(OriImg.Width * MaxW / OriImg.Height)
            Else
                MaxW = OriImg.Width
                MaxH = OriImg.Height
            End If
        End If

        OriImg = OriImg.GetThumbnailImage(MaxW, MaxH, New System.Drawing.Image.GetThumbnailImageAbort(AddressOf MyCallbackDelegate), System.IntPtr.Zero)
        Dim MS As System.IO.MemoryStream = New System.IO.MemoryStream
        OriImg.Save(MS, System.Drawing.Imaging.ImageFormat.Jpeg)
        Dim MsAr As Byte() = MS.ToArray()
        pageContext.Response.ContentType = "image/Jpeg"
        pageContext.Response.BinaryWrite(MsAr)

    End Sub
    Private Function MyCallbackDelegate() As Boolean
        Return False
    End Function

É necessário importar o namespace System.Drawing

Um abraço e até a próxima!!

quinta-feira, 15 de outubro de 2009

Fazendo um httpRequest em sua aplicação .Net

Fala, galera!!

Quem veio do ASP, como eu, está acostumado a utilizar o MSXML da Microsoft para realizar operações de httpRequest.
O .Net possui uma classe nativa para este tipo de Operação: HttpWebRequest.

Esta classe torna este tipo de operação ainda mais simples e, em caso de erro, fica mais fácil de debugar do que utilizando o antigo MSXML.
Além da vantagem de não precisar instalar nenhuma DLL externa no servidor onde a aplicação está hospedada. (Esta é o tipo de DLL que sempre dá problema em alguma implantação. Ninguém lembra dela. Só quando dá erro.)

Segue o código:


        Dim myRequest As HttpWebRequest = WebRequest.Create("http://www.algumaURL.com.br")
        Dim resp As HttpWebResponse = myRequest.GetResponse()

        Dim sr As New StreamReader(resp.GetResponseStream())
        retorno = sr.ReadToEnd()
        sr.Close()
      
        Response.Write(retorno)

O código acima irá obter o código gerado pela página apontada no seu WebRequest.

É necessário importar os seguintes Namespaces:


Imports System.Net
Imports System.IO


Um abraço e até a próxima!!

quarta-feira, 14 de outubro de 2009

Linq to SQL - Trabalhando com Procedures Dinâmicas

Fala, galera!!

Hoje estarei publicando uma espécie de "workaround" para uma limitação do Linq to SQL.
O LINQ nos permite trabalhar com stored procedures, gerando métodos de acesso às mesmas.
Quando criamos uma procedure que utiliza uma query "estática" o LINQ nos permite definir qual será o retorno da mesma: Auto-Generated ou algum objeto(tabela) do LINQ.

Mas quando trabalhamos com Queries dinâmicas o LINQ entende que o retorno da procedure é sempre um Inteiro (integer). Como contornar este problema?

Na verdade é bem simples. Basta estendermos a classe do LINQ.

O seu arquivo DBML possui 3 arquivos relacionados. o .dbml, o .designer.vb e o .vb.

Jamais altere o .designer.vb, pois este arquivo é gerado automaticamente a cada modificação no LINQ.
Ou seja, todas as suas modificações manuais são perdidas a cada modificação.

Para fazer as modificações, utilize o arquivo .vb.

Segue como deve ficar o seu aquivo .vb


Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Data.Linq
Imports System.Data.Linq.Mapping
Imports System.Linq
Imports System.Linq.Expressions
Imports System.Reflection
Imports System.ComponentModel.DataAnnotations
Imports Catalyst.ComponentModel.DataAnnotations

Namespace NomeProjetoDataContext


    Partial Public Class NomeProjeto
      <FunctionAttribute(Name:="dbo.procBuscarNoticias")> _
       Public Function procBuscarNoticias(<Parameter(Name:="Titulo", DbType:="VarChar(200)")> ByVal titulo As String, <Parameter(Name:="Resumo", DbType:="VarChar(500)")> ByVal resumo As String, <Parameter(Name:="DataCadastro", DbType:="VarChar(20)")> ByVal dataCadastro As String, <Parameter(Name:="CodCategoria", DbType:="Int")> ByVal codCategoria As System.Nullable(Of Integer), <Parameter(Name:="IndDestaque", DbType:="Int")> ByVal indDestaque As System.Nullable(Of Integer), <Parameter(Name:="IndAtiva", DbType:="Int")> ByVal indAtiva As System.Nullable(Of Integer)) As ISingleResult(Of Noticia)
            Dim result As IExecuteResult = Me.ExecuteMethodCall(Me, CType(MethodInfo.GetCurrentMethod, MethodInfo), titulo, resumo, dataCadastro, codCategoria, indDestaque, indAtiva)
            Return CType(result.ReturnValue, ISingleResult(Of Noticia))
        End Function
End Class

End Namespace

O código acima irá instanciar uma procedure que receberá alguns parâmetros e montará uma query dinâmica com base nesses parâmetros.
Definimos manualmente que o resultado desta procedure será um objeto do tipo "Noticia".

Apenas para constar: A estensão desta classe em um arquivo separado só pode ser feita graças ao conceito de Partial Class. O Partial Class permite que uma mesma classe possa estar distribuída em arquivos diferentes. Permitindo uma maior organização do seu código.

Um abraço e até a próxima!!

Acessando o Active Directory (LDAP) com ASP.Net - Parte 4 - Alterando a senha de um usuário

Fala, galera!!

Lá vai mais código de acesso à uma base LDAP.
Desta vez estarei publicando um código para alteração de senha de um usuário.

Lá vai:

Dim recurso As New DirectoryEntry("LDAP://10.190.1.25")
Dim busca As New DirectorySearcher(recurso)
Dim resultado As SearchResult
busca.Filter = "(sAMAccountName=RafaelMaia)"
resultado = busca.FindOne()

Dim oUser As DirectoryEntry = Resultado.GetDirectoryEntry
oUser.Invoke("SetPassword", New Object() {"NovaSenha"})
oUser.Close()

Bem simples. Como deve ser.

Um abraço e até a próxima!!

Acessando o Active Directory (LDAP) com ASP.Net - Parte 3 - Alterando dados do usuário

Fala, galera!!

Voltando ao assunto Active Directory.
Hoje estarei publicando um código para alteração dos atributos de um usuário em uma base LDAP.

A primeira coisa a fazer é carregar os dados do usuário que queremos alterar os dados.


Dim recurso As New DirectoryEntry("LDAP://10.190.1.25")
Dim busca As New DirectorySearcher(recurso)
Dim resultado As SearchResult
busca.Filter = "(sAMAccountName=RafaelMaia)"
resultado = busca.FindOne()

Em seguida, iremos para a alteração de fato.


Dim oDe As DirectoryEntry = Resultado.GetDirectoryEntry
oDe.Properties("mail")(0) = "rafael@email.com.br"
oDe.CommitChanges()
oDe.Close()


Pronto! O código acima altera o atributo "mail" diretamente na sua base LDAP.
Para alterar qualquer outro atributo basta trocar o nome da propriedade "mail" por qualquer outra propriedade.

Não esqueçam de importar o namespace System.DirectoryServices e das permissões necessárias para efetuar essas operações no LDAP.

Um abraço e até a próxima!!

segunda-feira, 12 de outubro de 2009

ASP.Net Dynamic Data - Gerando as classes de Metadados automaticamente

Fala, galera!!

O ASP.Net Dynamic Data permite que estendamos as classes de metadados das tabelas do banco de dados para que possamos fazer algumas customizações nas telas. Como: Aplicar regras de validação, formatar saída de dados, alterar o nome de exibição dos campos, etc.

Para que possamos estender essas classes, devemos codificar manualmente uma a uma.
Imagine o trabalho que isso daria em uma base de dados com muitas tabelas.

Para evitar esse trabalho manual, podemos automatizar a criação dos arquivos destas classes.
Segue o código:


Private Sub GerarAquivosDeMetadados()
        For i = 0 To MetaModel.Default.VisibleTables.Count - 1
            Dim arquivo As New Componente.Text.Controller
            Dim caminho As String = "c:\EnderecoDoProjeto" & MetaModel.Default.VisibleTables(i).EntityType.Name & "Partial.vb"
            Dim classes As String = CarregarImports()
            Dim conteudo As New StringBuilder
            conteudo.Append(classes & vbCrLf & "Namespace ManutencaoDataContext" & vbCrLf)
            If Not arquivo.FileExists(caminho) Then
                arquivo.OpenNewFile(caminho)
                conteudo.Append(vbTab & "<MetadataType(GetType(" & MetaModel.Default.VisibleTables(i).EntityType.Name & "_Metadata))> _" & vbCrLf)
                conteudo.Append(vbTab & "Partial Public Class " & MetaModel.Default.VisibleTables(i).EntityType.Name & vbCrLf)
                conteudo.Append(vbTab & "End Class" & vbCrLf & vbCrLf)
                conteudo.Append(vbTab & "Class " & MetaModel.Default.VisibleTables(i).EntityType.Name & "_Metadata" & vbCrLf & vbCrLf)
                For j = 0 To MetaModel.Default.VisibleTables(i).Columns.Count - 1
                    conteudo.Append(vbTab & vbTab & "Private _" & MetaModel.Default.VisibleTables(i).Columns(j).Name & " as " & IIf(InStr(MetaModel.Default.VisibleTables(i).Columns(j).TypeCode.ToString, "Int32") > 0, "Integer", MetaModel.Default.VisibleTables(i).Columns(j).TypeCode.ToString) & vbCrLf)
                Next
                conteudo.Append(vbCrLf)
                For j = 0 To MetaModel.Default.VisibleTables(i).Columns.Count - 1
                    conteudo.Append(vbTab & vbTab & "Public Property " & MetaModel.Default.VisibleTables(i).Columns(j).Name & "() as " & IIf(InStr(MetaModel.Default.VisibleTables(i).Columns(j).TypeCode.ToString, "Int32") > 0, "Integer", MetaModel.Default.VisibleTables(i).Columns(j).TypeCode.ToString) & vbCrLf)
                    conteudo.Append(vbTab & vbTab & vbTab & "Get" & vbCrLf)
                    conteudo.Append(vbTab & vbTab & vbTab & vbTab & "Return _" & MetaModel.Default.VisibleTables(i).Columns(j).Name & vbCrLf)
                    conteudo.Append(vbTab & vbTab & vbTab & "End Get" & vbCrLf)
                    conteudo.Append(vbTab & vbTab & vbTab & "Set(ByVal value As " & IIf(InStr(MetaModel.Default.VisibleTables(i).Columns(j).TypeCode.ToString, "Int32") > 0, "Integer", MetaModel.Default.VisibleTables(i).Columns(j).TypeCode.ToString) & ")" & vbCrLf)
                    conteudo.Append(vbTab & vbTab & vbTab & vbTab & "_" & MetaModel.Default.VisibleTables(i).Columns(j).Name & " = Value" & vbCrLf)
                    conteudo.Append(vbTab & vbTab & vbTab & "End Set" & vbCrLf)
                    conteudo.Append(vbTab & vbTab & "End Property" & vbCrLf & vbCrLf)
                Next
                conteudo.Append(vbTab & "End Class" & vbCrLf)
                conteudo.Append("End Namespace")
                arquivo.WriteLine(conteudo.ToString)
                arquivo.CloseFile()
                arquivo = Nothing
            End If
        Next
    End Sub


Private Function CarregarImports() As String
    Dim conteudo As New StringBuilder
    conteudo.Append("Imports System" & vbCrLf)
    conteudo.Append("Imports System.Collections.Generic" & vbCrLf)
    conteudo.Append("Imports System.ComponentModel" & vbCrLf)
    conteudo.Append("Imports System.Data" & vbCrLf)
    conteudo.Append("Imports System.Data.Linq" & vbCrLf)
    conteudo.Append("Imports System.Data.Linq.Mapping" & vbCrLf)
    conteudo.Append("Imports System.Linq" & vbCrLf)
    conteudo.Append("Imports System.Linq.Expressions" & vbCrLf)
    conteudo.Append("Imports System.Reflection" & vbCrLf)
    conteudo.Append("Imports System.ComponentModel.DataAnnotations" & vbCrLf)
    conteudo.Append("Imports Catalyst.ComponentModel.DataAnnotations" & vbCrLf)
    conteudo.Append("Imports System.Web.DynamicData" & vbCrLf)
    Return conteudo.ToString
End Function


OBS: Utilizei um componente que eu mesmo desenvolvi para fazer toda a manipulação do arquivo (criar, escrever, verificar a existência, etc.).
Este componente encapsula todas os namespaces e métodos do .net necessários para a manipulação de arquivos.
Quando você utilizar este código, deve substituir a chamada do meu componente pela chamada das classes do .net diretamente para a manipulação dos arquivos.

Normalmente, insiro o código acima no arquivo Default.aspx do ADD e executo o método GerarArquivosDeMetaDados no início da codificação.

Este código irá gerar fisicamente todas as classes de metadados que preciso no meu projeto.
Mas ainda é preciso incluí-las no projeto.

Vá ao solution explorer, clique na opção para exibir todos os arquivos.
As classes serão exibidas com um ícone branco. Clique com o botão direito do mouse nas classes e selecione a opção "Include in Project".

Pronto. Suas classes estão geradas e incluídas no projeto. Agora é só customizar.

Um abraço e até a próxima!!

DataPager - Utilizando a QueryString para paginar os dados

Fala, galera!!

Hoje em dia quando construímos aplicações web públicas devemos nos preocupar com algumas regras que permitem um melhor rankeamento de nosso site pelos sistemas de busca(google, yahoo, etc.).

Para que nosso site seja melhor rankeado e nossas páginas devidamente indexadas devemos nos preocupar em permitir que os robôs dos mecanismos de busca possam navegar por todo nosso site.

Isso tem um impacto direto na forma como programamos a paginação de nosso site.

Por default, o controle DataPager gera um código javascript que por sua vez dá um postback na página para que ocorra a paginação.
Este código não gera um link navegável pelos mecanismos de busca. Mas isso é facilmente contornável.
Basta utilizarmos a propriedade QueryStringField do datapager.

<asp:DataPager ID="DataPager1" PagedControlID="lstvNoticias" QueryStringField="Pagina" PageSize="10" runat="server">

Ao preenchermos esta propriedade, a paginação será exibida da seguinte forma:
http://www.seusite.com.br/pagina.aspx?Pagina=1
Este link é navegável pelos mecanismos de busca.

Em seguida, precisamos inserir a seguinte linha no code-behind antes de preenchermos o datasource.

DataPager1.SetPageProperties((CInt(Request("Pagina")) - 1) * DataPager1.PageSize, DataPager1.PageSize, False) 'Esta linha define a página que será exibida


lstvNoticias.DataSource = ListaComResultado
lstvNoticias.DataBind()



É isso ae, galera.

Um abraço e até a próxima!!

DataPager - Dica para evitar a necessidade de se clicar 2x para que a paginação funcione

Fala, galera!!

Quando utilizamos o DataPager para paginarmos dados em um controle de repetição, como o Datalist, nos deparamos com um comportamento "estranho" da paginação.

Este comportamento só ocorre quando preenchemos o datasource do controle de repetição programaticamente através do Code-Behind.

O comportamento ao qual me refiro é a necessidade de se clicar 2x no link de paginação para que a mesma funcione corretamente. São necessários 2 postbacks para se visualizar o efeito do postback anterior.

Exemplo:
Imagine uma paginção de 1 a 5. Serão exibidos 5 links:1  2  3  4  5

Ao clicarmos na página 2, a página não muda. Ao clicarmos na página 3, são exibidos os dados página 2.
Como se houvesse um delay de 1 postback.

A correção para isso é bem simples.

Basta inserirmos o preenchimento do datasource do controle de repetição dentro do evento "PreRender" do controle.


Private Sub DataList1_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
        DataList1.datasource = ListaComResultados
        DataList1.databind()
    End Sub

Um abraço e até a próxima!!

domingo, 11 de outubro de 2009

ASP.Net Dynamic Data - Alterando o texto dos botões de Inclusão, Alterção e Cancelamento

Fala, galera!!

Dando continuidade no assunto Asp.Net Dynamic Data estarei postando um código bem simples para alterar o texto dos botões de inclusão, alteração e cancelamento.

Por padrão, todos os textos do ADD estão em inglês. Isto inclui os textos dos botões exibidos nos formulários.

Para alterar o texto desses botões basta sobrescrever o método Render.

Eis o código:


Protected Overloads Overrides Sub Render(ByVal writer As HtmlTextWriter)
        Using htmlwriter As New HtmlTextWriter(New System.IO.StringWriter())
            MyBase.Render(htmlwriter)
            Dim html As String = htmlwriter.InnerWriter.ToString()
            html = html.Replace("Update</a>", "Atualizar</a>")
            html = html.Replace("Cancel</a>", "Cancelar</a>")
            writer.Write(html.Trim())
        End Using
    End Sub

Este método irá alterar o html que é renderizado pela aplicação.

Um abraço e até a próxima!!

sábado, 10 de outubro de 2009

Compactando e Descompactando arquivos através de sua aplicação ASP.Net

Fala, galera!!


Segue um código interessante para compactar e descompactar arquivos.


O código a seguir utiliza uma DLL de terceiros (open source) que pode ser baixada aqui.



    Public Sub DescompactarArquivoDiretorio(ByVal sArquivoZip As String, ByVal sDiretorioParaDescompactar As String)
        Dim oMeuZip As New ICSharpCode.SharpZipLib.Zip.FastZip
        oMeuZip.ExtractZip(sArquivoZip, sDiretorioParaDescompactar, ".*")
    End Sub


    Public Sub CompactarArquivo(ByVal sArquivoOrigem As String, ByVal sArquivoDestino As String)
        Dim sz As New ICSharpCode.SharpZipLib.Zip.FastZip
        Dim sArquivoZip As String = String.Empty

        ' Crio um arquivo do tipo stream, aprontando para o meu zip de destino.
        Dim strmZipOutputStream As ICSharpCode.SharpZipLib.Zip.ZipOutputStream
        strmZipOutputStream = New ICSharpCode.SharpZipLib.Zip.ZipOutputStream(File.Create(sArquivoDestino))
        ' Seto o nível de compressão (0->Sem compressão / 9-> Compressão Máxima)
        strmZipOutputStream.SetLevel(9)
        ' Leio o arquivo de origem
        Dim strmFile As FileStream = File.OpenRead(sArquivoOrigem)
        Dim abyBuffer(strmFile.Length - 1) As Byte
        strmFile.Read(abyBuffer, 0, abyBuffer.Length)
        ' Aqui eu trato para pegar somente o arquivo, sem os diretórios
        ' O split é um método que separa a string, de acordo com um caractere, no meu caso "\"
        ' Cada indice da minha matriz é um diretório, e o ultimo é o arquivo
        Dim sAuxArquivo As String() = Split(sArquivoOrigem, "\")
        ' Crio uma variável, adicionando o meu Arquivo ao Zip
        ' Com ubound, eu pego o ultimo índice da minha matriz, que é o nome do meu arquivo.
        Dim objZipEntry As ICSharpCode.SharpZipLib.Zip.ZipEntry = New  ICSharpCode.SharpZipLib.Zip.ZipEntry(sAuxArquivo(UBound(sAuxArquivo)))
        ' Seto a data de criação
        objZipEntry.DateTime = DateTime.Now
        ' Informo o tamanho do stream. (Do meu arquivo a ser zipado)
        objZipEntry.Size = strmFile.Length
        ' Fecho meu stream para liberar memória
        strmFile.Close()
        ' Adiciono no objeto para gerar o zip.
        strmZipOutputStream.PutNextEntry(objZipEntry)
        strmZipOutputStream.Write(abyBuffer, 0, abyBuffer.Length)
        ' "Limpo" o objeto
        strmZipOutputStream.Finish()
        strmZipOutputStream.Close()
    End Sub



É isso ae.

Um abraço e até a próxima!!

Acessando as propriedades de uma Imagem

Fala, galera!!

Vou postar um código simples, mas de grande utilidade para manipulação/validação de imagens em aplicações .net.


        Dim img As System.Drawing.Image
        img = Image.FromFile("c:\Imagem.jpg")
        Response.Write(img.size.height)
        Response.Write(img.size.Width)

Com apenas essas poucas linhas de código você tem acesso às propriedades de uma imagem, como: altura, largura, geração de thumbnails, rotacionamento, entre outras propriedades.

O objetivo deste post foi apenas apresentar a classe Image e alguns dos recursos que são implementados pela mesma.

Um abraço e até a próxima!!

Verificando a existência de um domínio de email

Fala, galera!!

O código que irei postar agora é muito interessante para aplicações de envio de newsletters.
É normal em um ambiente com milhares ou milhões de emails que muitos desses emails sejam inválidos.

Validar o formato do email apenas não garante que um email realmente existe.
Existe uma outra validação que podemos aplicar que aumenta as chances de garantirmos que o email existe: A validação do domínio do email.

Esta validação não garante 100% que a existência da conta do usuário, mas garante pelo menos que o domínio do email é um domínio válido.

Segue o código:


        Dim dominio As String
        Dim ObjHost As System.Net.IPHostEntry
        Try
            dominio = Email.Substring("email".IndexOf("@") + 1)
            ObjHost = System.Net.Dns.GetHostEntry(dominio)
            ObjHost = Nothing
            Response.Write("Domínio válido")
        Catch ex As Exception
            Response.Write("Domínio inválido")
        End Try

É isso ae.

Um abraço e até a próxima!!

Acessando uma caixa postal através de uma aplicação ASP.Net

Fala, galera!!

Hoje estarei postando um código para acessar uma caixa postal através de uma aplicação .net.
Este recurso é muito útil para quem deseja desenvolver seu próprio webmail ou fornecer alguma solução baseada em emails. Seja ela qual for.

O código abaixo utiliza uma DLL de terceiros totalmente gratuita e que pode ser baixada aqui.

Vamos ao que interessa:


        Dim oEmail As New Pop3Client("usuario", "senha", "servidor")
        oEmail.OpenPOP3()
        'Salva todos os anexos no diretório escolhido
        oEmail.AttachmentFolder = "c:\anexos"
        Response.Write("Foram localizados " & oEmail.MessageCount.ToString() & " email(s)")
        While oEmail.NextEmail()
            Response.Write(oEmail.From & "<br>")
            Response.Write(oEmail.Subject & "<br>")
            Response.Write(oEmail.HTMLBody & "<br>")
        End While
        oEmail.CloseConnection()

Simples assim.

Um abraço e até a próxima!!

sexta-feira, 9 de outubro de 2009

Executando um DTS através de sua aplicação ASP.Net

Fala, galera!!

Segue mais um código de grande utilidade para quem precisa trabalhar com DTS em suas aplicações.
O .net fornece classes para que você possa executar um DTS de dentro de sua aplicação.

Veja:


        Dim objDTS As New Global.DTS.Package
        Dim objStep As Global.DTS.Step
        Dim sSrc, sDsc As String
        Dim dErr As Double
      
        Try
            Dim obj As Object
            obj = Global.DTS.DTSSQLServerStorageFlags.DTSSQLStgFlag_Default
            objDTS.LoadFromSQLServer(Servidor, Usuario, Senha, 0, , , , NomeDTS)

            For Each objStep In objDTS.Steps
                objStep.ExecuteInMainThread = True
            Next

            objDTS.Execute()

            For Each objStep In objDTS.Steps
                If objStep.ExecutionResult = Global.DTS.DTSStepExecResult.DTSStepExecResult_Failure Then
                    objStep.GetExecutionErrorInfo(dErr, sSrc, sDsc)
                    If dErr > 0 AndAlso sSrc.Length > 0 Then
                        Response.Write(dErr & ": " & sSrc & " - " & sDsc & "<br>")
                    End If
                End If
            Next

Um abraço e até a próxima!!

Corretor Ortográfico do Word em aplicações ASP.Net

Um recurso muito interessante para nossas aplicações é o corretor ortográfico.
Principalmente quando falamos de gerenciadores de conteúdo.

O .net fornece classes para que se implemente um corretor ortográfico idêntico ao do word (para não dizer que é o mesmo corretor) em suas aplicações com um esforço mínimo de codificação.

Segue o código para implementar o corretor:


       'Instância do objeto Word
        Dim objWord As New Microsoft.Office.Interop.Word.ApplicationClass()
        'Cria um documento em branco
        objWord.Documents.Add()
        'Adiciona o texto no novo documento em branco
        objWord.Selection.TypeText(Me.txtTeste.Text)
        'Aciona a ação de verificação ortográfica
        objWord.Documents.Item(objWord.Documents.Count).CheckSpelling()
        'Retorna o texto corrigido para o textbox
        txtTeste.Text = objWord.Documents.Item(objWord.Documents.Count).Content.Text
        'Fecha o documento sem salvar as alterações no documento em branco que foi criado
        objWord.Documents.Close(Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges)
        'Fecha a instância do word
        objWord.Quit()
        'Destrói o objeto word
        objWord = Nothing

É importante adicionar a referência às bibliotecas do Word
Add Reference > COM > Microsoft Word 12.0 Object Library

E importar o namespace.
Imports Microsoft.Office.Interop.Word

Com isso, seu corretor está implementado.

Veja um print da tela.


update:

Versão em C#

Microsoft.Office.Interop.Word.ApplicationClass objWord = new Microsoft.Office.Interop.Word.ApplicationClass();
//Cria um documento em branco
objWord.Documents.Add();
//Adiciona o texto no novo documento em branco
objWord.Selection.TypeText(this.txtTeste.Text);
//Aciona a ação de verificação ortográfica
objWord.Documents.Item(objWord.Documents.Count).CheckSpelling();
//Retorna o texto corrigido para o textbox
txtTeste.Text = objWord.Documents.Item(objWord.Documents.Count).Content.Text;
//Fecha o documento sem salvar as alterações no documento em branco que foi criado
objWord.Documents.Close(Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges);
//Fecha a instância do word
objWord.Quit();
//Destrói o objeto word
objWord = null;

Um abraço e até a próxima!

Alterando o usuário que roda sua aplicação (Impersonation)

Tipicamente, o usuário que roda sua aplicação é o usuário do IIS. Este usuário pode ser configurado na tela abaixo: (Aba Directory Security > Seção Authentication and Access Control)



Você pode alerar este usuário de 2 formas.
A primeira delas é alterando diretamente no IIS.
Uma outra forma é alterando programaticamente na sua aplicação.

Basta adicionar a seguinte linha na seção <System.web> do arquivo web.config.

<identity impersonate="true" userName="Dominio\Usuario" password="Senha" />


Ao inserir esta linha no web.config, sua aplicação será executada sob o contexto do usuário configurado.


Um abraço e até a próxima!

Acessando o Active Directory (LDAP) com ASP.Net - Parte 2 - Adicionando e Removendo um usuário de um grupo

Fala, galera!!

Hoje estarei dando continuidade ao assunto Active Directory.
Em uma das aplicações que estive desenvolvendo foi necessário manipular o grupo ao qual um usuário pertence.

Segue o código para adicionar e remover um usuário de um grupo no Active Directory.

Adicionando usuário ao grupo:


        Dim rootEntry As New DirectoryEntry("LDAP://10.190.1.25")
        Dim Mysearcher As New DirectorySearcher(rootEntry)
        Mysearcher.SearchRoot = rootEntry
        Mysearcher.Filter = "(&(objectCategory=group)(CN=Grupo_Teste))"
        Dim result As SearchResult = Mysearcher.FindOne()
        Dim g As DirectoryEntry = result.GetDirectoryEntry()

        Dim busca As New DirectorySearcher(rootEntry)
        busca.Filter = "(sAMAccountName=RafaelMaia)"
        result = busca.FindOne()

        Dim user As DirectoryEntry = result.GetDirectoryEntry()

        g.Invoke("Add", New [Object]() {user.Path})
        g.CommitChanges()

        g.Close()
        g.Dispose()

        user.Close()
        user.Dispose()

        Mysearcher.Dispose()
        rootEntry.Close()
        rootEntry.Dispose()

No código acima estou adicionando o usuário RafaelMaia ao grupo Grupo_Teste.
Se você tentar adicionar um usuário a um grupo que ele já pertence, ocorrerá uma exception.

Por isso, é importante validar se o usuário já pertence ao grupo antes de adicioná-lo.
Isso pode ser feito facilmente utilizando o código postado no artigo anterior.
Basta consultar os dados do usuário e verificar a propriedade "MemberOf".
Esta propriedade retorna um array de string contendo todos os grupos que o usuário pertence.

Removendo usuário do grupo:


        Dim rootEntry As New DirectoryEntry("LDAP://10.190.1.25")
        Dim Mysearcher As New DirectorySearcher(rootEntry)
        Mysearcher.SearchRoot = rootEntry
        Mysearcher.Filter = "(&(objectCategory=group)(CN=Grupo_Teste))"
        Dim result As SearchResult = Mysearcher.FindOne()
        Dim g As DirectoryEntry = result.GetDirectoryEntry()

        Dim busca As New DirectorySearcher(rootEntry)
        busca.Filter = "(sAMAccountName=RafaelMaia)"
        result = busca.FindOne()

        Dim user As DirectoryEntry = result.GetDirectoryEntry()

        g.Invoke("Remove", New [Object]() {user.Path})
        g.CommitChanges()

        g.Close()
        g.Dispose()

        user.Close()
        user.Dispose()

        Mysearcher.Dispose()
        rootEntry.Close()
        rootEntry.Dispose()


Reparem que os códigos são praticamente idênticos. Alterando somente a linha a seguir:
        g.Invoke("Remove", New [Object]() {user.Path})

Antes de excluir um usuário do grupo, verifique se o mesmo pertence realmente ao grupo em questão.
Caso tente excluir um usuário que não pertence ao grupo, ocorrerá uma exception.

É muito importante também que o usuário que está rodando sua aplicação tenha permissões para executar esta operação no active directory.

Um abraço e até a próxima!!

quinta-feira, 8 de outubro de 2009

Acessando o Active Directory (LDAP) com ASP.Net - Parte 1 - Consultando dados de um usuário

Fala, galera!!

Sejam bem-vindos!

Não sei com que freqüência estarei atualizando o blog. Por isso, vou tentar iniciar com o pé direito publicando um código de acesso ao Active Directory (LDAP).

É muito comum criarmos aplicações que façam uso da estrutura do Active Directory para autenticar usuários ou validar regras de acesso. Para isso, o .Net fornece classes para manipulação de dados dentro de bases LDAP (Lightweight Directory Access Protocol

Segue um exemplo de como consultar dados de um usuário direto de uma base de dados LDAP:

        Dim de As New DirectoryEntry("LDAP://10.190.1.25") 'Endereço do active Directory
        Dim busca As New DirectorySearcher(de)
        Dim resultado As SearchResult
        busca.Filter = "(sAMAccountName=RafaelMaia)"
        resultado = busca.FindOne()
        Response.Write results.Properties("mail")(0)


O código acima irá consultar os dados do usuário RafaelMaia e escrever na tela o email do mesmo.
Pode-se acessar qualquer informação cadastrada no perfil do usuário no Active Directory.
Desde o Nome até telefones de contato. Só não se pode recuperar a senha do usuário, por razões óbvias.

É importante importar o namespace System.DirectoryServices.

Imports System.DirectoryServices


No link abaixo você pode visualizar uma lista completa de todas as propriedades do Active Directory.
http://www.computerperformance.co.uk/Logon/LDAP_attributes_active_directory.htm

A seguir um exemplo de como validar o login e senha de um usuário diretamente no AD.


Dim de As New DirectoryEntry(Nothing, "dominio\RafaelMaia", "senha_do_usuario")
        Try
            Dim o = de.NativeObject
            Dim ds As New DirectorySearcher(de)
            ds.Filter = "samaccountname=RafaelMaia"
            ds.PropertiesToLoad.Add("cn")
            Dim sr As SearchResult
            sr = ds.FindOne()
            If IsNothing(sr) Then Throw New Exception()
            Response.write("Login válido!")
        Catch ex As Exception
            Response.write("Login e/ou senha  inválidos!")
        End Try

É isso ae, galera!!
Há muitas coisas que se pode fazer em uma base LDAP. Como: criar usuário, alterar dados, ativar ou desativar contas, etc.

Por enquanto, vamos ficando por aqui.

Um abraço e até a próxima!