Further Web services with .NET and PHP

advertisement
Service Oriented Architectures for the Web
Service Oriented Architectures for the Web
Further Web Services
Dr Kevin McManus
http://staffweb.cms.gre.ac.uk/~mk05/soa
© 2015
University of Greenwich
1
Service Oriented Architectures for the Web
Talk About...
• Continuing from the previous PowerPoint
DOM programming to look at Web services
with .NET and PHP
• slides 3 – 14 were covered in greater detail earlier
• This time running from live HTTP servers
• With DOM programming to restructure and
combine XML
© 2015
University of Greenwich
2
Service Oriented Architectures for the Web
Visual Studio Ultimate 2013
fire up VS Ultimate
with a new C# project
Web Services are not
on the Framework 4.5
menu so choose
Web Application
untick this
© 2015
give it a sensible name and location on
your I:\ drive as this maps to the
stuiis.cms.gre.ac.uk
HTTP server
University of Greenwich
3
Service Oriented Architectures for the Web
Visual Studio Ultimate 2013
choose no
authentication
choose Web Forms
untick
press the button and send
email to request application
root on the IIS server
plenty of new to 2013 stuff
to sort out before we begin
© 2015
University of Greenwich
4
Service Oriented Architectures for the Web
skip the intro
because real programmers
don’t ask for directions
© 2015
University of Greenwich
5
Service Oriented Architectures for the Web
build the project
choose your favourite
ASP.NET active web pages
are .aspx files
all of this code is
generated for you
© 2015
University of Greenwich
Default.aspx is the default
home page
6
Service Oriented Architectures for the Web
ASP.NET Web Site
this URL is correct but this is what happens when
the application root is yet to be published
© 2015
University of Greenwich
7
Service Oriented Architectures for the Web
ASP.NET Web Site
once the application root is published we see
the now familiar responsive adaptive
placeholder running from a live URL
© 2015
University of Greenwich
8
Service Oriented Architectures for the Web
no need to press the
stop button as we are
running live
dive in, hack it about, and rebuild with cntrl shift B
then refresh your browser
© 2015
University of Greenwich
9
Service Oriented Architectures for the Web
ASP.NET Web Site
finally, a relatively
simple website
© 2015
University of Greenwich
10
Service Oriented Architectures for the Web
Add a Web Service
right click the project in the
Solution Explorer and
Add -> New Item
.NET web services are .asmx files
give the service a sensible name
© 2015
University of Greenwich
11
Service Oriented Architectures for the Web
add some usful
libraries to your new
Web service
rebuild and refresh your browser to
make sure that HelloWorld is working
before diving into some code
© 2015
University of Greenwich
12
Service Oriented Architectures for the Web
you may well need to
add some stanza’s to
your Web.config file
<protocols>
<add name="HttpSoap"/>
<add name="HttpSoap12"/>
add some stanzas to
<add name="HttpGet"/>
Web.config and rebuild
<add name="HttpPost"/>
</protocols>
© 2015
University of Greenwich
13
Service Oriented Architectures for the Web
use this database
table as a data source
© 2015
University of Greenwich
14
Service Oriented Architectures for the Web
.NET DataSet Web Service
using System.Data;
using System.Data.SqlClient;
instantiate a SqlConnection
[WebMethod]
to SQL Server
public DataSet lookupDataSet(string surname)
{
string conString = "server=sql-server;integrated security=SSPI;database=mk05";
SqlConnection sqlConn = new SqlConnection(conString);
instantiate a SqlCommand to
hold a SQL query
SqlCommand sqlCmd = sqlConn.CreateCommand();
sqlCmd.CommandType = CommandType.Text;
sqlCmd.CommandText = "SELECT FamilyName, GivenNames, Telephone FROM mk05.Directory
WHERE FamilyName LIKE '%"+surname+"%'";
SqlDataAdapter dataAdptr = new SqlDataAdapter();
dataAdptr.SelectCommand = sqlCmd;
DataSet dsStaff = new DataSet("phonebook");
dataAdptr.Fill(dsStaff, "staff");
return dsStaff ;
}
instantiate a SqlDataAdapter to
run the query and a DataSet to
hold the results
return the DataSet
© 2015
University of Greenwich
15
Service Oriented Architectures for the Web
lookupDataSet()
the DataSet is returned as
XML with a schema
included
good but not what we want
© 2015
University of Greenwich
16
Service Oriented Architectures for the Web
.NET XML Containers
• Three XML document stores each with different features
• XmlDocument
• the primary document store
• supports W3C standards for XML document (DOM), plus useful additional
features that make it easier to access the contents
• XmlDataDocument
• provides a bridge between XML and relational data by allowing the content to
be accessed as a DataSet instance as well as a standard XML document
• XPathDocument.
• fast and efficient document store designed to be accessed only using XPath
methods and the XPathNavigator
• XPathNavigator can be used over any of the three document stores
© 2015
University of Greenwich
17
Service Oriented Architectures for the Web
Telephone Directory Web Service
• Re-write the web service to return an XmlDocument
• instead of a data set
• Convert the data set read from SQL Server into a
string
• Load the string into an XmlDocument
© 2015
University of Greenwich
18
Service Oriented Architectures for the Web
.NET XmlDocument Web Service
using System.Xml;
instantiate a SqlConnection to
[WebMethod]
SQL Server
public XmlDocument lookupXmlDocument(string surname)
{
string conString = "server=sql-server;integrated security=SSPI;database=mk05";
SqlConnection sqlConn = new SqlConnection(conString);
instantiate a SqlCommand to
SqlCommand sqlCmd = sqlConn.CreateCommand();
hold a SQL query
sqlCmd.CommandType = CommandType.Text;
string sn = surname.Replace("'", "''");
sqlCmd.CommandText = "SELECT FamilyName, GivenNames, Telephone FROM mk05.Directory
WHERE FamilyName LIKE '%"+sn+"%'";
SqlDataAdapter dataAdptr = new SqlDataAdapter();
dataAdptr.SelectCommand = sqlCmd;
DataSet dsStaff = new DataSet("phonebook");
dataAdptr.Fill(dsStaff, "staff");
XmlDocument xmlDom = new XmlDocument();
xmlDom.LoadXml(dsStaff.GetXml());
return xmlDom;
}
© 2015
University of Greenwich
instantiate a SqlDataAdapter to
run the query and a DataSet to
hold the results
instantiate DOM, populate it
from the data set and return it
19
Service Oriented Architectures for the Web
lookupXmlDocument()
clean XML returned
we could easily manipulate
this XML further using DOM
programming
© 2015
University of Greenwich
20
Service Oriented Architectures for the Web
lookupXmlDocument()
XML is pretty printed but
this whitespace could cause
problems
© 2015
University of Greenwich
21
Service Oriented Architectures for the Web
XML Schema as DTD – directory.dtd
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE directory SYSTEM "directory.dtd">
<directory>
<person pid="FXC1" loc="Fox">
what if the XML schema we
<firstnames>Stewie</firstnames>
want does not match the
<surname>Griffin</surname>
namespace or structure
<telephone>6578</telephone>
</person>
from the database?
<person pid="HBC6" loc="Hanna-Barbera">
<firstnames>Betty</firstnames>
<surname>Rubble</surname>
<telephone>8719</telephone>
<!ELEMENT directory (person*)>
</person>
<!ELEMENT
person (firstnames, surname, telephone)>
<person pid="WBC8" loc="Warner
Brothers">
<!ATTLIST person
<firstnames>Bugs</firstnames>
pid ID #IMPLIED
<surname>Bunny</surname>
loc CDATA #IMPLIED
<telephone>1940</telephone>
>
</person>
<!ELEMENT firstnames (#PCDATA)>
</directory>
<!ELEMENT surname (#PCDATA)>
<!ELEMENT telephone (#PCDATA)>
© 2015
University of Greenwich
22
Service Oriented Architectures for the Web
lookupValidXmlDocument()
while we have no attributes
this is valid against
directory.dtd
© 2015
University of Greenwich
23
Service Oriented Architectures for the Web
.NET Valid XmlDocument Web Service
[WebMethod]
public XmlDocument lookupValidXmlDocument(string surname) instantiate a SqlConnection
SQL Server
{
string conString = "server=sql-server;integrated security=SSPI;database=mk05";
SqlConnection sqlConn = new SqlConnection(conString);
instantiate a SqlCommand
SqlCommand sqlCmd = sqlConn.CreateCommand();
sqlCmd.CommandType = CommandType.Text;
hold a SQL query
string sn = surname.Replace("'", "''");
sqlCmd.CommandText = "SELECT FamilyName, GivenNames, Telephone FROM mk05.StaffList
WHERE FamilyName LIKE '%" + sn + "%'";
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = sqlCmd;
DataTable dt = new DataTable();
da.Fill(dt);
to
to
instantiate SqlDataAdapter to run the
query and DataTable to hold the results
instantiate DOM with root
element <directory>
XmlDocument xmlDom = new XmlDocument();
xmlDom.AppendChild(xmlDom.CreateElement("", "directory", ""));
XmlElement xmlRoot = xmlDom.DocumentElement;
XmlElement xmlStaff, xmlFname, xmlSname, xmlTel;
XmlText xmlTxt;
string fname, sname, tel;
© 2015
University of Greenwich
create some handy
variables for what follows
24
Service Oriented Architectures for the Web
.NET Valid XmlDocument Web Service
foreach(DataRow r in dt.Rows)
{
fname = r["GivenNames"].ToString();
sname = r["FamilyName"].ToString();
tel = r["Telephone"].ToString();
loop over all rows in the DataTable
xmlStaff = xmlDom.CreateElement("person");
xmlFname = xmlDom.CreateElement("firstnames");
xmlTxt = xmlDom.CreateTextNode(fname);
xmlFname.AppendChild(xmlTxt);
xmlStaff.AppendChild(xmlFname);
xmlSname = xmlDom.CreateElement("surname");
xmlTxt = xmlDom.CreateTextNode(sname);
xmlSname.AppendChild(xmlTxt);
xmlStaff.AppendChild(xmlSname);
xmlTel = xmlDom.CreateElement("telephone");
xmlTxt = xmlDom.CreateTextNode(tel);
xmlTel.AppendChild(xmlTxt);
xmlStaff.AppendChild(xmlTel);
xmlRoot.AppendChild(xmlStaff);
}
return xmlDom;
extract values from each row
into handy variables
this is boilerplate code for
stiching together an XML
DOM as a hierarchical tree
return DOM to the client
}
© 2015
University of Greenwich
25
Service Oriented Architectures for the Web
.NET Valid XmlDocument Web Service
• The boilerplate code to construct an XML
DOM object is something that will become
very familiar
• Let’s add some more code to add attributes
into the DOM
© 2015
University of Greenwich
26
Service Oriented Architectures for the Web
.NET Valid XmlDocument Web Service
[WebMethod]
public XmlDocument lookupValidXmlDocument(string surname)
{
string conString = "server=sql-server;integrated security=SSPI;database=mk05";
SqlConnection sqlConn = new SqlConnection(conString);
SqlCommand sqlCmd = sqlConn.CreateCommand();
sqlCmd.CommandType = CommandType.Text;
string sn = surname.Replace("'", "''");
sqlCmd.CommandText = "SELECT id, FamilyName, GivenNames, Telephone, Location
FROM mk05.StaffList WHERE FamilyName LIKE '%" + sn + "%'";
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = sqlCmd;
DataTable dt = new DataTable();
da.Fill(dt);
this is much the same as before but with
more data included in the SQL query and
some more temporary variables
XmlDocument xmlDom = new XmlDocument();
xmlDom.AppendChild(xmlDom.CreateElement("", "directory", ""));
XmlElement xmlRoot = xmlDom.DocumentElement;
XmlElement xmlStaff, xmlFname, xmlSname, xmlTel;
XmlText xmlTxt;
XmlAttribute xmlPid, xmlLoc;
string fname, sname, tel, pid, loc;
© 2015
University of Greenwich
27
Service Oriented Architectures for the Web
foreach (DataRow r in dt.Rows)
{
fname = r["GivenNames"].ToString();
sname = r["FamilyName"].ToString();
tel = r["Telephone"].ToString();
pid = "GWS" + r["id"].ToString();
loc = r["Location"].ToString();
xmlStaff = xmlDom.CreateElement("person");
xmlPid = xmlDom.CreateAttribute("pid");
xmlPid.Value = pid;
xmlStaff.Attributes.Append(xmlPid);
xmlLoc = xmlDom.CreateAttribute("loc");
xmlLoc.Value = loc;
xmlStaff.Attributes.Append(xmlLoc);
xmlFname = xmlDom.CreateElement("firstnames");
xmlTxt = xmlDom.CreateTextNode(fname);
xmlFname.AppendChild(xmlTxt);
xmlStaff.AppendChild(xmlFname);
xmlSname = xmlDom.CreateElement("surname");
xmlTxt = xmlDom.CreateTextNode(sname);
xmlSname.AppendChild(xmlTxt);
xmlStaff.AppendChild(xmlSname);
xmlTel = xmlDom.CreateElement("telephone");
xmlTxt = xmlDom.CreateTextNode(tel);
xmlTel.AppendChild(xmlTxt);
xmlStaff.AppendChild(xmlTel);
xmlRoot.AppendChild(xmlStaff);
}
©return
2015 xmlDom;
}
University of Greenwich
the person id attribute must
be a valid token
this boilerplate code now
builds "pid" and "loc"
attributes into the <person>
element
28
Service Oriented Architectures for the Web
lookupValidXmlDocument()
we could consider changing
directory.dtd to make these
attributes #REQUIRED
© 2015
University of Greenwich
29
Service Oriented Architectures for the Web
PHP Web Service
• Create a similar Web service with PHP
• with a different but similar MySQL database
SELECT * FROM CartoonCharacters
© 2015
University of Greenwich
30
Service Oriented Architectures for the Web
searchCC.php
this Web service is valid
against directory.dtd
© 2015
University of Greenwich
31
Service Oriented Architectures for the Web
PHP Web Service – searchCC.php
<?php
header('Content-type: text/xml');
respond with XML mime type
accept POST and GET REST
if ( isset($_REQUEST['name']) ) {
$nq = trim($_REQUEST['name']);
if ( preg_match("/[^a-zA-Z0-9 \-']|^$/", $nq) ) die ('<directory/>');
} else {
die ('<directory/>');
validate input and protect
}
against SQL injection
require '/home/mkg01/include/studb.php';
$link = mysql_connect($host, $user, $passwd) or die
('<directory><error>'.mysql_error().'</error></directory>');
connect to MySQL
mysql_select_db($dbName) or die
('<directory><error>'.mysql_error().'</error></directory>');
with exceptions in
$query = 'SELECT ccid, firstname, familyname, phone, studio
XML
FROM CartoonCharacters
WHERE familyname RLIKE "'.$nq.'"';
$result = mysql_query($query, $link) or die
('<directory><error>'.mysql_error().'</error></directory>');
$xmlDom = new DOMDocument();
$xmlDom->appendChild($xmlDom->createElement('directory'));
$xmlRoot = $xmlDom->documentElement;
instantiate a DOM object with
<directory> as root element
© 2015
University of Greenwich
32
Service Oriented Architectures for the Web
PHP Web Service – searchCC.php
if ( mysql_num_rows($result) > 0 ) {
if the query returned data then
loop over all rows in the result
while ( $row = mysql_fetch_assoc($result) ) {
$xmlPerson = $xmlDom->createElement('person');
$xmlPid = $xmlDom->CreateAttribute('pid');
$xmlPid->value = 'CC' . $row['ccid'];
$xmlPerson->appendChild($xmlPid);
$xmlLoc = $xmlDom->CreateAttribute('loc');
$xmlLoc->value = $row['studio'];
$xmlPerson->appendChild($xmlLoc);
$xmlFname = $xmlDom->createElement('firstnames');
$xmlTxt = $xmlDom->createTextNode($row['firstname']);
$xmlFname->appendChild($xmlTxt);
$xmlPerson->appendChild($xmlFname);
$xmlSname = $xmlDom->createElement('surname');
$xmlTxt = $xmlDom->createTextNode($row['familyname']);
$xmlSname->appendChild($xmlTxt);
$xmlPerson->appendChild($xmlSname);
$xmlTel = $xmlDom->createElement('telephone');
$xmlTxt = $xmlDom->createTextNode($row['phone']);
$xmlTel->appendChild($xmlTxt);
$xmlPerson->appendChild($xmlTel);
$xmlRoot->appendChild($xmlPerson);
}
}
echo $xmlDom->saveXML();
?>
© 2015
this is much the same
boilerplate as the
previous C# Web method
return the DOM object to the client
University of Greenwich
33
Service Oriented Architectures for the Web
searchCC.php
this service works with
GET and POST REST
but not SOAP
the XML has no added
whitespace
this may prove to be convenient
© 2015
University of Greenwich
34
Service Oriented Architectures for the Web
XML Schema as DTD – directory.dtd
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE directory SYSTEM "directory.dtd">
<directory>
<error>Failed to connect to MySQL</error >
</directory>
modify the DTD to handle
exceptions and require
attributes
<!ELEMENT directory (person | error)*>
<!ELEMENT person (firstnames, surname, telephone)>
<!ATTLIST person
pid ID #REQUIRED
loc CDATA #REQUIRED
>
<!ELEMENT error (#PCDATA)>
<!ELEMENT firstnames (#PCDATA)>
<!ELEMENT surname (#PCDATA)>
<!ELEMENT telephone (#PCDATA)>
© 2015
University of Greenwich
35
Service Oriented Architectures for the Web
XML Schema as XSD – directory.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="directory">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="person"/>
<xs:element ref="error"/>
</xs:choice>
</xs:complexType>
</xs:element>
much the same
<xs:element name="error" type="xs:string"/>
schema as the DTD
<xs:element name="firstnames" type="xs:string"/>
<xs:element name="person">
<xs:complexType>
<xs:sequence>
<xs:element ref="firstnames"/>
<xs:element ref="surname"/>
<xs:element ref="telephone"/>
</xs:sequence>
<xs:attribute name="pid" type="xs:ID" use="required"/>
<xs:attribute name="loc" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="surname" type="xs:string"/>
<xs:element name="telephone" type="xs:short"/>
</xs:schema>
© 2015
University of Greenwich
36
Service Oriented Architectures for the Web
Reading a Web Service
• Create a .NET web service that accesses XML from a URL
• that URL could itself be a web service
• searchCC.php reads a telephone directory from a MySQL
database
• returns a DOM object
• is a RESTful web service
• readValidXmlDocument is a .NET Web method that simply
forwards a query to searchCC.php
• uses an ASP.NET string reader
• validates the results against directory.xsd
© 2015
University of Greenwich
37
Service Oriented Architectures for the Web
.NET XmlReader
[WebMethod]
public XmlDocument readValidXmlDocument(string surname)
configure XmlReaderSettings
{
XmlReaderSettings xmlRS = new XmlReaderSettings();
xmlRS.ValidationType = ValidationType.Schema;
xmlRS.Schemas.Add("", "http://stuweb.cms.gre.ac.uk/~mk05/web/soa/directory.xsd");
string getURL = "http://stuweb.cms.gre.ac.uk/~mk05/web/soa/searchCC.php?name=" + surname;
XmlDocument xmlDom = new XmlDocument();
build GET REST string
try
{
XmlReader xmlR = XmlReader.Create(new XmlTextReader(getURL), xmlRS);
xmlDom.Load(xmlR);
read and validate results from
}
catch ( Exception e )
the PHP Web service
{
xmlDom.AppendChild(xmlDom.CreateElement("", "directory", ""));
XmlElement xmlRoot = xmlDom.DocumentElement;
XmlElement xmlErr = xmlDom.CreateElement("error");
XmlText xmlTxt = xmlDom.CreateTextNode("invalid: " + e.Message);
xmlErr.AppendChild(xmlTxt);
handle exceptions including
xmlRoot.AppendChild(xmlErr);
validation failure
}
return xmlDom;
}
© 2015
University of Greenwich
38
Service Oriented Architectures for the Web
readValidXmlDocument()
this data is provided by a PHP
Web service from a MySQL table
© 2015
University of Greenwich
39
Service Oriented Architectures for the Web
readValidXmlDocument()
$xmlPerson = $xmlDom->createElement('persons');
alter the PHP so that it
returns XML that is not valid
against directory.xsd
this validation exception is
caught and handled
© 2015
University of Greenwich
40
Service Oriented Architectures for the Web
XML Aggregation
• Web services are used to create interfaces to data resources
• Using DOM structures we can operate on the data
• Data from many sources can be aggregated into a single DOM
object
• .NET provides alternative programmatic approaches to XML
• DataSet
• XmlNavigator
• XSLT
© 2015
University of Greenwich
41
Service Oriented Architectures for the Web
lookupValidXmlDocument2()
this data is provided by a C# method
from a MS SQL Server table
this data is provided by a PHP Web
service from a MySQL table via a C#
method
© 2015
University of Greenwich
42
Service Oriented Architectures for the Web
XML Aggregation – lookupValidXmlDocument2
instance DOM1 to hold results
from lookupValidXmlDocument()
[WebMethod]
public XmlDocument lookupValidXmlDocument2(string surname)
{
XmlDocument xmlDom1 = new XmlDocument();
xmlDom1 = lookupValidXmlDocument(surname);
XmlDocument xmlDom2 = new XmlDocument();
xmlDom2 = readValidXmlDocument(surname);
instance DOM2 to hold results
from readValidXmlDocument()
foreach (XmlNode xmlNode2 in xmlDom2.DocumentElement.ChildNodes)
{
XmlNode xmlNode1 = xmlDom1.ImportNode(xmlNode2, true);
loop over all
xmlDom1.DocumentElement.AppendChild(xmlNode1);
nodes in DOM2
}
return xmlDom1;
}
this is only successful because
both sources provde valid XML
© 2015
University of Greenwich
import nodes into DOM1
43
Service Oriented Architectures for the Web
XML Aggregation
• What if we need to aggregate XML with
different schemas?
• can't simply import the nodes
• DOM programing makes this relatively
straightforward
• Loop over the nodes in the DOM we wish to
import
• extract the node content into new nodes that
belong to the DOM we are merging into
© 2015
University of Greenwich
44
Service Oriented Architectures for the Web
XML Aggregation with DOM Programming
// Create some pointers
XmlElement xmlStaff, xmlEle;
XmlText xmlTxt;
// Loop over the staff nodes in the second XML document
foreach ( XmlNode xmlStaffNode in xmlDom2.DocumentElement.ChildNodes )
{
// Create a new staff element
xmlStaff = xmlDom1.CreateElement(xmlStaffNode.Name);
// Loop over the children of the staff element in the second document
foreach ( XmlNode xmlNode in xmlStaffNode.ChildNodes )
{
// Create new child elements
xmlEle = xmlDom1.CreateElement(xmlNode.Name);
xmlTxt = xmlDom1.CreateTextNode(xmlNode.InnerText);
xmlEle.AppendChild(xmlTxt);
xmlStaff.AppendChild(xmlEle);
}
// Append the new staff element to the first XML document
xmlDom1.DocumentElement.AppendChild(xmlStaff);
}
© 2015
University of Greenwich
45
Service Oriented Architectures for the Web
XML Aggregation using Nginx Server
• Our Nginx HTTP server deliberately has no database
connection
• for educational purposes
• Aggregate C# and PHP services to provide a name
search spanning both MSSQL Server and MySQL
databases
• could simply implement a proxy to
lookupValidXmlDocument2
• Use PHP to forward a query to the two services and
merge the result
• brings together much of what we have looked at
previously with SOAP and REST consumption of
heterogeneous services
© 2015
University of Greenwich
46
searchCombined.php
<?php
header('Content-type: text/xml');
Service Oriented Architectures for the Web
start with XML mime header
massage inputs
if ( isset($_REQUEST['name']) ) {
$nq = trim($_REQUEST['name']);
if ( preg_match("/[^a-zA-Z0-9 \-']|^$/",$nq) ) die ('<directory/>');
} else {
die ('<directory/>');
instance a SOAP clinet and
}
use it to fill DOM1
$args = array('surname'=>$nq);
$client = new SoapClient('http://stuiis.cms.gre.ac.uk/.../stafflist.asmx?WSDL');
$xmls = $client->lookupValidXmlDocument($args)->lookupValidXmlDocumentResult->any;
$xmlDom1 = new DOMDocument();
$xmlDom1->loadXML($xmls, LIBXML_NOBLANKS);
$url = 'http://stuweb.cms.gre.ac.uk/.../searchCC.php?name='.$nq;
$xmlDom2 = new DOMDocument();
$xmlDom2->load($url);
load DOM2 directly
from a GET URL
$xmlRoot1 = $xmlDom1->documentElement;
foreach ( $xmlDom2->documentElement->childNodes as $node2 ) {
$node1 = $xmlDom1->importNode($node2,true);
import DOM2
$xmlRoot1->appendChild($node1);
}
echo $xmlDom1->saveXML();
?>
return DOM1 to the client
nodes into DOM1
Service Oriented Architectures for the Web
searchCombined.php
this data is provided by a C# Web
service from a MS SQL Server table
this data is provided by a PHP Web
service from a MySQL table via a C#
method
© 2015
University of Greenwich
48
Service Oriented Architectures for the Web
Web Service Driven Web Application
• An easy way to use these services to drive a
Web application is to apply some XSLT
• May be server side or client side processed
• Server side is easier to develop
© 2015
University of Greenwich
49
Service Oriented Architectures for the Web
stafflist.php
XSLT has done more than
just re-order these
© 2015
University of Greenwich
50
Service Oriented Architectures for the Web
stafflist.php
<?php echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" ?> <!DOCTYPE html PUBLIC "//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html
xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-gb">
<head><title>Staff List</title></head><body>
<h1>Staff List</h1>
<form method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>">
sticky form posts
<p>
back to itself
<?php $nq = ( isset($_POST['name']) ) ? $_POST['name'] : ''; ?>
<input type="text" name="name" value="<?php echo $nq ?>"/>
<input type="submit" />
use searchCombined.php
</p><p>
to access the services
<?php
if ( isset($_POST['name']) ) {
$url = 'http://stu-nginx.cms.gre.ac.uk/~mk05/soa/searchCombined.php?name='.$nq;
$xmlDoc = new DOMDocument();
$xmlDoc->load($url);
$xslt = new XSLTProcessor(); $xslDoc = new DOMDocument();
$xslDoc->load('stafflist.xsl', LIBXML_NOCDATA);
$xslt->importStylesheet($xslDoc);
echo $xslt->transformToXML($xmlDoc);
}
?>
</p></form></body></html>
© 2015
University of Greenwich
import XSLT file into
XSLTProcessor
XSLT process the XML
51
Service Oriented Architectures for the Web
SQL Insert Web Service
• So far we have been retrieving information
from various databases
• often we want to insert or modify
• Need to take extra care when opening up a
database to such potential vulnerability
• careful input validation
• authentication
© 2015
University of Greenwich
52
Service Oriented Architectures for the Web
.NET SQL Server Insert Web Service
[WebMethod]
public string insertRecord(string txtFirstname, string txtSurname, string txtTel,
string txtLoc, string txtUname, string txtUpwd)
input data
{
includes
authentication credentials
bool
bool
bool
bool
bool
bool
bl_fn
bl_sn
bl_tp
bl_lc
bl_un
bl_up
=
=
=
=
=
=
Regex.IsMatch(txtFirstname,"[^a-zA-Z0-9 '-]|^$", RegexOptions.None);
Regex.IsMatch(txtSurname,"[^a-zA-Z0-9 '-]|^$", RegexOptions.None);
Regex.IsMatch(txtTel,"[^0-9]|^$", RegexOptions.None);
!Regex.IsMatch(txtLoc,"^([A-Z]{2})$", RegexOptions.None);
Regex.IsMatch(txtUname,"[^a-zA-Z0-9]|^$", RegexOptions.None);
Regex.IsMatch(txtUpwd,"[^a-zA-Z0-9]|^$", RegexOptions.None);
if ( bl_fn || bl_sn || bl_tp || bl_lc || bl_un || bl_up)
{
string str_idvf = "Input data validation failure: ";
if (bl_fn) str_idvf += txtFirstname + " ";
if (bl_sn) str_idvf += txtSurname + " ";
if (bl_tp) str_idvf += txtTel + " ";
if (bl_lc) str_idvf += txtLoc + " ";
if (bl_un) str_idvf += txtUname + " ";
if (bl_up) str_idvf += txtUpwd + " ";
return str_idvf;
}
© 2015
University of Greenwich
regular expressions filter
incoming strings
build input validation
failure message and
return it to the client
53
Service Oriented Architectures for the Web
.NET SQL Server Insert Web Service
bool bl_unc = !Regex.IsMatch(txtUname,"^([a-z]{6})$", RegexOptions.None);
bool bl_upc = !Regex.IsMatch(txtUpwd,"^([a-z]{6})$", RegexOptions.None);
if (bl_unc || bl_upc) {
this code should be replaced with actual
return "Authentication failure";
} else {
authentication against stored credentials
short tnumber = short.Parse(txtTel);
try
{
string conString = "server=sql-server;integrated security=SSPI;database=mk05";
SqlConnection sqlConn = new SqlConnection(conString);
sqlConn.Open();
apostrophes are
SqlCommand insertCmd = sqlConn.CreateCommand();
valid characters
insertCmd.CommandType = CommandType.Text;
string txtSn = txtSurname.Replace("'", "''");
string txtFn = txtFirstname.Replace("'", "''");
insertCmd.CommandText = "INSERT INTO mk05.StaffList(FamilyName, GivenNames,
Telephone, Location) VALUES
('" + txtSn + "', '" + txtFn + "', " + tnumber + ", '" + txtLoc + "')";
insertCmd.ExecuteNonQuery();
this is the preferred return value
return "Record inserted";
}
catch ( Exception e) { return "Insert failure" + e; }
}
expect exceptions and handle them
}
© 2015
University of Greenwich
54
Service Oriented Architectures for the Web
insertRecord
© 2015
University of Greenwich
55
Service Oriented Architectures for the Web
Conclusions
• It's all so easy
• especially when it's RESTful
• Visual Studio does most of the work
• wish we had VS for PHP
• PHPeclipse, Netbeans
• These examples show main points
• still some problems to be resolved
© 2015
University of Greenwich
56
Service Oriented Architectures for the Web
Questions?
© 2015
University of Greenwich
57
Download