Mostrando postagens com marcador dicas. Mostrar todas as postagens
Mostrando postagens com marcador dicas. Mostrar todas as postagens

Usando o ScripManager em sequência

Esse artigo será apenas uma dica para os desatentos. Quando você usa o ScriptManager para exibir um alerta, por exemplo, e em outro trecho do código fazer a mesma coisa, verá que apenas o primeiro alerta é demonstrado e o segundo não. O porquê disso é se estiver reaproveitando o mesmo script e não diferenciar o bloco de execução dele, sempre será exibido apenas o primeiro. Logo, o certo, é ter algo do tipo:


// Exibe o primeiro alerta
ScriptManager.RegisterStartupScript(Page, typeof(Page), "script1", "alert('Alerta 1');", true);


...



// Exibe o segundo alerta
ScriptManager.RegisterStartupScript(Page, typeof(Page), "script2", "alert('Alerta 2');", true);

Reparou no bloco script1 e script2? É isso.

Recuperando a senha da conta identidade do Pool de Aplicativos do Plesk no IIS

Mais um título longo... um tanto confuso, mas em resposta a uma dúvida de um amigo:
"Exclui um Application Pool no IIS e nela estava configurada uma conta interna do Plesk: IWAM_plesk. Não sei a senha utilizada. Tem como recuperar a senha para recriar um novo application?"
Sim! O Plesk sempre nos pregando aquela peça... Os dois pools que o Plesk utiliza estão vinculados à conta IWAM_plesk (conta interna) para que possam manipular corretamente os arquivos e seus aplicativos (bem como as permissões necessárias) no sistema operacional:

  1. plesk(default)(2.0)(pool)
  2. plesk(default)(4.0)(pool)

 Então façamos as seguintes etapas:

  • Abra o Prompt de Comando em Modo Administrador;
  • Navegue para a pasta C:\Windows\system32\inetsrv;
  • Execute o comando appcmd.exe list apppool “plesk(default)(2.0)(pool)” /text:*
Aparecerá a descrição completa desse pool. Procure a entrada referente ao usuário e senha do Plesk conforme a figura abaixo:


Agora você tem a senha do usuário! No site de Dhiraj tem mais detalhes acerca desse tipo de recuperação.

Calculando saldo final no Crystal Reports

Antes de começar o artigo, queria dizer que nesse mês irei responder muitas das questões que recebo por e-mail (calma que um dia sempre respondo) em forma de artigo, então muitos deles serão curtos e rápidos. Uma das respostas será nesse artigo.
Bem, como calculo o saldo, linha a linha, de entradas e saídas no Crystal Reports? De forma bem simples: uso de variáveis globais. Um bom artigo que sempre recomendo é o de Vince Varallo: não tem erro!
Supondo que você tenha o seguinte relatório e com os respectivos campos:


Esses dados já devem ser puxados do DataSet utilizado (na dúvida, veja o post de criar relatórios). Agora adicionamos um Formula Field com o nome SALDO.


Clique em Use Editor e escreva a seguinte fórmula:



Global NumberVar SALDO_FINAL;

if (RECORDNUMBER = 1) then
    SALDO_FINAL := @ENTRADA - @SAIDA
else
    SALDO_FINAL := SALDO_FINAL + @ENTRADA - @SAIDA


Ou seja, na primeira linha obtenho o saldo inicial diminuindo a ENTRADA da SAIDA. Nos demais já adiciono o saldo anterior. Tranquilo? Agora basta adicionar no relatório esse campo criado.

Testando um Web-Site na própria máquina como se fosse externamente

Tentei elaborar um título de forma que ficasse entendível o que eu queria dizer. Não sei se ajuda, mas significa que:
"Testaremos o acesso a um web-site que está publicado no IIS mas que no navegador não iremos usar localhost para buscá-lo e sim o próprio endereço."
Ficou bom agora? Então vamos lá. No IIS crie um web-site. O processo é bem simples:


Pronto! Já temos nosso site, mas se formos testar: http://thiagomarcal.com.br/ não encontra!


Por que isso? Quando queremos procurar um site, o sistema operacional analisa o hostname para saber onde encontrar esse endereço: se for interno e mapeado usa-se a rede interna, senão procura a rede externa dentre outros. Como não existe o mapeamento e tampouco o domínio externo, não acha nada. Então vamos alterar o arquivo de host.

Siga para o caminho: C:\Windows\System32\drivers\etc e abra o arquivo hosts, em modo texto, para adicionarmos algumas entradas.

# copyright (c) 1993-2009 microsoft corp.
#
# this is a sample hosts file used by microsoft tcp/ip for windows.
#
# this file contains the mappings of ip addresses to host names. each
# entry should be kept on an individual line. the ip address should
# be placed in the first column followed by the corresponding host name.
# the ip address and the host name should be separated by at least one
# space.
#
# additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# for example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host

# localhost name resolution is handled within dns itself.
#	127.0.0.1       localhost
#	::1             localhost

127.0.0.1	thiagomarcal.com.br

Coloque, na última linha, o IP, tabulação e nome do domínio nessa ordem para o site desejado. Salve e teste novamente o acesso. E pronto!


Mais fácil do que isso: impossível!

Consumindo Web-Service PHP através do ASP.NET (C#)

Já passou por aqui um post sobre de como consumir um web-service, mas era em ASP.NET. Agora como consumir um web-service em PHP? Da mesma forma. Não muda! O fato de escrever esse post é apenas e pelo simples fato de ter um certo inconveniente na elaboração do web-service em PHP.
Se procurar na net, recomendo o artigo de Maurício Reckziegel da iMasters que é muito bom e explica certinho como fazer. Se você seguir à risca o que está escrito irá conseguir elaborar um web-service em PHP normalmente e irá conseguir consumir, menos em ASP.NET. Não é que a matéria esteja errada, é porque o ASP.NET é chato com a validação do WSDL que é gerado pelo PHP. O documento (WSDL) tem que ser gerado na mão e, quando não é gerado de forma automática, estamos susceptíveis ao erro. Com o web-service em PHP é assim...
Então, digamos que você tenha elaborado o web-service em PHP e já fez referência na sua aplicação. Contudo sua aplicação pode dar erro ou retornar nada. Primeiramente, todo WSDL que iremos usar deve ser validado antes de ser devidamente consumido. O Visual Studio dispõe de uma ferramenta que valida e gera a classe consumidora (que não precisar ser usada pois está intrínseco na ferramenta). Vá em Iniciar > Todos os Programas > Microsoft Visual StudioVisual Studio ToolsVisual Studio 2008 Command Prompt. Irá abrir um prompt de comando. Escreva por exemplo: wsdl http://thiagomarcal.blogspot.com/webservice.php?wsdl . Se der tudo certo, irá surgir um resultado semelhante a esse:


Se estiver tudo OK, então pode usar tranquilamente, caso contrário irá surgir o seguinte problema:

Microsoft (R) Web Services Description Language Utility
[Microsoft (R) .NET Framework, Version 2.0.50727.3038]
Copyright (C) Microsoft Corporation. All rights reserved.

Warning: This web reference does not conform to WS-I Basic Profile v1.1.

Ou seja, o WSDL gerado pelo PHP não está conforme o padrão. Dando uma alterada aqui e ali, podemos usar o seguinte código para gerarmos o web-service em PHP dentro dos conformes:

<?php
// Requerimento aos componentes
require_once('nusoap/nusoap.php');
include("class.phpmailer.php");
include("class.smtp.php");


// Criação da instância
$server = new soap_server();


// Registro do método
$server->register('EnviaMail');


// WSDL
$server->configureWSDL('server.EnviaMail','urn:server.EnviaMail');
$server->wsdl->schemaTargetNamespace = 'urn:server.EnviaMail';
// registra o método a ser oferecido
$server->register('EnviaMail', //nome do método
array('email' => 'xsd:string'), //parâmetros de entrada
array('return' => 'xsd:string'), //parâmetros de saída
'urn:server.EnviaMail', //namespace
'urn:server.EnviaMail#EnviaMail', //soapaction
'rpc', //style
'literal', //use
'Retorna se o e-mail foi enviado' //documentação do serviço
);


// Definição do método a ser utilizado
function EnviaMail($email) {
return "E-email enviado com sucesso!";
}


// Requisição para uso do serviço
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
?>

Perceberam a diferença? Praticamente nenhuma, mas há: o estilo do documento. Não irei entrar em detalhes, mas dois tipos de documentos mais usados: encoded e literal (veja mais nesse artigo). Use literal! Com isso seu web-service será consumido certinho...
Se estiver com o erro: O cliente encontrou o tipo conteúdo de resposta de ' text/html; charset = utf-8 ', mas era esperado 'text/xml' ou The client find the answer 'text/html', but was expected 'text/xml'. verifique se seu web-service está imprimindo conteúdo HTML (echo) e comprometendo o retorno dos dados. Tranquilo, né?

Problemas de cache no SQL Server

Se você estiver recebendo uma mensagem do tipo:

O SQL Server encontrou %d ocorrência(s) de liberação de armazenamento em cache para o cache '%s' (parte do cache do esquema) devido à manutenção do banco de dados ou operações de reconfiguração.
ou
SQL Server has encountered %d occurrence(s) of cachestore flush for the '%s' cachestore (part of plan cache) due to some database maintenance or reconfigure operations.
É porque, segundo a MSDN, ao limpar o cache do plano gera uma recompilação de todos os planos de execução subseqüentes e pode provocar uma queda repentina e temporária no desempenho da consulta. Para cada armazenamento em cache limpo no cache do plano, aparece a mensagem supracitada.

Para resolver isso, basta ir no banco correspondente, clicar com o direito sobre ele e escolher Properties (Propriedades). Entre em Options (Opções) e configure o Auto-Close (Fechamento Automático) para False.

Cufon na Master Page

Para quem está com problemas no carregamento/aplicação do Cufon quando estiver usando Master Page, chame-o da seguinte forma:

<script>
Cufon.now();
function pageLoad(sender, args) {
      Cufon.refresh();
}
</script>

Assim ele aplica corretamente após o carregamento da página.

Out of Memory at Line - Memória Insuficiente

Dica rápida para quem tiver esse tipo de problema: remova o atributo LoadScriptsBeforeUI='false' from ScriptManager. Dentro de Grid editáveis ou em formulários dinâmicos a validação do Javascript falha quando estiver fazendo esse tipo de otimização.

Erros mais frequentes no ASP.NET

Para quem está começando a desenvolver com ASP.NET e se depara com a tela amarela, já deve ficar horrorizado com a linguagem. Diferente das linguagens ultrapassadas, essa tela é muito útil para desvendar os problemas e, posteriormente, corrigí-los.


As telas de erro do ASP.NET mais comuns são aquelas nas quais são exibidas direto o erro para o usuário. Lembrando que já vimos em um post que isso demonstra vulnerabilidade do sistema mas que, a nível de homologação, é utilizável para identificar os problemas, análise da pilha e comportamento do mesmo.

Não vou explicar tudo sobre erros no ASP.NET senão teríamos um grande post de tudo o que ocasiona erros, mas para auxiliar os iniciantes, a Locaweb disponibilizou um tópico nas quais explica os erros mais comuns de programação bem como corrigí-los. Dêem uma lida para conferir... Veja aqui!

Utilizando mensagem de confirmação e executando código de acordo com o que foi clicado na mesma página

Não sei se o título ficou claro com o que eu queria dizer, mas vejamos a seguinte situação:
"Quero colocar uma mensagem de confirmação via code-behind onde irá ser emitida para o usuário e a depender do que ele escolher irá ser processado um certo trecho de código ou outro. Tipo o confirm do JavaScript, só que é executado pelo ASP.NET."

No Code Project tem várias formas de implementação e umas delas me chamou a atenção: o de Yavuz Kucukpetek. Usando AJAX é possível transformar um Panel nessa janela flutuante usando o ModalPopupExtender. Dei uma simplificada no código dele (já informei que não fiz, apenas ajustei) e você podem baixar o controle modificado aqui.

Depois que baixarem o controle, adicione no seu projeto. Vamos lá! Na página que deseja utilizar o controle, registre-o e coloque-o da seguinte forma:

<%@ Register Src="~/inc_ConfirmMessage.ascx" TagName="ConfirmacaoBox" TagPrefix="Thiago" %>


<Thiago:ConfirmacaoBox ID="ConfirmacaoBox" runat="server"></Thiago:ConfirmacaoBox>

No code-behind deverá ficar o seguinte:


    protected void Page_Load(object sender, EventArgs e)
    {
        ConfirmacaoBox.MsgBoxAnswered += Mensagem_Resposta;
    }



    public void Mensagem_Resposta(object sender, inc_ConfirmMessage.MsgBoxEventArgs e)
    {
        if (e.Answer == inc_ConfirmMessage.enmAnswer.OK)
        {
            // Se clicou em OK processa o que deseja
        }
        else
        {
            // Senão processa outra coisa
        }
    }



    protected void ExecutaProcesso_Click(object sender, EventArgs e)
    {
        ConfirmacaoBox.AddMessage("Deseja continuar o cálculo do processo na mesma página?", inc_ConfirmMessage.enmMessageType.Attention, true, true, "");
    }

Pronto! Apenas isso... Vamos às explicações. No Page_Load precisamos informar o método que irá gerenciar as decisões do usuário, por isso informamos o Mensagem_Resposta. Dentro dele irá conter os processos que irão ser executados a depender da escolha. O ExecutaProcesso_Click é o método executado quando clicamos no botão que irá disparar a pergunta.

"Ah Thiago, mas aí é só apenas uma confirmação. E se eu quiser várias interações?"

Simples, basta adicionar outra Caixa de Confirmação para a segunda etapa de decisões chamando-a dentro do processo de decisão da primeira e assim por diante.

Bloqueando apenas um acesso por vez em uma variável de aplicação

Toda aplicação web que trabalhamos raramente pensamos na quantidade de acessos que são realizados simultaneamente em um determinado trecho de código. Um exemplo clássico é uma variável de contador de acessos/visitantes. Armazenamos o valor inicialmente em uma variável de aplicação. Depois quando um usuário acessa, é incrementado em 1. Só que se ao mesmo tempo acessar dois ou mais usuários, eles podem capturar o mesmo valor ou valor defasado e colocar a contagem errada. Veja o exemplo abaixo:


Quando tivemos o acesso simultâneo\paralelo, o valor capturado da variável da aplicação foi colhido pelos dois usuários e o valor armazenado foi comprometido. Para isso devemos bloquear o acesso à variável de aplicação e permitir apenas um usuário por vez executar a soma. Nesse caso, pode-se utilizar o seguinte trecho:


        try
        {
            Application.Lock();
            lock (this)
            {
                // Trecho a ser executado que altera uma variável de aplicação ou bloco crítico
            }
            Application.UnLock();
        }
        catch
        {
            Application.UnLock();
        }


O Application.Lock() irá bloquear o acesso de outros usuários às variáveis de aplicação e depois o Application.UnLock() libera. O lock (this) permitirá apenas o acesso de um único usuário por vez no trecho de código crítico. A combinação dos dois métodos depende muito do que estiver fazendo. Cada caso tem seu respectivo uso. O simples uso do lock (this) pode resolver... Ele é muito usado para evitar deadlocks. No mais, só isso. Recomendo dar uma lida posteriormente nos artigos abaixo:

Diferenças entre Aplicações Compiladas e Não-Compiladas

Quando programávamos (ou programamos) com aquelas linguagens do tipo PHP ou ASP Clássico apenas pegávamos o que foi implementado e jogávamos no servidor web para uso. Com a inovação das tecnologias e tipos de linguagens (compiladas, interpretadas, híbridas) algumas dúvidas nos cercam quando estamos publicando um certo projeto. Nesse caso, falemos do ASP.NET para as versões acima da 2.0.

Antes de mais nada, o ASP.NET é compilado. Mesmo que você jogue os fontes no IIS ele é compilado na primeira vez que é acessado (e/ou alterado). Você não vê, mas por trás é feito isso. Para quem nunca compilou uma aplicação web, há diversas formas para uma dada finalidade. Geralmente é usada a função Publish Web Site (compila e publica).


Mas o que muitos perguntam é: existe diferença de desempenho? Não! Muitos dizem que há um pouco, mas já trabalhei com várias aplicações e não notei qualquer diferença. Li vários artigos por aí na net e não achei qualquer um que demonstrasse e/ou notasse diferença brusca de desempenho. Então, elaborei a seguinte tabelinha abaixo com um pequeno resumo. Se tiver mais, favor avisar-me que atualizo:


Compilada
Não-Compilada
 Desempenho
 Normal
Normal
 Código-fonte
 Protegido em DLL's
Visível 
 HTML
 Sem mudança
Sem mudança 
 Atualização\Correção
 Precisa compilar todo o projeto e publicá-lo (código-fonte) enquanto no design pode alterar normalmente
Pode alterar diretamente no problema (página)
 Primeiro Acesso
 Normal
Lento 

Óbvio que toda regra tem sua exceção, então a depender dos casos supra-citados pode haver pequenos detalhes que mudam uma coisinha ou outra mas nada de tão drástico (de acordo com a tabela - exemplo, na compilação FULL você não altera sequer o HTML). Se quiserem conhecer mais sobre os tipos de compilação (Full, Pré ou Sob-Demanda) visite os links da MSDN e de Dennes Torres.

Convertendo HTML em PDF

Nesse artigo veremos como converter um HTML em PDF. O HTML pode vir de uma página externa quanto ser criado em tempo de execução. Não haverá muito o que explicar pois o código em si, você encontra a rodo pela net. Usaremos o componente iTextSharp.

Baixe o binário e adicione em seu aplicativo (pasta Bin). Utilize o código abaixo para fazer o processo de conversão e exibição do PDF na tela:


using System;
using System.Web;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.html.simpleparser;


            // Captura ou atribui o HTML a ser convertido - no caso estou baixando de uma URL
            string html = new System.Net.WebClient().DownloadString("http://thiagomarcal.blogspot.com/");
            //string html = "Convertendo o HTML em PDF - Thiago Marçal";
            // Cria o documento aplicando o tamanho e margens
            Document documento = new Document(PageSize.A4, 80, 50, 30, 65);
            // Memory Stream para ser usado na conversão e emissão
            MemoryStream ms = new MemoryStream();
            // Inicializa o gravador
            PdfWriter writer = PdfWriter.GetInstance(documento, ms);
            // Lê o HTML e atribui
            StringReader conteudo = new StringReader(html);
            // Objeto de conversão do HTML
            HTMLWorker objeto = new HTMLWorker(documento);
            // Abre o documento
            documento.Open();
            // Aplica o parser para análise de conversão
            // Geralmente aqui ocasiona muitos erros - irei explicar no post
            objeto.Parse(conteudo);
            // Fecha o documento
            documento.Close();
            // Força o download do PDF gerado - se desejável você pode salvar em disco também
            Response.Clear();
            Response.AddHeader("content-disposition", "attachment; filename=Documento_HTML.pdf");
            Response.ContentType = "application/pdf";
            Response.Buffer = true;
            Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
            Response.OutputStream.Flush();
            Response.End();


Veja que a variável html eu atribuo o HTML que desejo converter. O seu conteúdo pode vir externamente ou posso atribuir um valor desejado.

Vamos aos problemas! Muitos vão encontrar erro quando o objeto estiver fazendo o parser do HTML e muitos irão falhar. Acontece que, devido à complexidade do HTML que estiver trabalhando, o componente não consegue converter para o formato adequado ao que ele usa internamente. Por exemplo, o TABLE do HTML que usamos é "meio" diferente do TABLE que o componente usa. Esse é um dos exemplos... Então prepara-se para fazer um tratamento adequado antes de fazer o parser. Eu sugiro o seguinte:
  1. Use expressão regular para validar seu HTML;
  2. Use expressão regular e/ou o HtmlAgilityPack para remover os JavaScripts;
  3. O conteúdo a ser convertido deve ser apenas o que está dentro do body;
  4. Imagens, CSS e links devem conter o caminho completo (exemplo: http://thiagomarcal.blogspot.com/imgs/logo.png ao invés de ../imgs/logo.png), etc.
Ou seja, quanto mais simplificado for seu HTML mais rápido e fácil será convertido em PDF. Uma observação bem clara é: nem sempre ficará 100% que o esperado.

Uma dica que pode ser usada (e um armengue, claro!) é fazer o seguinte:
  1. Gere um thumb (imagem) do HTML que deseja converter (saiba como gerar um thumb de um HTML nesse post) e salve em disco;
  2. Atribua a variável html com o conteúdo "<img src="http://thiagomarcal.blogspot.com/imgs/thumb.png" />";
  3. Coloque o width e height na tag IMG o tamanho desejado (pode ser até o tamanho do papel).
Pronto! O parser irá identificar apenas uma imagem no HTML e gerará o PDF com ela. Mole-mole...

Acompanhar rastreamento de pedido dos Correios com C#

Mais um artigo para quem trabalha com loja virtual... Essa funcionalidade é bem importante para visualizar o rastreamento de um determinado pedido. Ao invés de mandar apenas o link com o código para seu cliente, porque não enviar logo a tabela com os dados? Pois bem, é isso que iremos fazer! O código é bem simples, rápido e pode-se alterar para uma "infinidades" de formas afim de o colocar do jeito que deseja.

Abaixo temos um resumo do processo:

  1. Enviamos uma requisição GET com o número do rastreamento;
  2. Obtemos os dados de retorno (página completa);
  3. Capturamos apenas a tabela com os dados de rastreamento;
  4. Exibimos na tela.
Para capturar a apenas a tabela com os dados, pode-se fazer de várias formas (Expressão Regular, etc), mas preferi usar um componente que captura nós de um documento HTML, o HtmlAgilityPack. Baixe ele e o coloque na referência de seu projeto (Bin). Agora é fácil - utilize o código abaixo:

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using HtmlAgilityPack;

protected void Page_Load(object sender, EventArgs e)
    {

        // Aplica campos de parâmetros
        string codigo = "ES659170465BR";
        string parametros = "?P_COD_UNI=" + codigo + "&P_LINGUA=001&P_TIPO=001";
        // Cria o objeto de requisição
        WebRequest requisicao = WebRequest.Create("http://websro.correios.com.br/sro_bin/txect01$.QueryList" + parametros);
        // Realiza a requisição
        HttpWebResponse retorno = (HttpWebResponse)requisicao.GetResponse();
        // Lê o objeto e faz a atribuição à variável
        StreamReader stream = new StreamReader(retorno.GetResponseStream(), Encoding.GetEncoding("ISO-8859-1"));
        string dados = stream.ReadToEnd();
        // Transforma em um documento HTML - HtmlAgilityPack
        HtmlDocument html = new HtmlDocument();
        html.LoadHtml(dados);
        // Captura apenas a tabela contendo os dados do envio
        HtmlNode tabela = html.DocumentNode.SelectSingleNode("//table");
        if (tabela != null)
        {
            // Nesse caso você pode capturar as colunas e linhas e trabalhar conforme desejar
            // Apenas fiz o loop para remover a formatação inicial da tabela
            string htmlTable = "<table>";
            // Extrai as linhas da tabela
            foreach (HtmlNode linha in tabela.SelectNodes("//tr"))
                htmlTable += "<tr>" + linha.InnerHtml + "</tr>";
            htmlTable += "</table>";
            // Exibe a tabela de rastreamento
            Response.Write("O horário não indica quando a situação ocorreu, mas sim quando os dados foram recebidos pelo sistema, exceto no caso do <b>SEDEX 10 e do SEDEX Hoje, </b>em que ele  representa o horário real da entrega.<br><br>" + htmlTable);
        }
        else
            Response.Write("O nosso sistema não possui dados sobre o objeto informado. Se o objeto foi postado recentemente, é natural que seus rastros não tenham ingressado no sistema, nesse caso, por favor, tente novamente mais tarde. Adicionalmente, verifique se o código digitado está correto: " + codigo);
        // Finaliza objetos
        stream.Close();
        retorno.Close();

    }

No caso peguei o HTML da tabela contendo os dados e exibi de vez na tela. Poderia tratá-la de várias formas e uma delas poderia ser transformando-a em um DataTable ou DataSet para alguma manipulação posterior. Veja nesse link aqui como fazer isso.

Os Correios não dispõe de Web-Service para esse tipo de consulta. Olhando na net, encontrei dois artigos: um de Manoel Campos e outro de Carlos Ferrari onde ambos dispõe de Web-Services (em PHP - mas pode ser consumido pelo ASP.NET) para esse tipo de consulta. Quem não quiser implementar e apenas consumir, podem usá-los que chega o mesmo objetivo.

Artigo bem fácil e rápido! Espero ter ajudado...

Redimensionar imagens com alta qualidade em ASP.NET

O código que irei mostrar nem precisarei de muita explicação. Você encontra a rodo aí pela internet... Contudo, esse tem um pequeno diferencial: misturei o código "pescado" da net com o incremento de Glenn Jones. O redimensionamento consiste em colocar no SRC da imagem o Generic Handler que faz todo o processo e gera a imagem. Ou seja, crie um arquivo ImageResize.ashx e coloque o seguinte código abaixo:


using System;
using System.Drawing;
using System.IO;
using System.Web;


public class ImagemHandler : IHttpHandler {
    
    public void ProcessRequest (HttpContext context) {
        
        // Recupera os parâmetros passados pela página
        string strSrcImagemOriginal = "../upload/" + context.Request["img"].ToString();
        string strAlturaImagemRedimensionar = "";
        string strLarguraImagemRedimensionar = context.Request["w"].ToString();        
        
        // Cria temporariamnte a imagem
        System.Drawing.Image imagemTemp = System.Drawing.Image.FromFile(context.Server.MapPath(strSrcImagemOriginal));
        
        // Variáveis contendo o tamanho
        int srcWidth = imagemTemp.Width;
        int srcHeight = imagemTemp.Height;
        int thumbHeight;
        int thumbWidth;
        
        // Redimensiona a largura de forma proporcional
        if (context.Request["w"] != null)
        {
            thumbWidth = int.Parse(strLarguraImagemRedimensionar);
            thumbHeight = (int)(thumbWidth * imagemTemp.Height) / imagemTemp.Width;
        }
        else
        {
            thumbWidth = imagemTemp.Width;
            thumbHeight = imagemTemp.Height;
        }
        
        // Redimensiona a altura
        if (context.Request["h"] != null)
        {
            strAlturaImagemRedimensionar = context.Request["h"].ToString();
            thumbHeight = int.Parse(strAlturaImagemRedimensionar);
            // Faz o rateio para o redimensionamento proporcional
            // Assim a altura e a largura nunca irão ultrapassar o tamanho limite
            double widthRatio = (double)imagemTemp.Width / (double)thumbWidth;
            double heightRatio = (double)imagemTemp.Height / (double)thumbHeight;
            double ratio = Math.Max(widthRatio, heightRatio);
            thumbWidth = (int)(imagemTemp.Width / ratio);
            thumbHeight = (int)(imagemTemp.Height / ratio);
        }
        imagemTemp.Dispose();
        
        // Envia para a memória o objeto a ser trabalhado bem como o novo objeto
        Stream objStream = new StreamReader(context.Server.MapPath(strSrcImagemOriginal)).BaseStream;
        BinaryReader objBinaryReader = new BinaryReader(objStream);
        int i = (int)objStream.Length;
        byte[] arrBytes = objBinaryReader.ReadBytes(i);
        System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(arrBytes);
        System.Drawing.Image image = System.Drawing.Image.FromStream(memoryStream);
        System.Drawing.Image thumbnail = new Bitmap(thumbWidth, thumbHeight);
        System.Drawing.Graphics graphic = System.Drawing.Graphics.FromImage(thumbnail);
        
        // Melhoria da nova imagem
        graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
        graphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
        graphic.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
        graphic.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
        
        // Desenha a nova imagem
        graphic.DrawImage(image, 0, 0, thumbWidth, thumbHeight);


        // Aplica a codificação necessária
        System.Drawing.Imaging.ImageCodecInfo[] info = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
        System.Drawing.Imaging.EncoderParameters encoderParameters;
        encoderParameters = new System.Drawing.Imaging.EncoderParameters(1);
        encoderParameters.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
        
        // Exibe a imagem em forma de JPG
        context.Response.ContentType = "image/jpeg";
        thumbnail.Save(context.Response.OutputStream, info[1], encoderParameters);


    }


}

Mais dado do que isso é só de mão beijada!