asp, использующий веб-службу, что делать с объектом набора записей?
-
09-06-2019 - |
Вопрос
В настоящее время я запускаю классическую (старую) веб-страницу 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 для уровня данных?Таким образом, его можно будет повторно использовать при обновлении сайта.
Это подводит меня к вопросам выше!
Решение
Если вы хотите придерживаться классического ASP, я бы предложил создать объект обработки базы данных с помощью классов ASP, а затем просто использовать этот объект для создания набора записей.Это позволит централизовать код обработки базы данных и сделать так, чтобы вам приходилось обрабатывать атаки SQL-инъекций только в одном месте.
Простой пример.
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
Конечно, вы можете расширить базовый класс для обработки параметризованных хранимых процедур или чего-то еще, а также дополнительных проверок и т. д.
Другие советы
Первый мой любимый совет на этой неделе:не относитесь к своей веб-службе так, как если бы она была локальным объектом, иначе вам придется заплатить очень высокую цену за производительность.По сути, не делайте подобных вещей в своем веб-приложении:
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>), фактически преобразуются в массив во время вызова веб-службы.Помните, что веб-службы возвращают не объекты (данные + поведение), а только структуры данных (или их последовательность).Таким образом, между списком и массивом нет большой разницы.
DataSets — более сложные классы;они используют собственный сериализатор и практически полностью воссоздаются в вызывающем приложении.За использование таких наборов данных приходится платить за производительность, поэтому я обычно не рекомендую его для большинства сценариев.Использование массивов для передачи данных туда и обратно, как правило, более эффективно и, откровенно говоря, это проще сделать.
Ваш случай немного другой;поскольку вы конвертируете существующий сайт, который уже использует ADO, лучшим вариантом обновления может быть набор данных ADO.NET.ADO.NET и ADO достаточно похожи, поэтому прямое обновление может оказаться проще.Это отчасти зависит от того, как построен ваш веб-сайт.
Что касается последней части вашего вопроса, наборы данных поддерживают несколько наборов записей, аналогичных набору записей ADO.Они называются DataTables.В каждом наборе данных есть хотя бы одна таблица данных, и вы можете читать их в любом порядке.
Удачи.
Я бы предложил использовать класс 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.
Вместо того, чтобы мыслить слоями, почему бы не попробовать сделать вертикальные срезы приложения и преобразовать их в .net.Таким образом, вы получите целые функции, закодированные в .net, а не разрозненные части.Какова ценность для бизнеса замены идеально работающего кода без улучшения пользовательского опыта или добавления функций?
Вы также можете рассмотреть компромисс между производительностью, от которой вы собираетесь отказаться, используя веб-службу, по сравнению с прямыми вызовами ADO.Веб-службы являются хорошим решением проблемы, когда несколько разрозненных приложений/команд получают доступ к общей схеме;они не делают отдельное изолированное приложение более удобным в обслуживании, а лишь делают его медленнее и сложнее.
Другой альтернативой является использование COM Interop для создания сборки в .NET, которую можно вызывать из классического ASP.
Чтобы создать сборку COM Interop из Visual Studio (например,Microsoft Visual C# 2005, экспресс-выпуск):
- Создайте новый проект библиотеки классов.
Откройте свойства проекта
- В разделе «Приложение» выберите «Информация о сборке...».и включите «Сделать сборку COM-видимой»
- В разделе «Подписание» включите «Подписать сборку» и создайте или выберите существующий файл ключа строгого имени.
Напишите и создайте библиотеку
- Классы COM Interop должны иметь конструктор по умолчанию, и публикуются только нестатические классы и методы.
Скопируйте .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 при ее обновлении
Смотрите также:
Внедрение SQL должно обрабатываться с помощью параметризованных SQL-запросов.Это не только устранит угрозу безопасности, но и значительно ускорит производительность вашей базы данных, поскольку она сможет повторно использовать план выполнения вместо того, чтобы каждый раз пересчитывать его.Предложение решить эту проблему посредством замены строк глупо.VB ужасно обрабатывает строки, и эти операторы «замены» будут чрезвычайно дорогостоящими с точки зрения производительности и памяти (кроме того, на самом деле вам все равно нужно обрабатывать только символ ')
Перенос кода в .net не улучшит его.Иметь код базы данных на своих страницах неплохо;особенно, если вы говорите о небольшом сайте, на котором работает всего пара разработчиков.Тысячи сайтов используют эту технику для обработки транзакций на миллиарды долларов.Непараметризованный динамический SQL — это плохо, и вам следует поработать над его устранением, но для этого не требуется переписывать приложение или .net.Мне всегда любопытно, почему люди рассматривают .net как фактическое улучшение своего приложения.Большая часть плохого кода и вредных привычек, существовавших в модели COM, просто распространяются во время преобразования.
Вам либо нужно взять на себя обязательство создать по-настоящему связный, минимально связанный объектно-ориентированный дизайн;или просто продолжайте то, что у вас есть, потому что это не так уж и плохо.
Жаль, что я не увидел этот вопрос в 2008 году.Мне кажется, что ваш сайт использует фреймворк Justa.Простой способ — изменить код Justa для отправки поиска и ввода данных в urlencode.Я сделал это и отлично работает для меня.
Остальная часть кода достаточно безопасна, чтобы предотвратить любые SQL-инъекции или другие попытки проникновения в базу данных.