asp использует веб-службу, что делать с объектом набора записей?

В настоящее время я запускаю классическую (старую) веб-страницу ASP с объектом набора записей, используемым непосредственно в плохой старой моде спагети-кода.

Я думаю о реализации уровня данных в asp.net в качестве веб-сервиса для улучшения управляемости. Это также первый шаг к обновлению веб-сайта до asp.net. Сам сайт пока остается ASP...

Может ли кто-нибудь порекомендовать хороший способ замены типа объекта набора записей типом, совместимым с веб-службой (например, массивом или чем-то еще)? Что мне заменить ниже?:

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

а также можно заменить несколько наборов записей? Я говорю :

 set objRS = objRs.nextRecordset 

Кто-нибудь проходил через это и может порекомендовать?

@AdditionalInfo — вы просили об этом :-)

Позвольте мне начать с самого начала. Существующая ситуация: у меня есть старый веб-сайт ASP с классическим иерархическим содержимым (заголовок, раздел, подраздел, содержимое), извлеченным из базы данных с помощью хранимых процедур, и страницы содержимого также находятся в базе данных (ссылка на файл html ).

Плохо то, что код ASP повсюду разбросан по множеству файлов .asp, каждый из которых выполняет свои собственные подключения к базе данных, чтение, запись (вы должны зарегистрироваться для получения содержимого). Недавно у нас были проблемы с атаками SQL-инъекций, поэтому меня вызвали, чтобы исправить это.

Я мог бы изменить все страницы .asp, чтобы предотвратить внедрение SQL, но это было бы безумием. Поэтому я подумал создать слой данных - все страницы, использующие этот слой для доступа к базе данных. Один раз место для исправления и обновления кода доступа к базе данных.

Придя к этому решению, я подумал, что обновление asp.net не за горами, почему бы не начать использовать asp.net для уровня данных? Таким образом, его можно повторно использовать при обновлении сайта.

Это подводит меня к вопросам выше!


person Johannes    schedule 10.09.2008    source источник
comment
Можете ли вы дать нам больше примеров и информации? Трудно понять, что именно вы пытаетесь здесь сделать.   -  person Michael Pryor    schedule 11.09.2008


Ответы (7)


Если вы хотите придерживаться классического ASP, я бы предложил создать объект обработки базы данных с помощью классов ASP, а затем просто использовать этот объект для создания ваших наборов записей. Это позволит централизовать ваш код обработки базы данных и сделать так, чтобы вам приходилось обрабатывать атаки SQL Injection только в одном месте.

Простой пример.

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

Затем, чтобы использовать это, вы должны изменить свои вызовы на:

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

Конечно, вы можете расширить базовый класс для обработки параметризованных хранимых процедур или чего-то еще, а также дополнительных проверок и т. д.

person Skyhigh    schedule 16.09.2008
comment
Привет Скайхай! Вот что я в итоге сделал. Придерживаемся кода ASP и вводим класс для обработки всего, что связано с базой данных. Спасибо! - person Johannes; 23.09.2008

Первый мой любимый совет на этой неделе: не относитесь к веб-службе так, как если бы она была локальным объектом, иначе вы заплатите очень высокую цену за производительность. По сути, не делайте подобных вещей в своем веб-приложении:

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

Вы всегда должны предпочитать минимизировать вызовы вашей веб-службы (и SQL):

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

Теперь, что касается типа данных, используемого для вызовов веб-службы, у вас есть два основных варианта:

  • набор данных
  • Все остальное (массив)

Большинство коллекций, возвращаемых веб-службой (например, List‹MyData›), фактически преобразуются в массив во время вызова веб-службы. Помните, что веб-службы возвращают не объекты (данные + поведение), а только структуры данных (или их последовательность). Поэтому разница между списком и массивом незначительна.

Наборы данных — это более сложные классы; они используют свой собственный сериализатор и практически полностью воссоздаются в вызывающем приложении. За использование таких наборов данных приходится платить производительностью, поэтому я обычно не рекомендую его для большинства сценариев. Использование массивов для передачи данных туда и обратно, как правило, более эффективно, и, откровенно говоря, это проще сделать.

Ваш случай немного отличается; поскольку вы преобразовываете существующий сайт, который уже использует ADO, набор данных ADO.NET может быть лучшим способом обновления. ADO.NET и ADO достаточно похожи, поэтому прямое обновление может быть проще. Это зависит от того, как построен ваш веб-сайт.

Что касается последней части вашего вопроса, наборы данных поддерживают несколько наборов записей, аналогичных набору записей ADO. Они называются таблицами данных. В каждом наборе данных есть как минимум одна таблица данных, и вы можете читать их в любом порядке.

Удачи.

person Euro Micelli    schedule 10.09.2008

Я бы предложил использовать класс XmlHttp в вашем коде ASP.

Предполагая, что у вас есть веб-служба ASMX, подобная этой, в MyService.asmx:

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

Вы можете назвать это в ASP примерно так:

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 будет XML-ответом:

<string>Hello World</string>

Предполагая, что ваша служба вернула набор данных, вы могли бы перебрать его, используя XPath или любую другую технику/библиотеку обработки XML.

Поиск в Google о MSXML2, вероятно, ответит на любые ваши конкретные вопросы, поскольку он специфичен для классического ASP.

person Dave Ward    schedule 10.09.2008

Вместо того, чтобы мыслить слоями, почему бы не попробовать сделать вертикальные срезы приложения и преобразовать их в .net. Таким образом, вы получите целые функции, закодированные в .net, а не отдельные части. Какова ценность для бизнеса замены идеально работающего кода без улучшения взаимодействия с пользователем или добавления функций?

Вы также можете рассмотреть компромисс производительности, от которого вы собираетесь отказаться с помощью веб-службы, по сравнению с прямыми вызовами ado. Веб-сервисы — хорошее решение проблемы доступа нескольких разрозненных приложений/команд к общей схеме; они не делают отдельное изолированное приложение более удобным для сопровождения, а только замедляют и усложняют его работу.

person DancesWithBamboo    schedule 11.09.2008
comment
Спасибо за мысль! Я тоже думал об этом. К сожалению, код доступа к базе данных распределен по многим файлам .asp, поэтому мне пришлось бы делать много вертикальных срезов и в конечном итоге покрывать большую часть сайта. - person Johannes; 11.09.2008

Другой альтернативой является использование COM Interop для создания сборки в .NET, которую можно вызывать из классического ASP.

Чтобы создать сборку COM Interop из Visual Studio (например, Microsoft Visual C# 2005 Express Edition):

  • Создайте новый проект библиотеки классов
  • Откройте свойства проекта

    • Under Application select Assembly Information... and enable "Make assembly COM-Visible"
    • В разделе «Подписание» включите «Подписать сборку» и создайте или выберите существующий файл ключа со строгим именем.
  • Написать и собрать библиотеку

    • COM Interop classes must have a default constructor and only non-static classes and methods are published
  • Скопируйте .dll в нужную папку/машину

  • Зарегистрируйте .dll для COM с помощью RegAsm

Например (при необходимости отрегулируйте):

"C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe" "C:\path\to\assembly.dll" /tlb /codebase
  • Вызов сборки из ASP

Например (при необходимости отрегулируйте):

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

Примечание:

  • сборка должна быть перерегистрирована через RegAsm при обновлении

Смотрите также:

person Mike Henry    schedule 17.09.2008

Внедрение Sql должно обрабатываться с помощью параметризованных запросов sql. Это не только устранит угрозу безопасности, но и значительно повысит производительность вашей базы данных, поскольку она сможет повторно использовать план выполнения, а не пересчитывать его каждый раз. Предложение справиться с этим с помощью замены строк глупо. VB ужасно обрабатывает строки, и эти операторы «заменить» будут чрезвычайно дорогостоящими с точки зрения производительности и памяти (кроме того, вам в любом случае нужно обрабатывать только символ ')

Перенос кода в .net не делает его лучше. Наличие кода базы данных на ваших страницах неплохо; особенно если вы говорите о небольшом сайте с парой разработчиков. Тысячи сайтов используют эту технику для обработки транзакций на миллионы долларов. Теперь непараметризованный динамический sql - это плохо, и вы должны работать над его устранением, но для этого не требуется переписывать приложение или .net. Мне всегда любопытно, почему люди считают .net фактическим улучшением своего приложения. Большинство плохого кода и вредных привычек, которые существовали в модели COM, просто распространяются вперед во время преобразования.

Вы либо должны взять на себя обязательство создать по-настоящему целостный, минимально связанный объектно-ориентированный дизайн; или просто продолжайте то, что у вас есть, потому что это не так уж и плохо.

person DancesWithBamboo    schedule 21.09.2008
comment
Я согласен - в моей ситуации нет смысла сходить с ума от .net, ASP работает нормально. Теперь у меня есть параметризованные запросы в классе уровня данных для централизованного обслуживания. Использование COM просто добавляет сложности, которая мне не нужна. - person Johannes; 23.09.2008

Жаль, что я не видел этот вопрос в 2008 году. Мне кажется, что ваш сайт использует фреймворк Justa. Простой способ - изменить код Justa для отправки поиска и ввода данных в urlencode. Я сделал это и отлично работает для меня.

Остальной код достаточно безопасен, чтобы предотвратить любые SQL-инъекции ОС или другие попытки проникновения в базу данных.

person alexsts    schedule 22.01.2011