480 likes | 627 Views
Active Server Pages. Dynamic content in Microsoft Internet Information Server 4.0+. Mål. Ha en oversikt over hvordan ASP passer inn i puslespillet Kunne skrive dynamiske sider ved hjelp av ASP Kunne aksessere COM komponenter ved hjelp av ASP
E N D
Active Server Pages Dynamic content in Microsoft Internet Information Server 4.0+
Mål • Ha en oversikt over hvordan ASP passer inn i puslespillet • Kunne skrive dynamiske sider ved hjelp av ASP • Kunne aksessere COM komponenter ved hjelp av ASP • Kunne skrive ATL COM komponenter for bruk med ASP sider
Krav • ASP kjører på IIS 4.0 og høyere • IIS finnes få Windows NT Server Option Pack • For å bruke XML må en XML parser installeres. Msxml.dll følger med Internet Explorer 5.0 og høyere • For å lære ASP bør man ha kjennskap til HTML • JScript/JavaScript eller VBScript kunnskap er også en fordel, men disse språkene er lette å lære dersom man kan programmere
Hello ASP <%@ Language="JScript" %> <html> <h1>ASP 1: Hello world</h1> <% var hello = "Hello ASP" %> <%=hello%> </html>
Anatomien til en ASP side • I utgangspunktet en vanlig HTML side • Elementer som starter med <% angi ASP elementer • ASP elementer behandles av serveren før svaret sendes til klienten • ASP elementer er skrevet i et script-språk som JScript eller VBScript • http://gnats/asp-sample/01hello.asp
Spesielle ASP Elementer • <%@LANGUAGE er et ASP direktiv som angir hvilket språk (JScript eller VBScript) som skal brukes • Andre direktiver er f.eks. @CODEPAGE, @TRANSACTION, og @LCID • <%=...%> er en forkortelse for <% Response.Write(...) %>
Eksempel 2 <%@ Language="JScript" %> <html> <% for ( var i=0; i<10; i++ ) { var line = "Iteration" + i + "<br>"; Response.Write(line); } %> </html>
Program-biter • Vi kan ha programbiter i ASP siden. • Program-bitene er i et <% %> element. • Programbitene vil bli utført akkurat som en hvilket som helst script. • Vi bruker Respose objektets Write metode for å skrive til resultatsiden. • http://gnats/asp-sample/02-1loop.asp
Html i script i html <%@ Language="JScript" %> <html> <h1>ASP 2: Looping ASP script</h1> <% for ( var i=0; i<10; i++ ) { %> <p>Iteration <%=i%>: Hello there</p> <% } %> </html>
Mikse HTML og Script • Kontrol-flyten fra scriptspråket inkluderer html som er mellom {} etc. • <%= ... %> fungerer som <% Response.Write(...) %> • http://gnats/asp-sample/02loop.asp
Scriptobjekter <%@ Language="JScript" %> <html> <h1>ActiveX Server Pages 3: Time</h1> The time is <%=new Date()%>. </body> </html>
Script-objekter • Alle objekter og funksjoner tilgjengelige i scriptspråket er også tilgjengelige i ASP • I tillegg definerer ASP fem objekter siden kan bruke: • Request – informasjon fra senderen • Response – svaret som vises i browseren • Server – Informasjon og metoder for serveren • Session – inneholder brukers sesjonsinfo • Application – brukes til å dele info mellom brukere • http://gnats/asp-sample/03time.asp
Forms <% @Language="JScript" %> <html> <%if(Request.form("inMessagePost")!="true" ){%> <!-- html for å vise en form --> <% } else { %> <!-- html for å vise resultatet --> <% } %> </html>
Form – oversikt • Request objektet sendes med når vi mottar en web-side • Dersom det eksisterer informasjon i en form fra senderen, kan ”form” metoden til Request returnere denne informasjonen • Vi har laget et skjult element med navn ”inMessagePost” og verdi ”true” som sendes med når brukeren trykker ”post” i formen. • http://gnats/asp-sample/05form.asp
Form – user entry <form name=”Input Form" method="post" action="05form.asp"> <table> <tr><td><b>To:</b></td> <td><input type="text" name="to” value=”recp”/></td></tr> <tr><td><b>From:</b></td> <td><input type="text" name="from” value=”sender”/></td></tr> <tr><td><b>Email:</b></td> <td><input type="text" name="email” value=”name@server.domain”/></td></tr> <tr><td><b>Subject:</b></td> <td><input type="text" name="subject” value=”message subject”/></td></tr> <tr><td colspan="2"><b>Message text</b></td></tr> <tr><td colspan="2"> <textarea name="message" rows="6" cols="30">Message Text</textarea> </td></tr> </table> <input type="hidden" name="inMessagePost" value="true"/> <input type="submit" name="Send message"/> <input type="reset" name="Clear form"/> </form>
Form – user input • Form elementet forteller at vi skal POST’e svaret til 05form.asp (som er samme dokument som formen selv) • Vi har presentert følgende input-elementer i en tabell: • To, from, email, subject og message • I tillegg har vi et input element av type ”hidden”. Dette er for å sende med styreparameteren ”inMessagePost”
Form – echo back <h2>I got the following information:</h2> <table border=""> <tr><td><b>To:</b></td><td><%=Request.form("to")%></td></tr> <tr><td><b>From:</b></td><td><%=Request.form("from")%></td></tr> <tr><td><b>Email:</b></td><td><%=Request.form("email")%></td></tr> <tr><td> <b>Subject:</b></td><td><%=Request.form("subject")%> </td></tr> <tr><td colspan="2"><b>Message text</b></td></tr> <tr><tdcolspan="2"> <pre><%=Request.form("message")%></pre> </td></tr> </table>
Form – echo back • Vi bruker Request.Form for å finne verdiene som ble sent til formen. • Vi bruker <%= ... %> som en snarvei for Response.Write for at det ikke skal bli så mye å skrive og lese.
Forsinkelse <%@ Language="JScript" %> <html> <% function f(i) { var result = 1; while ( i > 0 ) result *= i--; return result; } for ( var i=0; i<10; i++ ) { %> <p>Hello there</p> <% f(1000000); // simulate delay } %> </html>
Forsinkelse • Vi definerer en funksjon som gjør mye arbeid for å simulere forsinkelse. • En og en linje kommer opp når den er ”klar” • Legg også merke til funksjons-deklarasjonen. Dette er vanlig funksjons-deklarasjon i JScript, og kan også brukes i et ASP script • http://gnats/asp-sample/06delay.asp
Bruk av COM - ADO <%@ Language="JScript" %> <html> <% var connection = Server.CreateObject("ADODB.Connection"); connection.Open("guestbook", "admin", ""); var recordset = Server.CreateObject("ADODB.Recordset"); recordset.Open("SELECT * FROM guestbook", connection); Response.Write("<table border=''>"); for ( recordset.MoveFirst(); !recordset.EOF; recordset.MoveNext() ) { Response.Write("<tr>"); var iter = new Enumerator(recordset.Fields); for ( ; !iter.atEnd(); iter.moveNext() ) { Response.Write("<td>" + iter.item() + "</td>"); } Response.Write("</tr>"); } Response.Write("</table>"); %> </html>
COM • Server.CreateObject brukes til å lage et (Inprocess) COM objekt på serveren • COM Objektet kan aksesseres som fra ethvert script • Legg merke til at Scriptet har fulle rettigheter, det regnes ikke som et utrygt script • I JScript bruker vi en Enumerator for å gå gjennom en collection • http://gnats/asp-sample/07ado.asp
Filsystem <%@ Language="JScript" %> <ul> <% var fileSystem = Server.CreateObject("Scripting.FileSystemObject"); var folder = fileSystem.getFolder(Server.MapPath(”.")); var iter = new Enumerator(folder.Files); for ( ; !iter.atEnd(); iter.moveNext() ) { var fileName = iter.item().Name; if ( !fileName.match(".asp$") ) continue; %> <li><a href="<%=fileName%>"><%=fileName%></a></li> <% } %> </ul>
Filsystem • Et Scripting.FileSystemObject opprettes på serveren med Server.CreateObject • Server.MapPath brukes til å få path’en til en virtuell (web) folder. I dette tilfellet returneres ”c:\InetPub\WwwRoot\asp-sample” • FileSystemObject’s metode getFolder oppretter et Folder objekt • Scripting.FileSystemObject er en komponent som er designet for å gi skript-språk tilgang til filsystemet.
Filsystem – forts. • Kun ASP filer skrives ut • Name.match(”.asp$”) bruker JScript string’s matching metode (regular expressions) • Selve utskriften gjøres med en av-ASP’et linje • Vi bruker et Enumerator objekt for å gå gjennom Files samlingen på Folder objektet • http://gnats/asp-sample/default.asp
Prosessere XML <%@ Language="JScript" %> <% var xmlFile = (Request.QueryString("xml").Count > 0 ? Request.QueryString("xml") : "Remit-0711-00.xml"); var xslFile = (Request.QueryString("xsl").Count > 0 ? Request.QueryString("xsl") : "PaymentLog-viewer.xsl"); var xml = Server.CreateObject("Microsoft.XMLDOM"); xml.load(Server.MapPath(xmlFile)); var xsl = Server.CreateObject("Microsoft.XMLDOM"); xsl.load(Server.MapPath(xslFile)); var html = xml.transformNode(xsl); Response.Write(html); %>
Prosessere XML • QueryString henter ut argumenter gitt til URL’en til web-siden (f.eks. ”.../09Xml.asp?xml=Remit-0817-00.xml”) • transformNode gjør hele arbeidet med å transformere xml-en til html ved hjelp av stylesheet’et • Det eksisterer en mengde andre funksjoner på Microsoft.XMLDOM objektet. • http://gnats/asp-sample/09Xml.asp • http://gnats/asp-sample/09Xml.asp?xml=Remit-0817-00.xml • http://gnats/asp-sample/09Xml.asp?xsl=PaymentLog-Viewer2.xsl
ATL og ASP COM komponenter for bruk i ASP sider
C++ COM ASP • En ASP side kan aksessere ethvert objekt som implementerer IDispatch interfacet • Aksessen skjer på samme måte som enhver script-basert aksess til en komponent • Metoder som ikke er ”oleautomation” kompatible kan ikke kalles • Det ser ut som om script-interpreteren ikke støtte VARIANT-records (ennå?)
Hello ATL - IDL import "oaidl.idl"; import "ocidl.idl"; [ object, uuid(B6207922-7993-11D4-A235-0008C785A717), dual, pointer_default(unique) ] interface ICaseTransform : IDispatch { HRESULT ToUpperCase([in] BSTR input, [out,retval] BSTR* upcase); }; [ uuid(4F63DF31-78E1-11D4-A234-0008C785A717), version(1.0) ] library ASPCOMPONENTLib { importlib("stdole32.tlb"); importlib("stdole2.tlb"); [ uuid(B6207923-7993-11D4-A235-0008C785A717) ] coclass CaseTransform { [default] interface ICaseTransform; }; };
Hello ATL - Header class ATL_NO_VTABLE CoCaseTransform : public CComObjectRoot, public CComCoClass<CoCaseTransform, &CLSID_CaseTransform>, public IDispatchImpl<ICaseTransform, ...> { public: DECLARE_REGISTRY_RESOURCEID(IDR_CASETRANSFORM) // ProgId ASPComponent.CaseTransform.1 // Clsid {B6207923-7993-11D4-A235-0008C785A717} BEGIN_COM_MAP(CoCaseTransform) COM_INTERFACE_ENTRY(ICaseTransform) COM_INTERFACE_ENTRY(IDispatch) END_COM_MAP() STDMETHOD(ToUpperCase)(BSTR input, BSTR* upcaseString) { CComBSTR result(input); wcsupr(result); *upcase = result.Detach(); return S_OK; } };
Hello ATL - ASP <%@ LANGUAGE="JScript" %> <HTML> <% var component = Server.CreateObject("ASPComponent.CaseTransform"); Response.Write(component.ToUpperCase("hello world")); %> </HTML>
Hello ASP • ASP scriptet bruker Server.CreateObject for å opprette det nye objektet • Scriptet bruker ProgId for å angi hvilket objekt som skal opprettes (husk å registrere dll’en) • Merk at IIS 4.0 kun støttet InProcess komponenter (dette kan påvirkes) • IIS tar lock på dll’en. Denne locken blir ikke frigjort før serveren rebootes (?!?) • http://gnats/asp-sample/10AspComponentTest.asp
ATL – Bruk av ASP objekter • Når et objekt opprettes på en side, vil metodene ”OnStartPage” og ”OnEndPage” kalles, dersom objektet implementerer dem • OnStartPage – kalles når objektet opprettes, gir komponenten tilgang til ASP’s objektmodell • OnEndPage – kalles når siden er ferdig presentert. Etter at OnEndPage er kalt, vil objektene fra OnStartPage være ugyldige
Eksempel • OnStartPage – setter opp alle objekt-referansene vi trenger • OnEndPage – slipper alle objektreferanser • OutputPage – skriver ut en web-side ved å bruke Response objektet • OutputPage er funksjonelt lik eksempel 5, som bruker Forms • http://gnats/asp-sample/11AspSecondCompontent.asp
OnStartPage STDMETHODIMP CoAspTestComponent::OnStartPage (IUnknown* pUnk) { CComPtr<IScriptingContext> pContext; HRESULT hr = pUnk->QueryInterface(IID_IScriptingContext, (void **)&pContext); // Get all the scripting object references if ( SUCCEEDED(hr) ) hr = pContext->get_Request(&m_pRequest); if ( SUCCEEDED(hr) ) hr = pContext->get_Response(&m_pResponse); if ( SUCCEEDED(hr) ) hr = pContext->get_Server(&m_pServer); if ( SUCCEEDED(hr) ) hr = pContext->get_Session(&m_pSession); if ( SUCCEEDED(hr) ) hr = pContext->get_Application(&m_pApplication); if ( FAILED(hr) ) // Release all object references if something went wrong return S_OK; }
OnEndPage STDMETHODIMP CoAspTestComponent::OnEndPage () { // Release all interfaces m_pRequest.Release(); m_pResponse.Release(); m_pServer.Release(); m_pSession.Release(); m_pApplication.Release(); return S_OK; }
OutputPage STDMETHODIMP CoAspTestComponent::OutputPage() { CComPtr<IRequestDictionary> pForm; m_pRequest->get_Form(&pForm); int formCount = 0; pForm->get_Count(&formCount); if ( formCount == 0 ) { // means no post action return OutputFormPage(); } else { return OutputResultPage(pForm); } }
OutputFormPage HRESULT CoAspTestComponent::OutputFormPage() { CComVariant vFormPage( L"<form method='post' action='11AspSecondCompontent.asp'>\n" L"<h2>Please insert your message</h2>\n" L"<table>\n" L"<tr><td><b>To:</b></td>” L”<td><input type='text' name='to' value='recp'/></td></tr>\n" L"<tr><td><b>From:</b></td>” L”<td><input type='text' name='from' value='sender'/></td></tr>\n" L"<tr><td colspan='2'><b>Message text</b></td></tr>\n” // OSV L"</table>\n" L"<input type='submit' name='Send message'/>\n" L"<input type='reset' name='Clear form'/>\n" L"</form>"); return m_pResponse->Write(vFormPage); }
OutputResultPage HRESULT CoAspTestComponent::OutputResultPage(IRequestDictionary* pForm) { m_pResponse->Write( CComVariant(L"<h2>I got the following information:</h2>\n")); m_pResponse->Write(CComVariant(L"<table border=''>\n")); CComVariant fields[] = { L"to", L"from", L"email", L"subject" }; for ( int i=0; i<sizeof(fields)/sizeof(*fields); i++ ) OutputFieldValue(fields[i]); m_pResponse->Write( CComVariant(L"<tr><td colspan='2'><b>Message text</b></td></tr>\n" L"<tr><td colspan='2'><pre>")); CComVariant fieldValue; pForm->get_Item(CComVariant(L"message"), &fieldValue); m_pResponse->Write(fieldValue); m_pResponse->Write(CComVariant(L"</pre></td></tr>\n</table>\n")); return hr; }
OutputFieldValue HRESULT CoAspTestComponent::OutputFieldValue( IRequestDictionary* pForm, CComVariant fieldName) { CComVariant fieldValue; pForm->get_Item(fieldName, &fieldValue); m_pResponse->Write(CComVariant(L"<tr><td><b>")); m_pResponse->Write(fieldName); m_pResponse->Write(CComVariant(L":</b></td><td>")); m_pResponse->Write(fieldValue); m_pResponse->Write(CComVariant(L"</td></tr>")); return hr; }
Grenser for hva som kan gjøres • På grunn av locking av dll er det vanskelig å bytte ut en dll • Jeg har ikke forsøkt å bruke debuggeren mot et ASP script, men jeg tror det er vrient • ASP kan ikke aksesser IUnknown komponenter eller Variant structer • Konklusjon: ASP egner seg best som et tynt presentasjonslag over eksisterende funksjonalitet
ASP og IUnknown • http://gnats/asp-sample/12-1AspStructs.asp • Det går ikke å aksessere funksjoner som ikke er oleauto. • Eksempelet viser aksess av : HRESULT GetStruct([out, retval, ref] struct MyTestStruct** theStruct);
ASP og Variant Records • http://gnats/asp-sample/12-2AspStructs.asp • Eksempelet viser kall på en metode som returnerer en struct i en VARIANT
Structwrapper • Det er relativt enkelt å skrive en wrapper for structs i en IDispatch interface • Bruken av denne wrapperen er nesten transparent fra Script klienter • Dessverre ser det ut som om dette fremprovoserer en feil i script interpreter (?) • Bruk vil få serveren til å bruke mer og mer ressurser på ”inetinfo.exe” prosessen inntil maskinen krasjer. • Bruk vil også blokke alle andre web-requester
Eksempler • Jeg skal gjøre tilgjengelig en samling med ASP script (eksemplene her) og et VC 6.0 prosjekt med ATL ASP-kode • ATL koden inkluderer scriptwrapper. Det går fint ann å leke med den, men man må reboote serveren etterpå ;-)
Hva nå? • Både JScript, og ASP er dokumentert i MSDN • Scriptspråk • JScript - msdn.microsoft.com/scripting/jscript/ • VBScript - msdn.microsoft.com/scripting/vbscript/ • Generelt – http://msdn.microsoft.com/scripting/ • Se spesielt Language Reference • http://msdn.microsoft.com/workshop/server/ • http://msdn.microsoft.com/workshop/server/asp/ASPover.asp
MSDN • For orden skyld: Her er plasseringen i MSDN • ASP Object Model: • Platform SDK/Web Services/Internet Information Services SDK/Active Server Pages Guide/Visual Basic Object Model • Jscript • Plaform SDK/Tools and Languages/Scripting/Jscript • VBScript • Plaform SDK/Tools and Languages/Scripting/Vbscript