Pergunta

Atualmente eu executo uma página da Web ASP clássica (antiga) com objeto de conjunto de registros usado diretamente no antigo código spagethi.

Estou pensando em implementar uma camada de dados no asp.net como serviço web para melhorar a capacidade de gerenciamento.Este também é o primeiro passo para atualizar o site para asp.net.O site em si permanece ASP no momento...

Alguém pode recomendar uma boa maneira de substituir o tipo de objeto do conjunto de registros por um tipo compatível com serviço da Web (como um array ou algo assim)?O que substituo abaixo?:

set objRS = oConn.execute(SQL)
while not objRS.eof
   ...
   name = Cstr(objRS(1))
   ...
wend

e também vários conjuntos de registros podem ser substituídos por?Eu estou falando :

 set objRS = objRs.nextRecordset 

Alguém passou por isso e pode recomendar?

@AdditionalInfo - você pediu :-)

Deixe-me começar no início.A situação existente é:Eu tenho um site ASP antigo com conteúdo hierárquico clássico (cabeçalho, seção, subseção, conteúdo) retirado do banco de dados por meio de procedimentos armazenados e páginas de conteúdo também estão no banco de dados (um link para o arquivo html).

Agora, o ruim é que o código ASP está espalhado em todos os lugares por muitos arquivos .asp, todos fazendo suas próprias conexões de banco de dados, lendo, escrevendo (você precisa se registrar para obter conteúdo).Recentemente tivemos problemas com ataques de injeção de SQL então fui chamado para consertar.

EU poderia vá mudar todas as páginas .asp para evitar injeção de sql, mas isso seria uma loucura.Então pensei em construir uma camada de dados - todas as páginas usando essa camada para acessar o banco de dados.Uma vez local para corrigir e atualizar o código de acesso do banco de dados.

Chegando a essa decisão, pensei que a atualização do asp.net não estava longe, por que não começar a usar o asp.net para a camada de dados?Desta forma, ele pode ser reutilizado na atualização do site.

Isso me leva às perguntas acima!

Foi útil?

Solução

Se você quiser continuar com o ASP clássico, sugiro criar um objeto de manipulação de banco de dados por meio de classes ASP e, em seguida, usar esse objeto para fazer suas criações de conjunto de registros.Isso centralizaria o código de manipulação do banco de dados e faria com que você só precisasse lidar com ataques de injeção de SQL em um único local.

Um exemplo simples.

Class clsDatabase

    Private Sub Class_Initialize()
        If Session("Debug") Then Response.Write "Database Initialized<br />"
    End Sub

    Private Sub Class_Terminate()
        If Session("Debug") Then Response.Write "Database Terminated<br />"
    End Sub

    Public Function Run(SQL)
        Set RS = CreateObject("ADODB.Recordset")
        RS.CursorLocation = adUseClient
        RS.Open SQLValidate(SQL), Application("Data"), adOpenKeyset, adLockReadOnly, adCmdText
        Set Run = RS
        Set RS = nothing
    End Function

    Public Function SQLValidate(SQL)
        SQLValidate = SQL
        SQLValidate = Replace(SQLValidate, "--", "", 1, -1, 1)
        SQLValidate = Replace(SQLValidate, ";", "", 1, -1, 1)
        SQLValidate = Replace(SQLValidate, "SP_", "", 1, -1, 1)
        SQLValidate = Replace(SQLValidate, "@@", "", 1, -1, 1)
        SQLValidate = Replace(SQLValidate, " DECLARE", "", 1, -1, 1)
        SQLValidate = Replace(SQLValidate, "EXEC", "", 1, -1, 1)
        SQLValidate = Replace(SQLValidate, " DROP", "", 1, -1, 1)
        SQLValidate = Replace(SQLValidate, " CREATE", "", 1, -1, 1)
        SQLValidate = Replace(SQLValidate, " GRANT", "", 1, -1, 1)
        SQLValidate = Replace(SQLValidate, " XP_", "", 1, -1, 1)
        SQLValidate = Replace(SQLValidate, "CHAR(124)", "", 1, -1, 1)
    End Function
End Class

Então, para usar isso, você mudaria suas chamadas para:

Set oData = new clsDatabase
Set Recordset = oData.Run("SELECT field FROM table WHERE something = another")
Set oData = nothing

É claro que você pode expandir a classe básica para lidar com procedimentos armazenados parametrizados ou outras coisas e mais validações, etc.

Outras dicas

Primeiro meu conselho favorito desta semana:não trate seu serviço da Web como se fosse um objeto local ou você pagará um preço de desempenho muito alto.Essencialmente, não faça coisas assim em seu aplicativo web:

MyDataWebService ws = new MyDataWebService();
foreach(DataItem item in myData)
{
    ws.Insert(item);
}

Você deve sempre preferir minimizar chamadas para seu serviço Web (e SQL):

MyDataWebService ws = new MyDataWebService();
ws.Insert(myData); // Let the web service process the whole set at once.

Agora, no que diz respeito ao tipo de dados a ser usado para suas chamadas de serviço da web, você basicamente tem duas opções:

  • Conjunto de dados
  • Todo o resto (matriz)

A maioria das coleções retornadas de um serviço web (como List<MyData>) na verdade são convertidas em um Array durante a invocação do serviço web.Lembre-se que Web Services não retornam objetos (dados + comportamento), mas apenas estruturas de dados (ou uma sequência de).Portanto, há pouca distinção entre uma lista e uma matriz.

DataSets são classes mais complexas;eles usam seu próprio serializador personalizado e são totalmente recriados no aplicativo de chamada.Há um custo de desempenho a ser pago pelo uso de DataSets como esse, por isso geralmente não o recomendo para a maioria dos cenários.Usar arrays para transmitir dados tende a ser mais eficiente e, francamente, é mais fácil de fazer.

Seu caso é um pouco diferente;como você está convertendo um site existente que já usa ADO, um DataSet ADO.NET pode ser seu melhor caminho de atualização.ADO.NET e ADO são semelhantes o suficiente para que uma atualização direta possa ser mais fácil dessa forma.Depende de como o seu site é construído.

Para a última parte da sua pergunta, os DataSets suportam vários conjuntos de registros semelhantes ao Recordset do ADO.Eles são chamados de DataTables.Cada DataSet possui pelo menos um DataTable e você pode lê-los em qualquer ordem.

Boa sorte.

Eu sugiro usar a classe XmlHttp no seu código ASP.

Supondo que você tenha um serviço web ASMX semelhante a este, em MyService.asmx:

[WebMethod]
public string HelloWorld()
{
  return "Hello World";
}

Você poderia chamá-lo em ASP algo assim:

Dim xhr

Set xhr = server.CreateObject("MSXML2.XMLHTTP")

xhr.Open "POST", "/MyService.asmx/HelloWorld", false
xhr.SetRequestHeader "content-type", "application/x-www-form-urlencoded"
xhr.Send

Response.Write(xhr.ResponseText)

ResponseText seria uma resposta XML de:

<string>Hello World</string>

Supondo que seu serviço retornou uma coleção de dados, você poderia iterá-los usando XPath ou qualquer outra técnica/biblioteca de processamento XML.

Pesquisar no Google sobre MSXML2 provavelmente responderá a quaisquer perguntas específicas que você tenha, já que é específico do ASP clássico.

Em vez de pensar em camadas, por que não tentar obter fatias verticais do aplicativo e convertê-las para .net.Dessa forma, você obterá recursos inteiros codificados em .net, em vez de partes separadas.Qual é o valor comercial de substituir um código que funciona perfeitamente sem melhorar a experiência do usuário ou adicionar recursos?

Você também pode considerar a compensação de desempenho que você abandonará com um serviço da Web em vez de chamadas diretas.Os serviços da Web são uma boa solução para o problema de vários aplicativos/equipes separados acessando um esquema comum;eles não tornam um único aplicativo isolado mais sustentável, apenas mais lento e complexo.

Outra alternativa é usar COM Interop para criar um assembly em .NET que possa ser chamado a partir do ASP clássico.

Para criar um assembly de interoperabilidade COM do Visual Studio (por exemplo,Edição Expressa do Microsoft Visual C# 2005):

  • Crie um novo projeto de biblioteca de classes
  • Abra as propriedades do projeto

    • Em Aplicativo, selecione Informações de montagem...e habilite "Tornar a montagem COM-Visível"
    • Em Assinatura, habilite Assinar o assembly e criar ou selecionar um arquivo de chave de nome forte existente
  • Escreva e construa a biblioteca

    • As classes COM Interop devem ter um construtor padrão e apenas classes e métodos não estáticos são publicados
  • Copie o .dll para a pasta/máquina desejada

  • Registre o .dll para COM usando RegAsm

Por exemplo (ajuste conforme necessário):

"C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe" "C:\path\to\assembly.dll" /tlb /codebase
  • Chame a montagem do ASP

Por exemplo (ajuste conforme necessário):

Dim obj, returnValue
Set obj = Server.CreateObject("MyProject.MyClass")
returnValue = obj.DoSomething(param1, param2)

Observação:

  • o assembly deve ser registrado novamente via RegAsm quando for atualizado

Veja também:

A injeção SQL deve ser tratada usando consultas SQL parametrizadas.Isso não apenas eliminará o risco de segurança, mas também acelerará significativamente o desempenho do seu banco de dados, pois será capaz de reutilizar um plano de execução em vez de recalculá-lo todas as vezes.A sugestão de lidar com isso através de substituições de strings é tola.VB é péssimo no manuseio de strings e essas instruções de "substituição" serão extremamente caras em desempenho e memória (além disso, você só precisa manipular o caractere 'de qualquer maneira)

Mover o código para .net não o torna melhor.Ter código db em suas páginas não é ruim;especialmente se você estiver falando de um site pequeno com apenas alguns desenvolvedores.Milhares de sites usam essa técnica para processar bilhões de dólares em transações.Agora, o SQL dinâmico não parametrizado é ruim e você deve trabalhar para eliminá-lo, mas isso não requer uma reescrita do aplicativo ou do .net para fazer isso.Estou sempre curioso para saber por que as pessoas veem o .net como uma melhoria de fato em seus aplicativos.A maior parte do código incorreto e dos maus hábitos que existiam no modelo COM apenas se propaga durante uma conversão.

Você precisa se comprometer a criar um design OO verdadeiramente coeso e minimamente acoplado;ou apenas mantenha o que você tem porque não é tão ruim assim.

Pena que não vi essa pergunta em 2008.Para mim, parece que seu site está usando o framework Justa.A maneira simples é modificar o código Justa para enviar pesquisas e entradas de dados para o urlencode.Eu fiz isso e funcionou perfeitamente para mim.

Resto do código seguro o suficiente para evitar qualquer tipo de injeções de SQL ou outra tentativa de entrar no banco de dados.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top