Somente pelo IIS é possível converter uma pasta em aplicação? Mais ou menos. Na versão 7 do IIS já dispõe de módulos que simplificam o processo de criação de site, diretório virtual, pools de aplicação e as aplicações em si. Nesse artigo mostrarei bem rápido como converter uma pasta em uma aplicação.
Crie sua aplicação e adicione, como referência, o binário Microsoft.Web.Administration.dll que fica na pasta C:\Windows\System32\inetsrv . Agora adicione o seguinte código:
using Microsoft.Web.Administration;
private void CriaEntradaIIS(string diretorio)
{
try
{
// Cria a pasta do site
if (!Directory.Exists(diretorio))
Directory.CreateDirectory(diretorio);
// Servidor de Aplicação
ServerManager sm = new ServerManager();
// Captura o site raiz onde irá adicionar a aplicação
Site st = sm.Sites["Default Web Site"];
// Cria a aplicação no diretório criado apontando o caminho, ex: aplicacao
Application app = st.Applications.Add("/aplicacao", diretorio);
app.ApplicationPoolName = "ASP.NET v4.0";
sm.CommitChanges();
// Libera
sm.Dispose();
}
catch (Exception erro)
{
return;
}
}
Se tentar executar dará erro... Antes dê permissão total ao grupo Serviço de Rede (Network Service) à pasta C:\Windows\System32\inetsrv\config . Agora sim irá criar. Para mais exemplos veja nesse post aqui.
Mostrando postagens com marcador dll. Mostrar todas as postagens
Mostrando postagens com marcador dll. Mostrar todas as postagens
Convertendo uma pasta em aplicação no IIS via código (C#)
Postado por
Thiago Marçal
on segunda-feira, 28 de novembro de 2011
/
Marcadores:
application,
diretório virtual,
dll,
iis,
site,
windows
/
Comments: (3)
Converter PDF em Imagem em C# com GhostScript
Postado por
Thiago Marçal
on terça-feira, 22 de novembro de 2011
/
Marcadores:
componentes,
dll,
ghostscript,
imagem,
pdf,
upload,
winform
/
Comments: (1)
Esse é um artigo bem old, mas que muita gente me enviou e-mails pedindo como fazer isso. Então criei um artigo bem resumido baseado no de Lord TaGoH. Primeiramente, você precisa ter a DLL do GhostScript em seu projeto: ou você instala ou pega de alguém que já tenha instalado. O arquivo que me refiro é o gsdll32.dll. Obs: a conversão só funciona para as versões mais recentes então pegue alguma a partir da versão 9 como garantia.
Lembra do meu último post de scaneamento? Adicionei um botão de anexar um PDF e converter em imagem, então irei aproveitar a mesma aplicação adicionando essa funcionalidade. Copie a DLL para seu projeto e, em Propriedades, deixe configurado o atributo Copiar sempre para quando for compilá-la caso seja um Windows Form. Se for um Web Form, adicione em algum local onde a classe conversora possa encontrá-la.
Na página do CodeProject dispõe de uma classe (binária) já pronta para uso uso da DLL chamada de PdfToImage. Então você podem baixar de lá ou aqui. Baixado a DLL, você pode adicionar como referência ao seu projeto/página. Agora é só código...
using PdfToImage;
// Objeto de conversão
PDFConvert converter = new PDFConvert();
// Arquivo PDF selecionado de um OpenFileDialog
string arquivo = FileUploadSelect.FileName;
// Local de saída do arquivo convertido
string output = _directoryForImages + "LJ_" + _loja + "_Scan_" + DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss") + ".jpg";
// Configurações de conversão
converter.OutputToMultipleFile = false;
converter.TextAlphaBit = 4;
converter.FirstPageToConvert = 1;
converter.LastPageToConvert = 1;
converter.FitPage = false;
converter.JPEGQuality = 10;
converter.OutputFormat = "png16m";
// Faz a conversão e retorna true se estiver tudo OK
bool resultado = converter.Convert(arquivo, output);
Pronto! Mais fácil do que isso impossível. Fique atento às configurações de conversão, senão não funciona.
Lembra do meu último post de scaneamento? Adicionei um botão de anexar um PDF e converter em imagem, então irei aproveitar a mesma aplicação adicionando essa funcionalidade. Copie a DLL para seu projeto e, em Propriedades, deixe configurado o atributo Copiar sempre para quando for compilá-la caso seja um Windows Form. Se for um Web Form, adicione em algum local onde a classe conversora possa encontrá-la.
Na página do CodeProject dispõe de uma classe (binária) já pronta para uso uso da DLL chamada de PdfToImage. Então você podem baixar de lá ou aqui. Baixado a DLL, você pode adicionar como referência ao seu projeto/página. Agora é só código...
using PdfToImage;
// Objeto de conversão
PDFConvert converter = new PDFConvert();
// Arquivo PDF selecionado de um OpenFileDialog
string arquivo = FileUploadSelect.FileName;
// Local de saída do arquivo convertido
string output = _directoryForImages + "LJ_" + _loja + "_Scan_" + DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss") + ".jpg";
// Configurações de conversão
converter.OutputToMultipleFile = false;
converter.TextAlphaBit = 4;
converter.FirstPageToConvert = 1;
converter.LastPageToConvert = 1;
converter.FitPage = false;
converter.JPEGQuality = 10;
converter.OutputFormat = "png16m";
// Faz a conversão e retorna true se estiver tudo OK
bool resultado = converter.Convert(arquivo, output);
Pronto! Mais fácil do que isso impossível. Fique atento às configurações de conversão, senão não funciona.
Scanear um documento com C#
Um dos melhores componentes de scaneamento que já utilizei é o da VintaSoft. Ele não é free, mas pode ser utilizado normalmente. O único empecilho é que, para cada scan que fizer, ele irá solicitar que clique em Evaluate. Quem comprar, vale a pena pois é muito bom e seu suporte sempre está a disposição. Chega de elogios e vamos ao que interessa.
O componente permite tanto utilizar em Windows Form quando Web Form e no site há todos os exemplos necessários. Baixe o componente e instale. Para nosso exemplo, trabalharemos com um Windows Form. Fiz uma pequena aplicação de scanear nota fiscal.
Vá na pasta de instalação do componente, copie o arquivo Vintasoft.Twain.dll para sua aplicação e adicione como referência. No Code-Behind do formulário a ser trabalhado, adicione o seguinte código para inicializar o componente:
using Vintasoft.Twain;
// Carrega o gerenciador de dispositivo
DeviceManager _deviceManager = new DeviceManager();
Device _device;
// Avalia se é um dispositivo útil
if (!_deviceManager.IsTwainAvailable)
{
MessageBox.Show("Não é um dispositivo TWAIN!", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
try
{
// Abre o gerenciador de dispositivo
_deviceManager.Open();
// Seta o dispositivo corrente
_device = _deviceManager.Devices.Current;
lblDipositivo.Text = _deviceManager.Devices.Current.Info.ProductName;
}
catch (TwainDeviceManagerException ex)
{
MessageBox.Show(ex.Message, "Gerenciador de Dispositivos");
return;
}
Agora, ao clicar no botão Scannear, adicionamos o seguinte método:
private void btnScanear_Click(object sender, EventArgs e)
{
try
{
// Seta as configurações
_device.TransferMode = TransferMode.File;
try
{
_device.ShowUI = false;
_device.ShowIndicators = false;
_device.DisableAfterAcquire = true;
}
catch { }
// Abre o dispositivo
_device.Open();
// Propriedades do scaneamento
try
{
_device.UnitOfMeasure = UnitOfMeasure.Inches;
_device.Resolution = new Resolution(float.Parse(resolucaoX.SelectedItem.ToString()), float.Parse(resolucaoY.SelectedItem.ToString()));
}
catch { }
// Informação sobre o arquivo
_arquivo = "LJ_" + _loja + "_Scan_" + DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss") + ".jpg";
_device.FileName = _directoryForImages + _arquivo;
//_device.FileFormat = TwainImageFileFormat.Jpeg;
// Captura a imagem
AcquireModalState acquireModalState = AcquireModalState.None;
do
{
acquireModalState = _device.AcquireModal();
switch (acquireModalState)
{
case AcquireModalState.ImageAcquired:
_device.FileName = _directoryForImages + _arquivo;
//_device.FileFormat = TwainImageFileFormat.Jpeg;
break;
case AcquireModalState.ScanCompleted:
CloseDevice();
break;
case AcquireModalState.ScanCanceled:
CloseDevice();
break;
case AcquireModalState.ScanFailed:
CloseDevice();
break;
case AcquireModalState.UserInterfaceClosed:
CloseDevice();
break;
}
}
while (acquireModalState != AcquireModalState.None);
}
catch (TwainException ex)
{
MessageBox.Show(ex.Message + " - " + ex.StackTrace, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
E outros métodos são necessários adicionar ao form, como:
/// Fecha o dispositivo e a gerência
private void CloseDeviceAndDeviceManager()
{
// Verifica de há dispositivo
if (_device != null)
{
if (_device.State != DeviceState.Closed)
_device.Close();
}
// Fecha a gerência
if (_deviceManager.State != DeviceManagerState.Closed)
_deviceManager.Close();
}
/// Fecha o dispositivo
private void CloseDevice()
{
// Desabilita o serviço
if (_device.State == DeviceState.Enabled)
{
if (!_device.ShowUI)
_device.Disable();
}
// Fecha
if (_device.State == DeviceState.Opened)
_device.Close();
}
/// Ao fechar o formulário, libera o uso
private void Scan_FormClosing(object sender, FormClosingEventArgs e)
{
if (_device != null)
{
// Verifica se está em uso
if (_device.State == DeviceState.Transferring ||
_device.State == DeviceState.TransferReady)
{
// Envia a solicitação de cancelamento
_device.CancelTransfer();
// Aguarda finalizar
e.Cancel = true;
MessageBox.Show("O dispositivo está em uso! Aguarde alguns instantes enquanto é solicitado a liberação do scanner.", "Informação");
return;
}
}
// Fecha o dispositivo e a gerência
CloseDeviceAndDeviceManager();
}
Pronto! O scaneamento é realizado e é gerado um arquivo JPG. Reparem que está comentado o atributo _device.FileFormat porque nem todo scanner dá a possibilidade de configuração. Alguns aceitam e outros não. Se utilizar alguma configuração que o scanner não suporta, deve aparecer a mensagem: "Failed to get/get to capability". Então você precisa deixar apenas as configurações que o scanner suporte.
Bons scans!
O componente permite tanto utilizar em Windows Form quando Web Form e no site há todos os exemplos necessários. Baixe o componente e instale. Para nosso exemplo, trabalharemos com um Windows Form. Fiz uma pequena aplicação de scanear nota fiscal.
Vá na pasta de instalação do componente, copie o arquivo Vintasoft.Twain.dll para sua aplicação e adicione como referência. No Code-Behind do formulário a ser trabalhado, adicione o seguinte código para inicializar o componente:
using Vintasoft.Twain;
// Carrega o gerenciador de dispositivo
DeviceManager _deviceManager = new DeviceManager();
Device _device;
// Avalia se é um dispositivo útil
if (!_deviceManager.IsTwainAvailable)
{
MessageBox.Show("Não é um dispositivo TWAIN!", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
try
{
// Abre o gerenciador de dispositivo
_deviceManager.Open();
// Seta o dispositivo corrente
_device = _deviceManager.Devices.Current;
lblDipositivo.Text = _deviceManager.Devices.Current.Info.ProductName;
}
catch (TwainDeviceManagerException ex)
{
MessageBox.Show(ex.Message, "Gerenciador de Dispositivos");
return;
}
Agora, ao clicar no botão Scannear, adicionamos o seguinte método:
private void btnScanear_Click(object sender, EventArgs e)
{
try
{
// Seta as configurações
_device.TransferMode = TransferMode.File;
try
{
_device.ShowUI = false;
_device.ShowIndicators = false;
_device.DisableAfterAcquire = true;
}
catch { }
// Abre o dispositivo
_device.Open();
// Propriedades do scaneamento
try
{
_device.UnitOfMeasure = UnitOfMeasure.Inches;
_device.Resolution = new Resolution(float.Parse(resolucaoX.SelectedItem.ToString()), float.Parse(resolucaoY.SelectedItem.ToString()));
}
catch { }
// Informação sobre o arquivo
_arquivo = "LJ_" + _loja + "_Scan_" + DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss") + ".jpg";
_device.FileName = _directoryForImages + _arquivo;
//_device.FileFormat = TwainImageFileFormat.Jpeg;
// Captura a imagem
AcquireModalState acquireModalState = AcquireModalState.None;
do
{
acquireModalState = _device.AcquireModal();
switch (acquireModalState)
{
case AcquireModalState.ImageAcquired:
_device.FileName = _directoryForImages + _arquivo;
//_device.FileFormat = TwainImageFileFormat.Jpeg;
break;
case AcquireModalState.ScanCompleted:
CloseDevice();
break;
case AcquireModalState.ScanCanceled:
CloseDevice();
break;
case AcquireModalState.ScanFailed:
CloseDevice();
break;
case AcquireModalState.UserInterfaceClosed:
CloseDevice();
break;
}
}
while (acquireModalState != AcquireModalState.None);
}
catch (TwainException ex)
{
MessageBox.Show(ex.Message + " - " + ex.StackTrace, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
E outros métodos são necessários adicionar ao form, como:
private void CloseDeviceAndDeviceManager()
{
// Verifica de há dispositivo
if (_device != null)
{
if (_device.State != DeviceState.Closed)
_device.Close();
}
// Fecha a gerência
if (_deviceManager.State != DeviceManagerState.Closed)
_deviceManager.Close();
}
private void CloseDevice()
{
// Desabilita o serviço
if (_device.State == DeviceState.Enabled)
{
if (!_device.ShowUI)
_device.Disable();
}
// Fecha
if (_device.State == DeviceState.Opened)
_device.Close();
}
private void Scan_FormClosing(object sender, FormClosingEventArgs e)
{
if (_device != null)
{
// Verifica se está em uso
if (_device.State == DeviceState.Transferring ||
_device.State == DeviceState.TransferReady)
{
// Envia a solicitação de cancelamento
_device.CancelTransfer();
// Aguarda finalizar
e.Cancel = true;
MessageBox.Show("O dispositivo está em uso! Aguarde alguns instantes enquanto é solicitado a liberação do scanner.", "Informação");
return;
}
}
// Fecha o dispositivo e a gerência
CloseDeviceAndDeviceManager();
}
Pronto! O scaneamento é realizado e é gerado um arquivo JPG. Reparem que está comentado o atributo _device.FileFormat porque nem todo scanner dá a possibilidade de configuração. Alguns aceitam e outros não. Se utilizar alguma configuração que o scanner não suporta, deve aparecer a mensagem: "Failed to get/get to capability". Então você precisa deixar apenas as configurações que o scanner suporte.
Bons scans!
Mega Post de Erros
Postado por
Thiago Marçal
on sábado, 9 de abril de 2011
/
Marcadores:
banco de dados,
cloud server,
crystal reports,
dll,
erros,
iis,
locaweb,
plesk,
sql server,
windows
/
Comments: (0)
Lidar com erros é algo realmente muito chato... Chato demais! Esses dias fui convocado para fazer um certo trabalho de migração entre servidores. Um desses servidores era um Cloud Server Pro da Locaweb. Em muitos posts que aqui escrevi tem um pouco retratando sobre a Locaweb. Trabalho e já trabalhei muito com ela e sei de todos os seus passos e "artimanhas" de atendimento... O antigo Cloud Server foi até tranquilo de trabalhar, mas esse novo... Vamos aos problemas!
Uma dica que dou sempre quando alguém quer contratar um servidor: leiam muito sobre os prós e contras. Os prós vejam no próprio site do prestador, os contras vejam nos relatos de usuários. No post a seguir não estou jogando a Locaweb contra a parede, apenas estou expondo erros que podem ser sanados de forma fácil mas que burocraticamente é jogado para o cliente se virar (nos 30!).
Nesse Cloud Server vem embutido o Plesk. Em poucas palavras serve para gerenciar a hospedagem através de uma interface web. É uma boa ferramenta de gerência, tem tudo para gerenciar sua hospedagem. Só que esse demais gera ocupação demais (redundância) de espaço em disco. Dos 50 Gb que você contrata, 40Gb é para o sistema operacional e 10Gb para seus arquivos. Sendo que dos 10Gb é para todos os seus arquivos, e-mails, banco de dados, etc. Ou seja, apenas usufrui dos 10Gb um pouco menos que 9Gb e olhe lá.
Bem, dizem que vem tudo preparado e instalado para usar... Verdade até certa parte! Quem está usando e é iniciante vai ver que é mil maravilhas. Dá para fazer o básico de tudo. O problema vem a seguir...
Um cliente contratou o Cloud Server gerenciado pelo cliente (ou seja, sobrou para o usuário final) e me passou para configurar e deixar no ponto de uso fazendo toda a migração e instalação. Em um passe de mágica surgem os problemas...
Os bancos de dados que vem são o MS SQL Server 2008 e o MySQL. Não há interface para dump e recovery das bases forçando a usar o Plesk para isso, mas não queria. Onde está o Management Studio 2008? Onde está o MySQL Workbench? Como vou fazer para migrar as bases? Gerar script de bancos gigantes? Nem pensar! Preciso instalar!
Mas como instalar esses aplicativos? Se fazer download, gera tráfego. Se pedir para a Locaweb tem que pagar e se pedir, de graça, não instala! Lembrando que esses aplicativos, no mínimo, são gratuitos e deveriam estar em uma zona em que os usuários pudessem obtê-los de forma fácil e sem cobrança. Pois bem, feito o download, hora de instalar. Abrindo o executável (lembrando que tem que ser a da versão 64bits) dá aviso de incompatibilidade. É preciso instalar o Service Pack 1 do SQL Server 2008 (mais tráfego). Baixado o SP1 é preciso instalá-lo. Tranquilo e instalado sem problemas. Hora de instalar o Management Studio...
Ao tentar abrir, outro problema?!?! É preciso do Framework 3.5! Incrivel... No Cloud Server vem instalado a versão 2.0 e 4.0 do Framework ASP.NET mas não tem a 3.5 ativado. Menos mal, porque no Windows Server 2008 é nativo, basta ativar. Realize os seguintes passos (retirado do Wiki):
Agora sim, tudo pronto! Vamos instalar o Management Studio. Clica no instalador e... Erro! Caramba... de novo!
TITLE: SQL Server Setup failure.
-------------------------------
SQL Server Setup has encountered the following error:
Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
A dica é: feche o Windows Explorer! Por algum motivo, a instalação do Management Studio não inicia quando o Windows Explorer estiver em aberto. Copie para a Área de Trabalho e abra o instalador... Agora sim! Depois de tanta malemolência pelo menos iniciemos a instalação. Para quem tem dúvidas e um passo-a-passo bem explicativo de como instalar o Management Studio, acesse aqui o post de Marcos dell Antonio. Há uma dica bem interessante que pode confundir o usuário na hora da instalação. Terminado a instalação, menos um item da lista de afazeres.
Consegui conectar ao SQL Server local, criei as bases, usuários, fiz restores, configurei o backup, providenciei tudo o que tinha que fazer onde o Plesk jamais pensaria em um dia ser. Agora o principal, testar um website. Publiquei o site no IIS e abri o navegador para visualizar. Erro!
Could not load type 'System.ServiceModel.Activation.HttpModule' from assembly 'System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
Sabe o porquê disso? Eu instalei o ASP.NET 3.5 depois que eu já tinha a versão 4.0 instalada por causa do Management Studio então gerou conflito nas DLL's. Para resolver, faça o seguinte:
Agora vamos testar! Abri o navegador e digitei o endereço e... Mais erro!
There is a duplicate 'system.web.extensions/scripting/scriptResourceHandler' section defined
Mais conflitos! Se você tiver outra versão do System.Web.Extensions instalado, devido ao ASP.NET AJAX por exemplo, a versão que está no GAC do sistema difere da que você quer chamar ocorrendo ambiguidade. O correto seria alterar os assemblys mas como isso é muito trabalhoso e pode acontecer algum imprevisto para aqueles que não sabem manuseá-las, então aconselho o seguinte: remova toda a sectionGroup do seu web.config ou comente-as:
<!--
<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
<sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere" />
<section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
<section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
</sectionGroup>
</sectionGroup>
</sectionGroup>
-->
No caso comentei o sectionGroup do System.Web.Extension que pode estar na versão 1.0, 2.0 ou 3.5 que for.
Agora vamos lá! De pés juntos e mãos dadas: Abre o navegador e... e... e... Funcionou! Depois de um árduo trabalho aparentemente tudo estava normal. Vamos testar outros sites e... e... e... Mais erros!
Quem ainda não está acostumado a trabalhar com Windows Server 2008 e IIS 7 terá que aprender muito sobre permissões e tratamento de erros. Incontestavelmente a tela do erro 500 irá aparecer e muito se sua aplicação não estiver configurada adequadamente para o IIS 7. Nem sempre a mesma aplicação que está no IIS 6 irá funcionar no IIS 7. Então eis que surge a tela do Erro 500 Erro Interno do Servidor ou Error 500 Internal Server Error:
Ou então:
Dá para descobrir o que é? Vou dar a dica: revise seu web.config. "Ah, mas está tudo certo, não sei porque não funciona...". Engano, está errado. Já disse que o IIS 7 é chato, muito chato. O parser dele é muito minucioso e se não estiver nos padrões vai dar problema.
Se você não sabe utilizar bem o IIS e tem medo de alterar uma coisinha ali e outra acolá vou dar a maior dica: saia abrindo cada opção do painel da aplicação até que uma delas acuse um erro de configuração.
Por exemplo, abra o item Documento Padrão. Se ele estiver configurado corretamente então abrirá a próxima tela normalmente. Se tiver algum erro, aparecerá um alerta. Então no web.config você deve corrigir a sessão correspondente. Ficou claro? Saia clicando um a um até que um deles se denuncie podendo então fazer a correção.
O que ocorreu comigo foi que um site que estava no IIS 6 podia colocar a mesma página (index.aspx) como padrão, duas vezes, e não tinha problema. Quando foi para o IIS 7, na qual estava herdando a configuração pai, e foi adicionar a página index.aspx como padrão novamente, ele dava erro e não sabia porquê. Então removi a entrada do web.config e funcionou. Desabilitar a mensagem de erro amigável no navegador vai funcionar (encontrar o erro)? Não. Desabilitar as páginas de erros personalizáveis do IIS vai funcionar (encontrar o erro)? Talvez ou não. Depende muito do ambiente que está configurado e quem está manipulando.
Pronto! Mais um problema solucionado... Vamos testar outro site e... e... e... Erro! Agora aconteceu um erro 404. Mas como? Erro 404 de página não encontrada mas se o caminho está lá? Incrivelmente no IIS do Cloud Server possuem dois Applications Pools do Plesk (e mais outros nativos): Plesk(default)(2.0) e Plesk(default)(4.0). O pool do 2.0 quase nem sempre funciona. E um comportamento anormal é que se você tem um site pai em 2.0 e um filho em 2.0 às vezes pára de funcionar. O "correto" é ter um pai 2.0 ou 4.0 com filho sempre 4.0. Estranho? Pode crer! E onde está o pool do 3.5? Tem que criar na mão mesmo.
Nota: Se você reiniciar o IIS o Plesk pára de vez e não volta:
Você terá que iniciá-lo manualmente. Mas antes terá que iniciar seu pool também (que é muito suspeito):
Ajeitado uma coisinha ali, outra aqui, vamos testar mais algumas coisas e... e... e... Quase tudo certo. Em questão de funcionalidade (que deveria ser) está quase tudo certo a não ser o funcionamento do bom e velho Crystal Reports. Quem já leu o post de erros do Crystal aqui e aqui nos deparamos com o erro:
O inicializador de tipo de 'CrystalDecisions.CrystalReports.Engine.ReportDocument' acionou uma exceção
ou
The type initializer for 'CrystalDecisions.CrystalReports.Engine.ReportDocument' threw an exception
Cuidado! Esse não é o descritivo do erro. Só com isso não dá para saber o motivo. Faça o debug, log, exibição da pilha ou na própria tela exiba o erro (sem ter AJAX) que teremos o erro completo. No link dos dois posts anteriores que fiz explica o problema do Crystal na plataforma 64bits e como pode resolver. Só que o problema no meu caso era permissão.
Server Error in '/virtual_directory_name' Application.
Error in File UNKNOWN.RPT:
The request could not be submitted for background processing.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Runtime.InteropServices.COMException: Error in File UNKNOWN.RPT: The request could not be submitted for background processing.
Os usuários listados abaixo, não tinham permissão na execução de scripts DCOM e gravação em algumas pastas (principalmente as que estão na unidade C):
Esses são os usuários que devem ter privilégio (descritos abaixo) nas pastas listadas abaixo:
Obs: Para alguns servidores é preciso aplicar o Replace permission entries on all child objects nessas pastas.
Lembrando de reiniciar o IIS e/ou o servidor para recarregar as configurações.
Se estiver trabalhando com Windows Service ou Windows Form e ocorra o erro:
System.IO.FileNotFoundException: Retrieving the COM class factory for component with CLSID {5FF57840-5172-4482-9CA3-541C7878AE0F} failed due to the following error: 8007007e
Basta compilar sua aplicação em x86.
E agora, tudo certo? Até o momento sim. Porque não dizer que está tudo OK? Depois de ter ocorrido todos esses problemas, fica-se receoso com o futuro. Pode ser que ocorra outro problema posteriormente? Sim e irá.
Conforme disse anteriormente, o post não é para dizer mal sobre a Locaweb e/ou Plesk. Acho que eles prestam um serviço adequado para o nível nacional (até uso) contudo são coisas que acontecem que simplesmente poderiam ser sanadas antes de jogar o pepino para o cliente. Se você tiver algum problema desses e sua gerência for pelo cliente, nem adianta pedir que eles vão lhe informar: "o gerenciamento é por conta do cliente e não nos responsabilizamos" ou "a ferramenta (Plesk) é terceirizada e não prestamos suporte.". Enfim, espero que o post ajude a você, cliente e usuário, a corrigir seus problemas/pepinos que ocorrerem. Isso me lembra quando lançou o plug-and-play... a velha piadinha do plug-and-pray (ligar e rezar) não some da cabeça quando ocorre esse tipo de problema. Porque será?
Uma dica que dou sempre quando alguém quer contratar um servidor: leiam muito sobre os prós e contras. Os prós vejam no próprio site do prestador, os contras vejam nos relatos de usuários. No post a seguir não estou jogando a Locaweb contra a parede, apenas estou expondo erros que podem ser sanados de forma fácil mas que burocraticamente é jogado para o cliente se virar (nos 30!).
Nesse Cloud Server vem embutido o Plesk. Em poucas palavras serve para gerenciar a hospedagem através de uma interface web. É uma boa ferramenta de gerência, tem tudo para gerenciar sua hospedagem. Só que esse demais gera ocupação demais (redundância) de espaço em disco. Dos 50 Gb que você contrata, 40Gb é para o sistema operacional e 10Gb para seus arquivos. Sendo que dos 10Gb é para todos os seus arquivos, e-mails, banco de dados, etc. Ou seja, apenas usufrui dos 10Gb um pouco menos que 9Gb e olhe lá.
Bem, dizem que vem tudo preparado e instalado para usar... Verdade até certa parte! Quem está usando e é iniciante vai ver que é mil maravilhas. Dá para fazer o básico de tudo. O problema vem a seguir...
Um cliente contratou o Cloud Server gerenciado pelo cliente (ou seja, sobrou para o usuário final) e me passou para configurar e deixar no ponto de uso fazendo toda a migração e instalação. Em um passe de mágica surgem os problemas...
Os bancos de dados que vem são o MS SQL Server 2008 e o MySQL. Não há interface para dump e recovery das bases forçando a usar o Plesk para isso, mas não queria. Onde está o Management Studio 2008? Onde está o MySQL Workbench? Como vou fazer para migrar as bases? Gerar script de bancos gigantes? Nem pensar! Preciso instalar!
Mas como instalar esses aplicativos? Se fazer download, gera tráfego. Se pedir para a Locaweb tem que pagar e se pedir, de graça, não instala! Lembrando que esses aplicativos, no mínimo, são gratuitos e deveriam estar em uma zona em que os usuários pudessem obtê-los de forma fácil e sem cobrança. Pois bem, feito o download, hora de instalar. Abrindo o executável (lembrando que tem que ser a da versão 64bits) dá aviso de incompatibilidade. É preciso instalar o Service Pack 1 do SQL Server 2008 (mais tráfego). Baixado o SP1 é preciso instalá-lo. Tranquilo e instalado sem problemas. Hora de instalar o Management Studio...
Ao tentar abrir, outro problema?!?! É preciso do Framework 3.5! Incrivel... No Cloud Server vem instalado a versão 2.0 e 4.0 do Framework ASP.NET mas não tem a 3.5 ativado. Menos mal, porque no Windows Server 2008 é nativo, basta ativar. Realize os seguintes passos (retirado do Wiki):
- Clique em Start, Administrative Tools e selecione Server Manager;
- Na interface, clique em Features e clique em Add Features;
- Selecione a primeira opção .NET Framework 3.5.1 Features e adicione todos seus dependentes;
- Conclua a instalação do Framework.
Agora sim, tudo pronto! Vamos instalar o Management Studio. Clica no instalador e... Erro! Caramba... de novo!
TITLE: SQL Server Setup failure.
-------------------------------
SQL Server Setup has encountered the following error:
Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
A dica é: feche o Windows Explorer! Por algum motivo, a instalação do Management Studio não inicia quando o Windows Explorer estiver em aberto. Copie para a Área de Trabalho e abra o instalador... Agora sim! Depois de tanta malemolência pelo menos iniciemos a instalação. Para quem tem dúvidas e um passo-a-passo bem explicativo de como instalar o Management Studio, acesse aqui o post de Marcos dell Antonio. Há uma dica bem interessante que pode confundir o usuário na hora da instalação. Terminado a instalação, menos um item da lista de afazeres.
Consegui conectar ao SQL Server local, criei as bases, usuários, fiz restores, configurei o backup, providenciei tudo o que tinha que fazer onde o Plesk jamais pensaria em um dia ser. Agora o principal, testar um website. Publiquei o site no IIS e abri o navegador para visualizar. Erro!
Could not load type 'System.ServiceModel.Activation.HttpModule' from assembly 'System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
Sabe o porquê disso? Eu instalei o ASP.NET 3.5 depois que eu já tinha a versão 4.0 instalada por causa do Management Studio então gerou conflito nas DLL's. Para resolver, faça o seguinte:
- Vá para a pasta C:\Windows\Microsoft.NET\Framework64\v4.0.30319;
- Execute o comando aspnet_regiis.exe -iru
Agora vamos testar! Abri o navegador e digitei o endereço e... Mais erro!
There is a duplicate 'system.web.extensions/scripting/scriptResourceHandler' section defined
Mais conflitos! Se você tiver outra versão do System.Web.Extensions instalado, devido ao ASP.NET AJAX por exemplo, a versão que está no GAC do sistema difere da que você quer chamar ocorrendo ambiguidade. O correto seria alterar os assemblys mas como isso é muito trabalhoso e pode acontecer algum imprevisto para aqueles que não sabem manuseá-las, então aconselho o seguinte: remova toda a sectionGroup do seu web.config ou comente-as:
<!--
<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
<sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere" />
<section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
<section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
</sectionGroup>
</sectionGroup>
</sectionGroup>
-->
No caso comentei o sectionGroup do System.Web.Extension que pode estar na versão 1.0, 2.0 ou 3.5 que for.
Agora vamos lá! De pés juntos e mãos dadas: Abre o navegador e... e... e... Funcionou! Depois de um árduo trabalho aparentemente tudo estava normal. Vamos testar outros sites e... e... e... Mais erros!
Quem ainda não está acostumado a trabalhar com Windows Server 2008 e IIS 7 terá que aprender muito sobre permissões e tratamento de erros. Incontestavelmente a tela do erro 500 irá aparecer e muito se sua aplicação não estiver configurada adequadamente para o IIS 7. Nem sempre a mesma aplicação que está no IIS 6 irá funcionar no IIS 7. Então eis que surge a tela do Erro 500 Erro Interno do Servidor ou Error 500 Internal Server Error:
Ou então:
Dá para descobrir o que é? Vou dar a dica: revise seu web.config. "Ah, mas está tudo certo, não sei porque não funciona...". Engano, está errado. Já disse que o IIS 7 é chato, muito chato. O parser dele é muito minucioso e se não estiver nos padrões vai dar problema.
Se você não sabe utilizar bem o IIS e tem medo de alterar uma coisinha ali e outra acolá vou dar a maior dica: saia abrindo cada opção do painel da aplicação até que uma delas acuse um erro de configuração.
Por exemplo, abra o item Documento Padrão. Se ele estiver configurado corretamente então abrirá a próxima tela normalmente. Se tiver algum erro, aparecerá um alerta. Então no web.config você deve corrigir a sessão correspondente. Ficou claro? Saia clicando um a um até que um deles se denuncie podendo então fazer a correção.
O que ocorreu comigo foi que um site que estava no IIS 6 podia colocar a mesma página (index.aspx) como padrão, duas vezes, e não tinha problema. Quando foi para o IIS 7, na qual estava herdando a configuração pai, e foi adicionar a página index.aspx como padrão novamente, ele dava erro e não sabia porquê. Então removi a entrada do web.config e funcionou. Desabilitar a mensagem de erro amigável no navegador vai funcionar (encontrar o erro)? Não. Desabilitar as páginas de erros personalizáveis do IIS vai funcionar (encontrar o erro)? Talvez ou não. Depende muito do ambiente que está configurado e quem está manipulando.
Pronto! Mais um problema solucionado... Vamos testar outro site e... e... e... Erro! Agora aconteceu um erro 404. Mas como? Erro 404 de página não encontrada mas se o caminho está lá? Incrivelmente no IIS do Cloud Server possuem dois Applications Pools do Plesk (e mais outros nativos): Plesk(default)(2.0) e Plesk(default)(4.0). O pool do 2.0 quase nem sempre funciona. E um comportamento anormal é que se você tem um site pai em 2.0 e um filho em 2.0 às vezes pára de funcionar. O "correto" é ter um pai 2.0 ou 4.0 com filho sempre 4.0. Estranho? Pode crer! E onde está o pool do 3.5? Tem que criar na mão mesmo.
Nota: Se você reiniciar o IIS o Plesk pára de vez e não volta:
Você terá que iniciá-lo manualmente. Mas antes terá que iniciar seu pool também (que é muito suspeito):
Ajeitado uma coisinha ali, outra aqui, vamos testar mais algumas coisas e... e... e... Quase tudo certo. Em questão de funcionalidade (que deveria ser) está quase tudo certo a não ser o funcionamento do bom e velho Crystal Reports. Quem já leu o post de erros do Crystal aqui e aqui nos deparamos com o erro:
O inicializador de tipo de 'CrystalDecisions.CrystalReports.Engine.ReportDocument' acionou uma exceção
ou
The type initializer for 'CrystalDecisions.CrystalReports.Engine.ReportDocument' threw an exception
Cuidado! Esse não é o descritivo do erro. Só com isso não dá para saber o motivo. Faça o debug, log, exibição da pilha ou na própria tela exiba o erro (sem ter AJAX) que teremos o erro completo. No link dos dois posts anteriores que fiz explica o problema do Crystal na plataforma 64bits e como pode resolver. Só que o problema no meu caso era permissão.
Server Error in '/virtual_directory_name' Application.
Error in File UNKNOWN.RPT:
The request could not be submitted for background processing.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Runtime.InteropServices.COMException: Error in File UNKNOWN.RPT: The request could not be submitted for background processing.
Os usuários listados abaixo, não tinham permissão na execução de scripts DCOM e gravação em algumas pastas (principalmente as que estão na unidade C):
- IWAN_plesk(default)
- IUSR
- IIS_IUSR
- NETWORK SERVICE
- INTERACTIVE
Esses são os usuários que devem ter privilégio (descritos abaixo) nas pastas listadas abaixo:
- C:\Windows\Temp\ : leitura \ escrita
- C:\Program Files (x86)\Business Objects\Common\2.8\bin\ : leitura
- C:\ : leitura
Obs: Para alguns servidores é preciso aplicar o Replace permission entries on all child objects nessas pastas.
Lembrando de reiniciar o IIS e/ou o servidor para recarregar as configurações.
Se estiver trabalhando com Windows Service ou Windows Form e ocorra o erro:
System.IO.FileNotFoundException: Retrieving the COM class factory for component with CLSID {5FF57840-5172-4482-9CA3-541C7878AE0F} failed due to the following error: 8007007e
Basta compilar sua aplicação em x86.
E agora, tudo certo? Até o momento sim. Porque não dizer que está tudo OK? Depois de ter ocorrido todos esses problemas, fica-se receoso com o futuro. Pode ser que ocorra outro problema posteriormente? Sim e irá.
Conforme disse anteriormente, o post não é para dizer mal sobre a Locaweb e/ou Plesk. Acho que eles prestam um serviço adequado para o nível nacional (até uso) contudo são coisas que acontecem que simplesmente poderiam ser sanadas antes de jogar o pepino para o cliente. Se você tiver algum problema desses e sua gerência for pelo cliente, nem adianta pedir que eles vão lhe informar: "o gerenciamento é por conta do cliente e não nos responsabilizamos" ou "a ferramenta (Plesk) é terceirizada e não prestamos suporte.". Enfim, espero que o post ajude a você, cliente e usuário, a corrigir seus problemas/pepinos que ocorrerem. Isso me lembra quando lançou o plug-and-play... a velha piadinha do plug-and-pray (ligar e rezar) não some da cabeça quando ocorre esse tipo de problema. Porque será?
Diferenças entre Aplicações Compiladas e Não-Compiladas
Postado por
Thiago Marçal
on sábado, 12 de março de 2011
/
Marcadores:
desempenho,
dicas,
dll,
iis
/
Comments: (0)
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:
Ó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.
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 | |
Ó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:
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:
- Use expressão regular para validar seu HTML;
- Use expressão regular e/ou o HtmlAgilityPack para remover os JavaScripts;
- O conteúdo a ser convertido deve ser apenas o que está dentro do body;
- 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:
- Gere um thumb (imagem) do HTML que deseja converter (saiba como gerar um thumb de um HTML nesse post) e salve em disco;
- Atribua a variável html com o conteúdo "<img src="http://thiagomarcal.blogspot.com/imgs/thumb.png" />";
- 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#
Postado por
Thiago Marçal
on domingo, 13 de fevereiro de 2011
/
Marcadores:
correios,
dicas,
dll,
web-service
/
Comments: (4)
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:
Abaixo temos um resumo do processo:
- Enviamos uma requisição GET com o número do rastreamento;
- Obtemos os dados de retorno (página completa);
- Capturamos apenas a tabela com os dados de rastreamento;
- 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...










