MSCF/CMU 1 More on Web Services Maintaining State Legacy Code Asynchronous Calls
Dec 21, 2015
MSCF/CMU 2
State Management
• Web Service objects are single call objects
• The object is created and destroyed on each visit
• Client Activated objects hold state associated with each client
• How can we do the same with Web Services?
• Use an Http Session object
MSCF/CMU 3
State Management Example
• Suppose we need a web service object to store a person’s name.
• The name is to be available over many visits from the same client.
• More than one client can use the service at the same time.
MSCF/CMU 4
Step by step
1. Write the remote object that uses a session object
2. Compile to a .dll and store in a directory named bin
3. Write a .asmx file and store it in the directory immediately above bin
4. Build a virtual directory named PersonName and point it at the directory immediately above bin
MSCF/CMU 5
Step by step
5. Visit http://localhost/PersonName
6. Click the .asmx file
7. Experiment with the service
8. Download the WSDL document
9. Run wsdl and generate a C# proxy
10. Compile the proxy to a .dll
11. Write a client with cookies enabled
12. Compile with csc –r:theProxy.dll MyClient.cs
MSCF/CMU 6
The Web Serviceusing System;using System.Runtime.Remoting.Lifetime;using System.Web.Services;
namespace SessionDemo{
public class PersonName : System.Web.Services.WebService {
[WebMethod(EnableSession=true)] public void setName(String n) {
// write the name to the Session object
Session["PersonName"] = n; }
MSCF/CMU 7
[WebMethod(EnableSession=true)] public String getName()
{ // read from the session object String n = (String)Session["PersonName"]; return n; }
}}
MSCF/CMU 8
PersonName.asmx
<%@ WebService Language="c#"
Class="SessionDemo.PersonName"
CodeBehind="PersonName.cs" %>
The pointer to the .cs file is misleading. This is used by Visual Studio to switch between views. We are not using Visual Studio here.
MSCF/CMU 9
The Clientusing System;
public class PersonNameClient {
static void Main(string[] args){
Console.WriteLine("Visit http://localhost/PersonName");
PersonName p = new PersonName(); p.CookieContainer = new System.Net.CookieContainer();
MSCF/CMU 10
// make 2000 visits
for(int k = 0; k < 2000; k++) { p.setName(""+k); String s = p.getName(); Console.WriteLine("Visit #" + k + " " + s); } }}
Test by running the client twice, at the sametime and from two different DOS screens.
MSCF/CMU 11
Web Services & Legacy Code
• Many web services will be developed from scratch.
• Many web services will want to make use of existing code.
• Existing code is typically “unmanaged”.
• In this demonstration we will use Visual Studio .NET to create a web service from managed legacy code.
• The example will use the genetic algorithm project from the previous course.
MSCF/CMU 12
C++ As A Web Service
• Run Visual Studio .NET
• Select New Project
• New Project Type = Visual C++
• Template = Managed C++ web service
• Enter a file and directory name
• Look over the Readme.txt file and the directory structure
MSCF/CMU 13
Files Created (From Readme.txt)
ACPlusPlusExample.vcproj
-- main project file for VC++ projects
-- holds information about the platforms,
configurations,
and project features selected with the
Application Wizard.
MSCF/CMU 14
ACPlusPlusExample.cpp
This is the main web source file. The
default is a “hello world” application.
In this demo, we’ll write some C++
code to this file.
MSCF/CMU 15
ACPlusPlusExample.h -- This header file contains the declarations of the Web Service. The default file contains a function prototype for the hello world web service. -- We’ll add new prototypes (method signatures) to this file.
AssemblyInfo.cpp
-- Contains custom attributes for modifying assembly metadata.
MSCF/CMU 16
ACPlusPlusExample.vsdisco -- discovery file for your web service. -- through the discovery process Web Service clients learn that a Web Service exists, what its capabilities are, and how to properly interact with it. -- an XML document that contains links to other resources that describe the Web Service.
MSCF/CMU 17
Web.Config
-- This file allows you to override the default configuration settings for your service.
An .asmx file
-- created as a pointer to this web application.
MSCF/CMU 18
Edit the C++ code
• Select build
• Select Run icon
• View the service in a browser
• On the client side Run wsdl.exe to create a proxy
wsdl -o:Proxy.cs http://localhost/ACPlusPlusExample/ACPlusPlusExample.asmx?
WSDL
• Write a client that uses the proxy
MSCF/CMU 19
A Client of the Genetic Algorithm
using System;public class CallGeneticWebService { public static void Main(string[] args) { double[] values = { 6.5, 1.0, 0.0, 2.0, 7.3, 1.1, 0.0, 2.0, 8.5, 1.15, 1.0, 2.0, 8.7, 1.4, 0.0, 3.0, 9.8, 1.7, 1.0, 3.0, 10.5, 1.8, 1.0, 4.0, 9.5, 1.9, 0.0, 3.0, 12.5, 1.9, 1.0, 4.0, 12.5, 2.1, 2.0, 4.0, 13.7, 2.1, 2.0, 4.0, 15.0, 2.3, 2.0, 4.0 };
MSCF/CMU 20
Class1 p = new Class1();
string result = p.GeneticAlgorithm(11,3,values);
Console.WriteLine(result);
}}
This will not work without a proxy class generated from the webservice WSDL document.
MSCF/CMU 21
MyClientOur data set is
6.5 1 0 27.3 1.1 0 28.5 1.15 1 28.7 1.4 0 39.8 1.7 1 310.5 1.8 1 49.5 1.9 0 312.5 1.9 1 412.5 2.1 2 413.7 2.1 2 415 2.3 2 4
MSCF/CMU 22
Our function is
0.1777 = ((0.907132 + ((0.727165 + x1) + (x2 + ((0.727165 + (((x0 + x2) - (0.172155 * ((0.907132 + (((((x0 + x0) - x1) / x2) + x1) + x2)) + ((((0.727165 + x1) + (x0 + ((0.727165 +0.727165) + x0))) + x0) – (0.172155 * x0))))) / x2)) + x0)))) + x0)
MSCF/CMU 23
Web Service
BrowserBrowserTest and Learn
WSDL = Web Services Description Language
WSDL.EXE Proxy code to handlecommunications and marshalling Of parameters
MSCF/CMU 25
Asynchronous Web Service
• The generated proxy contains code for asynchronous calls.
• We make a call to the service and then continue executing
• We have two ways to get the result:
(1) Provide a callback method
(2) Call a specific method to get the result
MSCF/CMU 26
A Second Client// AsyncGeneticlient/MyClient.cs// Each method in the proxy has a BeginXXX and EndXXX // where XXX is the name of the web service method.
using System;using System.Threading;
public class CallGeneticWebServiceAsync {
class MyStateObject { public AutoResetEvent Event = new AutoResetEvent(false); public Class1 calc = new Class1(); }
MSCF/CMU 27
public static void MyFinishProc(IAsyncResult iar) {
MyStateObject o = (MyStateObject) iar.AsyncState;
string result = o.calc.EndGeneticAlgorithm(iar);
Console.WriteLine(result);
o.Event.Set(); // tell the main thread }
MSCF/CMU 28
public static void Main(string[] args) {
double[] values = { 6.5, 1.0, 0.0, 2.0, 7.3, 1.1, 0.0, 2.0, 8.5, 1.15, 1.0, 2.0, 8.7, 1.4, 0.0, 3.0, 9.8, 1.7, 1.0, 3.0, 10.5, 1.8, 1.0, 4.0, 9.5, 1.9, 0.0, 3.0, 12.5, 1.9, 1.0, 4.0, 12.5, 2.1, 2.0, 4.0, 13.7, 2.1, 2.0, 4.0, 15.0, 2.3, 2.0, 4.0 };
MSCF/CMU 29
MyStateObject stateObject = new MyStateObject();
IAsyncResult iar =
stateObject.calc.BeginGeneticAlgorithm(11, 3, values, new AsyncCallback(MyFinishProc), stateObject);
Console.WriteLine("Waiting for call back to complete");
stateObject.Event.WaitOne(); }}
MSCF/CMU 30
AsyncGeneticClient>MyClientWaiting for call back to completeOur data set is
6.5 1 0 27.3 1.1 0 28.5 1.15 1 28.7 1.4 0 39.8 1.7 1 310.5 1.8 1 49.5 1.9 0 312.5 1.9 1 412.5 2.1 2 413.7 2.1 2 415 2.3 2 4Our function is
0.213383 = ((((x0 + x0) + x0) + (x1 + (0.569536 * (((((((((x0 + 0.303568) + x0)+ x1) / (x0 + x0)) + x0) + 0.303568) + x0) + (x1 + (0.569536 * ((((((x0 + 0.303568) + x2) + (x1 + (0.569536 * (((x0 + 0.64922) + x1) / (x0 + x0))))) + 0.64922)+ ((x0 + 0.303568) + x0)) / (x0 + x0))))) / (x0 + x0))))) + x2)