|
Purpose The purpose of this project is to demonstrate how to create a .Net 3.5 web service from scratch. .Net AJAX will be used in conjunction with JScript 8.0 and one ASP.NET web page. No web page post-backs will be done (since .Net AJAX and JScript will be used). Other things, such as working with console applications are also covered in this project. How I Approach This Project As a web researcher/developer I had the opportunity to get rolling with .Net 3.5 months before it was released. Because of this I've developed a variety of ASP.NET 3.5 web applications; this is among one of them which was taken out of a larger context. So, if you see me mention something that seems odd (such as the web service communicating with a command-line (console) application, breaking up StdOut of that application and stuffing that into the web service response) you can skip it if you want; but it may be handy to know for the sake of knowing how it's done under the .Net 3.5 umbrella. |
![]() (Enlarge) |
Open Visual Studio 2008. | |
![]() (Enlarge) |
Under the File Menu select "New Web Site". | |
![]() (Enlarge) |
|
|
![]() (Enlarge) |
You will notice that a default web page has been created (Default.aspx). We are going to rename the default web page. Under Solution Explorer, right-click on "Default.aspx". |
|
![]() (Enlarge) |
From the pop-up menu, select "Rename". | |
![]() (Enlarge) |
Rename the filename to "PDFCreate.aspx". | |
![]() (Enlarge) |
|
|
![]() (Enlarge) |
Now we are going to create a folder to place the JScript into.
Under Solution Explorer, right-click on ""\\webserverA\siteB\folder". From the pop-up menu select "New Folder". |
|
![]() (Enlarge) |
Specify the folder name as "Javascript". | |
![]() (Enlarge) |
Now we are going to add a Jscript file inside of the folder you just created.
|
|
![]() (Enlarge) |
Now we have a blank source code page to work with. | |
![]() (Enlarge) |
|
|
![]() (Enlarge) |
Now we are going to create the web service. Under Solution Explorer, right-click on ""\\webserverA\siteB\folder". From the pop-up menu select "Add New Item". |
|
![]() (Enlarge) |
|
|
![]() (Enlarge) |
The source code page, containing generic source code should now be displayed. Remove the generic source code. |
|
![]() (Enlarge) |
|
|
![]() (Enlarge) |
Congratulations, all the pieces are now in place! Now let's perform a build. Under the Build menu, select "Build Web Site". |
|
![]() (Enlarge) |
The build should succeed and you can now begin experimenting with PDFCreate.aspx by typing in the URL of that web page in your web browser and studying the output. If <HTMLDoc> is not installed and configured properly on the web server, the web service will not work. | |
function sendDataAsXML_SOAP() {
var req_params = "", url = "", number = 0, type = "";
/* Configure Parameters */
url = "http://www.somesite.com/folder/webService.asmx";
number = 21;
type = "newest";
req_params = "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body><ajaxDataRequest xmlns=\"serviceAjax\">";
req_params = req_params + "<articleNumber>" + number + "</articleNumber>";
req_params = req_params + "<articleType>" + type + "</articleType>";
req_params = req_params + "</ajaxDataRequest></soap:Body></soap:Envelope>";
/* Send XML/SOAP Request To Web Service Using Browser's Javascript DOM */
try { ajax_request = new XMLHttpRequest(); }
catch (trymicrosoft) {
try { ajax_request = new ActiveXObject("Msxml2.XMLHTTP"); }
catch (othermicrosoft) {
try { ajax_request = new ActiveXObject("Microsoft.XMLHTTP"); }
catch (failed) { ajax_request = false; }
}
}
ajax_request.open("POST", url, true);
ajax_request.setRequestHeader("Content-Type", "text/xml;charset=utf-8");
ajax_request.onreadystatechange = receiveXML_SOAPData;
ajax_request.send(req_params);
}
var xmlCount = 0; xmlName = new Array(); xmlValue = new Array();
function receiveXML_SOAPData() {
if (ajax_request.readyState == 4) {
if (ajax_request.status == 200) {
/* Parse The Response Data */
captureXML(ajax_request.responseText);
/* Alert The Response Data */
for (x = 0; x < xmlName.length; x++) {
alert(xmlName[x] + " - " + xmlValue[x]);
}
}
}
}
function captureXML(xmlStream) {
/* XML put into a string is passed to this function as xmlStream */
var items, xmlTree, xmlDoc;
var x_name = "", x_value = "";
var xmlBrowseType = 0, x_drop = 0, x_count = 0;
if (window.ActiveXObject) {
/* Internet Explorer */
xmlBrowseType = 1;
xmlDoc = new ActiveXObject("MSXML2.DomDocument");
xmlDoc.loadXML(xmlStream);
}
else {
/* Mozilla / Firefox */
xmlBrowseType = 2;
var parser = new DOMParser();
xmlDoc = parser.parseFromString(xmlStream.replace(/\t/g,"").replace(/\v/g, ""), "text/xml");
}
xmlTree = xmlDoc.documentElement;
if (xmlTree.hasChildNodes()) {
if (xmlBrowseType == 1) {
/* Internet Explorer */
y_count = 0;
do {
x_drop = 0; y_drop = 0; x_count = 0;
try {
x_name = xmlTree.childNodes[x_count].nodeName;
x_value = xmlTree.getElementsByTagName(x_name)[y_count].childNodes[y_count].nodeValue;
}
catch(onerror) { x_drop = 1; y_drop = 1; }
do {
try {
x_name = xmlTree.childNodes[x_count].nodeName;
x_value = xmlTree.getElementsByTagName(x_name)[y_count].childNodes[y_count].nodeValue;
}
catch(onerror) { x_drop = 1; x_value = null; }
xmlSave(x_name, x_value); x_name = ""; x_value = "";
x_count = x_count + 1;
} while (x_drop == 0);
y_count = y_count + 1;
} while (y_drop == 0);
}
else {
/* Mozilla / Firefox */
y_count = 0;
do {
x_drop = 0; y_drop = 0; x_count = 0;
try {
x_name = xmlTree.childNodes[x_count].nodeName;
x_value = xmlTree.childNodes[x_count].childNodes[y_count].nodeValue;
}
catch(onerror) { x_drop = 1; y_drop = 1; }
do {
try {
x_name = xmlTree.childNodes[x_count].nodeName;
x_value = xmlTree.childNodes[x_count].childNodes[y_count].nodeValue;
}
catch(onerror) { x_drop = 1; x_value = null; }
xmlSave(x_name, x_value); x_name = ""; x_value = "";
x_count = x_count + 1;
} while (x_drop == 0);
y_count = y_count + 1;
} while (y_drop == 0);
}
}
}
<script type="text/javascript">
//<![CDATA[
var PDFAjaxWebService=function() {
PDFAjaxWebService.initializeBase(this);
this._timeout = 0;
this._userContext = null;
this._succeeded = null;
this._failed = null;
}
PDFAjaxWebService.prototype={
_get_path:function() {
var p = this.get_path();
if (p) return p;
else return PDFAjaxWebService._staticInstance.get_path();},
ajaxPDFGenerator:function(httpURL,httpURLVirtual,rawTxt,succeededCallback, failedCallback, userContext) {
/// <param name="httpURL" type="String">System.String</param>
/// <param name="httpURLVirtual" type="String">System.String</param>
/// <param name="rawTxt" type="String">System.String</param>
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param>
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param>
/// <param name="userContext" optional="true" mayBeNull="true"></param>
return this._invoke(this._get_path(), 'ajaxPDFGenerator',false,{httpURL:httpURL,httpURLVirtual:httpURLVirtual,rawTxt:rawTxt},succeededCallback,failedCallback,userContext); }}
PDFAjaxWebService.registerClass('PDFAjaxWebService',Sys.Net.WebServiceProxy);
PDFAjaxWebService._staticInstance = new PDFAjaxWebService();
PDFAjaxWebService.set_path = function(value) {
PDFAjaxWebService._staticInstance.set_path(value); }
PDFAjaxWebService.get_path = function() {
/// <value type="String" mayBeNull="true">The service url.</value>return PDFAjaxWebService._staticInstance.get_path();}
PDFAjaxWebService.set_timeout = function(value) {
PDFAjaxWebService._staticInstance.set_timeout(value); }
PDFAjaxWebService.get_timeout = function() {
/// <value type="Number">The service timeout.</value>
return PDFAjaxWebService._staticInstance.get_timeout(); }
PDFAjaxWebService.set_defaultUserContext = function(value) {
PDFAjaxWebService._staticInstance.set_defaultUserContext(value); }
PDFAjaxWebService.get_defaultUserContext = function() {
/// <value mayBeNull="true">The service default user context.</value>
return PDFAjaxWebService._staticInstance.get_defaultUserContext(); }
PDFAjaxWebService.set_defaultSucceededCallback = function(value) {
PDFAjaxWebService._staticInstance.set_defaultSucceededCallback(value); }
PDFAjaxWebService.get_defaultSucceededCallback = function() {
/// <value type="Function" mayBeNull="true">The service default succeeded callback.</value>
return PDFAjaxWebService._staticInstance.get_defaultSucceededCallback(); }
PDFAjaxWebService.set_defaultFailedCallback = function(value) {
PDFAjaxWebService._staticInstance.set_defaultFailedCallback(value); }
PDFAjaxWebService.get_defaultFailedCallback = function() {
/// <value type="Function" mayBeNull="true">The service default failed callback.</value>
return PDFAjaxWebService._staticInstance.get_defaultFailedCallback(); }
PDFAjaxWebService.set_path("/folder/PDFAjaxWebService.asmx");
PDFAjaxWebService.ajaxPDFGenerator= function(httpURL,httpURLVirtual,rawTxt,onSuccess,onFailed,userContext) {
/// <param name="httpURL" type="String">System.String</param>
/// <param name="httpURLVirtual" type="String">System.String</param>
/// <param name="rawTxt" type="String">System.String</param>
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param>
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param>
/// <param name="userContext" optional="true" mayBeNull="true"></param>
PDFAjaxWebService._staticInstance.ajaxPDFGenerator(httpURL,httpURLVirtual,rawTxt,onSuccess,onFailed,userContext); }
var gtc = Sys.Net.WebServiceProxy._generateTypedConstructor;
if (typeof(XMLPDFDataBlock) === 'undefined') {
var XMLPDFDataBlock=gtc("XMLPDFDataBlock");
XMLPDFDataBlock.registerClass('XMLPDFDataBlock');
}
//]]>
</script>
<script type="text/javascript">
//<![CDATA[Sys.WebForms.PageRequestManager._initialize('ajaxClientComponentMgr', document.getElementById('form1'));
Sys.WebForms.PageRequestManager.getInstance()._updateControls([], [], [], 90);
//]]>
</script>
PDFAjaxWebService.ajaxPDFGenerator(httpURL, httpURLVirtual, rawTxt, responseSuccessPDF, responseFailPDF, "text/xml");
function responseSuccessPDF(response) {
/* Handle response data which has been transformed from XML/SOAP into class hierarchy */
alert(response.xmlNodeNameA); // Substitute xmlNodeNameA with an actual XML node name which contains a value
}
Public Function ajaxPDFGenerator(ByVal httpURL As String, ByVal httpURLVirtual As String, ByVal rawTxt As String) As XMLPDFDataBlock
' Our "XML/SOAP" ClassPublic Class XMLPDFDataBlock
' The following basically allows you to have an unlimited number of "child nodes" inside what may be
' considered the parent node "generationResultsBin".
Private _generationResultsBin() As String
Public Property generationResultsBin() As String()
Get
Return _generationResultsBin
End Get
Set(ByVal value() As String)
_generationResultsBin = value
End Set
End Property
' This is the equivalent of a single XML node, which holds one value which is of the type "string".
Private _generationResultsMsg As String
Public Property generationResultsMsg() As String
Get
Return _generationResultsMsg
End Get
Set(ByVal value As String)
_generationResultsMsg = value
End Set
End Property
' This is the equivalent of a single XML node, which holds one value which is of the type "string".
Private _generationResultsURL As String
Public Property generationResultsURL() As String
Get
Return _generationResultsURL
End Get
Set(ByVal value As String)
_generationResultsURL = value
End Set
End Property
End Class
' Our custom-defined "XML/SOAP" class Dim xmlResponse As New XMLPDFDataBlock ' Define an array (which can be infinite in size less message transport size restrictions of the XML/SOAP message itself) to populate with one-dimensional data Dim generationResultsBin(2) As String generationResultsBin(1) = "Child Node 1 Data" generationResultsBin(2) = "Child Node 2 Data" ' Populate class data With xmlResponse .generationResultsMsg = "This is a test" .generationResultsURL = "http://www.somesite.com/" .generationResultsBin = generationResultsBin End With ' Return the data Return xmlResponse
' Call htmldoc and have it return PDF stream blocks translated from the temporary file containing html code
Dim localTempLocation As String = "\\webserverA\siteB\folder\temppdf.txt"
Dim externalProcessPageVirtual As ProcessStartInfo = New ProcessStartInfo("htmldoc", "--quiet --webpage -t pdf " & localTempLocation)
externalProcessPageVirtual.RedirectStandardOutput = True ' Grab StdOut
externalProcessPageVirtual.RedirectStandardError = True ' Grab any errors (StdErr) that may come up if needed although not handled in this example
externalProcessPageVirtual.CreateNoWindow = True ' No need to create a window for this operation
externalProcessPageVirtual.UseShellExecute = False ' We want the raw output
Dim runProcessPageVirtual As Process = Process.Start(externalProcessPageVirtual)
runProcessPageVirtual.Start()
Dim generationResultsBinTemp As String = ""
generationResultsBinTemp = runProcessPageVirtual.StandardOutput.ReadToEnd
Try ' Create a few child nodes for <generationResultsBin></generationResultsBin> Dim parseFinished As Integer = 0 Dim lenBoundary As Integer = 2500 ' Maximum size of a child node before a new child node is created which holds a fragment of StandardOutput Dim maximumNodeSize As Integer = 30000 ' Maximum size of all child nodes to be transported. If you want the to be able to transport a SOAP message much larger, you will need to make changes on the server, MaxRequestLength, etc. If generationResultsBinTemp.Length < maximumNodeSize Then maximumNodeSize = generationResultsBinTemp.Length End If Do Until parseFinished >= maximumNodeSize If parseFinished + lenBoundary >= maximumNodeSize Then ReDim Preserve generationResultsBin(UBound(generationResultsBin) + 1) generationResultsBin(UBound(generationResultsBin)) = Mid(generationResultsBinTemp, parseFinished + 1, maximumNodeSize) Else ReDim Preserve generationResultsBin(UBound(generationResultsBin) + 1) generationResultsBin(UBound(generationResultsBin)) = Mid(generationResultsBinTemp, parseFinished + 1, lenBoundary) End If parseFinished = parseFinished + lenBoundary Loop Catch ex As Exception generationResultsMsg = Replace(ex.ToString, vbCrLf, "\n") End Try generationResultsURL = ""