繁体中文
设为首页
加入收藏
当前位置:.Net技术首页 >> Web Service开发 >> Using Web Services for Remoting over the Internet. (下)

Using Web Services for Remoting over the Internet. (下)

2004-10-01 08:26:10  作者:  来源:互联网  浏览次数:19  文字大小:【】【】【
简介:Decoding and de-serializing of the request message Invoking the Remote Method Encoding and serialization of the response message [WebMethod] public string SyncProcessMessage(string request) { &nb...

Decoding and de-serializing of the request message Invoking the Remote Method Encoding and serialization of the response message

[WebMethod]

public string SyncProcessMessage(string request)

{

// Request: decoding and deserializing

byte[] reqbyteArray = Convert.FromBase64String(request);

MemoryStream reqstream = new MemoryStream();

reqstream.Write(reqbyteArray, 0, reqbyteArray.Length);

reqstream.Position = 0;

BinaryFormatter bf = new BinaryFormatter();

IMessage reqmsg = (IMessage)bf.Deserialize(reqstream);

reqmsg.Properties["__Uri"] = reqmsg.Properties["__Uri2"]; // work around!!

reqstream.Close();

// Action: invoke the Remote Method

string[] stype = reqmsg.Properties["__TypeName"].ToString().Split(new Char[]{','}); // split typename

Assembly asm = Assembly.Load(stype[1].TrimStart(new char[]{' '})); // load type of the remote object

Type objectType = asm.GetType(stype[0]); // type

string objectUrl = reqmsg.Properties["__Uri"].ToString(); // endpoint

object ro = RemotingServices.Connect(objectType, objectUrl); // create proxy

TraceIMessage(reqmsg);

IMessage rspmsg = RemotingServices.ExecuteMessage((MarshalByRefObject)ro,

(IMethodCallMessage)reqmsg);

TraceIMessage(rspmsg);

// Response: encoding and serializing

MemoryStream rspstream = new MemoryStream();

bf.Serialize(rspstream, rspmsg);

rspstream.Position = 0;

string response = Convert.ToBase64String(rspstream.ToArray());

rspstream.Close();

return response;

}

[WebMethod]

public string SyncProcessSoapMessage(string request)

{

IMessage retMsg = null;

string response;

try

{

Trace.WriteLine(request);

// Request: deserialize string into the SoapMessage

SoapFormatter sf = new SoapFormatter();

sf.TopObject = new SoapMessage();

StreamWriter rspsw = new StreamWriter(new MemoryStream());

rspsw.Write(request);

rspsw.Flush();

rspsw.BaseStream.Position = 0;

ISoapMessage soapmsg = (ISoapMessage)sf.Deserialize(rspsw.BaseStream);

rspsw.Close();

// Action: invoke the Remote Method

object[] values = soapmsg.ParamValues;

string[] stype = values[2].ToString().Split(new Char[]{','});

Assembly asm = Assembly.Load(stype[1].TrimStart(new char[]{' '}));

Type objectType = asm.GetType(stype[0]);

string objectUrl = values[0].ToString();

RealProxyWrapper rpw = new RealProxyWrapper(objectType, objectUrl,

soapmsg.ParamValues[4]);

object ro = rpw.GetTransparentProxy();

MethodInfo mi = objectType.GetMethod(values[1].ToString());

object retval = mi.Invoke(ro, values[3] as object[]);

retMsg = rpw.ReturnMessage;

}

catch(Exception ex)

{

retMsg = new ReturnMessage((ex.InnerException == null) ?

ex : ex.InnerException, null);

}

finally

{

// Response: serialize IMessage into string

Stream rspstream = new MemoryStream();

SoapFormatter sf = new SoapFormatter();

RemotingSurrogateSelector rss = new RemotingSurrogateSelector();

rss.SetRootObject(retMsg);

sf.SurrogateSelector = rss;

sf.AssemblyFormat = FormatterAssemblyStyle.Full;

sf.TypeFormat = FormatterTypeStyle.TypesAlways;

sf.TopObject = new SoapMessage();

sf.Serialize(rspstream, retMsg);

rspstream.Position = 0;

StreamReader sr = new StreamReader(rspstream);

response = sr.ReadToEnd();

rspstream.Close();

sr.Close();

}

Trace.WriteLine(response);

return response;

}

The implementation of the steps are depended from the type of formatter such as SoapFormatter or BinaryFormatter. The first and last steps are straightforward using the Remoting namespace classes. The second one (action) for the SoapFormatter message needed to create the following class to obtain IMessage of the MethodCall:

public class RealProxyWrapper : RealProxy

{

string _url;

string _objectURI;

IMessageSink _messageSink;

IMessage _msgRsp;

LogicalCallContext _lcc;

public IMessage ReturnMessage { get { return _msgRsp; }}

public RealProxyWrapper(Type type, string url, object lcc) : base(type)

{

_url = url;

_lcc = lcc as LogicalCallContext;

foreach(IChannel channel in ChannelServices.RegisteredChannels)

{

if(channel is IChannelSender)

{

IChannelSender channelSender = (IChannelSender)channel;

_messageSink = channelSender.CreateMessageSink(_url, null, out _objectURI);

if(_messageSink != null)

break;

}

}

if(_messageSink == null)

{

throw new Exception("A supported channel could not be found for url:"+ _url);

}

}

public override IMessage Invoke(IMessage msg)

{

msg.Properties["__Uri"] = _url; // endpoint

msg.Properties["__CallContext"] = _lcc; // caller's callcontext

_msgRsp = _messageSink.SyncProcessMessage(msg);

return _msgRsp;

}

}// RealProxyWrapper

Test

I built the following package to test functionality of the WebServiceListener and WebServiceChannelLib assemblies. Note that this package has only test purpose. Here is what you downloaded it:ConsoleClient, the test console program to invoke the call over Internet - client machine ConsoleServer, the host process of the MyRemoteObject - server machine MyRemoteObject, the remote object - server machine WebServiceChannelLib, the custom client channel WebServiceListener, the Web Service listener - server machine

To recompile a package and its deploying in your environment follow these notes:The folder WebServiceListener has to be moved to the virtual directory (inetpub\wwwroot). The MyRemoteObject assembly has to be install into the GAC on the server machine The WebServiceChannelLib assembly has to be install into the GAC on the client machine (option) The MSMQChannelLib assembly [1] has to be install into the GAC on the server machine The solution can be tested also using the same machine (Win2k/Adv Server) Use the Echo WebMethod on the test page of the WebServiceListener to be sure that this service will be work

The test case is very simple. First step is to launch the ConsoleServer program. Secondly open the ConsoleClient program and follow its prompt text. If everything is going right you will see a response from the remote object over Internet. I am recommending to make a first test on the same machine and then deploying over Internet.

Conclusion

In this article has been shown one simple way how to implement a solution for remoting over Internet. I used the power of .Net Technologies such as SOAP, Remoting, Reflection and Web Service. The advantage of this solution is a full transparency between the consumer and remote object. This logical connectivity can be mapped into the physical path using the config files, which they can be administratively changed.

责任编辑:admin
相关文章