Hello All,
I am using an IHttpAsyncHandl er class to intercept HTTP Requests and forward
them to a system which processes the Request and returns the Result.
I use .NET Remoting to connect the IHttpAsyncHandl er object to the System
and transfer the Request and Result between the two.
This works fine for quite a while, and then I start to get the following
error.
"This remoting proxy has no channel sink which means either the server has
no registered server channels that are listening, or this application has no
suitable client channel to talk to the server"
At this point I can't access the IAsyncHandler objects and the Server has to
be restarted.
As a note, the IHttpAsynHandle r objects are managed in a pool by IIS.
In order to maintain the HTTPContext for the request, the system caches the
IHttpAsyncHandl er Proxy until the request is processed, and then returns the
Result via this proxy instance. It is at this time that I get the
exception.
I am attaching some sample code for the client and server.
Thanks to all in advance
Mike Grishaber
mg********@cp.o rg
The following is code from the Client. Note that this runs under IIS as an
asp.net IHttpAsyncHandl er.
The InitializeChann el method creates the .NET Remoting connection to the
server called m_RequestManage r.
/// <summary>
/// This method will register tcp channel and connect to RequestManager.
/// </summary>
protected override void InitializeChann el()
{
//Register channel if not already registered
//create TcpChannel with port set to 0. Giving it as 0 instead means
//that the framework should look for a free port and use this.
m_Channel = new TcpChannel(0);
//Register Channel
ChannelServices .RegisterChanne l(m_Channel);
//set registered flag to true
m_ChannelIsRegi stered = true;
m_RequestManage r = null;
m_RequestManage r =
(RequestManager )Activator.GetO bject(typeof(Re questManager)," tcp://" + HOST +
":" + PORT + "/" + URI);
}
The next method BeginProcessReq uest() is called by IIS when the HTTPRequest
is received. The IHttpAsyncHandl er object will connect to the
RequestManager server and send the request. An IAsyncResult object is
returned to IIS so that we can retieve the IHttpAsyncHandl er from the pool
when we need it.
/// <summary>
/// This method is called asynchronously by ASP.Net. In this method we
create a
/// Async object which allows us to keep track of state between this method
and
/// EndProcessReque st. After BuildRequest is called the Async object is
returned
/// to IIS. EndProcessReque st will not be invoked intill
m_Async.SetComp leted() is
/// called.
/// </summary>
/// <param name="context"> Http context object.</param>
/// <param name="cb">Call back method</param>
/// <param name="extraData ">asyncStat e</param>
/// <returns>Asyn c object</returns>
public IAsyncResult BeginProcessReq uest(HttpContex t context,
System.AsyncCal lback cb, object extraData)
{
//create Async class to return to IIS
m_Async = new Async(cb,extraD ata);
//get context to use output stream
m_Async.context = context;
//create request object
m_Request = new Cp.Util.Request ();
//set request paramaters
m_Request.Param eters = new
NameValueCollec tion(m_Async.co ntext.Request.P arams);
//set Request ID using IDGenerator class. IDGenerator uses .Net GIUD Class.
IDGenerator RequestGiud = IDGenerator.Get Instance();
//set request id with unique id using .Net GUID class
m_Request.ID = RequestGiud.Get ID("Pre","Suff" );
//pass request object and (this)sink to requestmanager
m_RequestManage r.NewRequest(m_ Request,this);
//return object to IIS
return m_Async;
}
The next method EndProcessReque st() is called when processing is completed
and the Server has sent back the Result. The IAsyncResult object is invoked
and IIS will call EndProcessReque st().
/// <summary>
/// Called by IIS by when request is ready to stream content to client. IIS
passes
/// the Async as parameter. From here we can get the correct http context of
the
/// clients request and send the response stream back.
/// </summary>
/// <param name="result">A sync object</param>
public void EndProcessReque st(IAsyncResult result)
{
//get Async object from IIS
Async async = (Async)result;
//write result to client
async.context.R esponse.StatusC ode = m_StatusCode;
async.context.R esponse.Write(m _ResponseString );
this.Close();
}
The following is the Server side code....
The next method RegisterChannel () sets up the .NETRemoting server.
/// <summary>
/// This method will registar our TCP Server Channel.
/// </summary>
protected virtual void RegisterChannel ()
{
//create binary server formatter
System.Runtime. Remoting.Channe ls.BinaryServer FormatterSinkPr ovider provider
= new System.Runtime. Remoting.Channe ls.BinaryServer FormatterSinkPr ovider();
//set formatter TypeFilterLevel to full to allow passing of delegates and
object references over Remoting boundaries
provider.TypeFi lterLevel =
System.Runtime. Serialization.F ormatters.TypeF ilterLevel.Full ;
//create tcp server channel
m_Channel = new TcpServerChanne l("RequestManag erChannel",m_Po rt,provider);
ChannelServices .RegisterChanne l(m_Channel); //registar channel
}
The next method is the NewRequest() method which is exposed as a remoting
interface for the client to call.
/// <summary>
/// This method will receive new RequestSink from sink classes.
/// Request object and ID will be mapped by MapRequest method. Request
object will
/// be sent to transaction sub-system.
/// </summary>
/// <param name="Sink">Req uestSink</param>
public void NewRequest(Cp.U til.Request InRequest,Reque stSink Sink)
{
//map Request
m_ResultRouter. MapRequest(InRe quest.ID, Sink);
//send request to outbox
m_TransactionOu tBox.SendObject (InRequest);
}
The next method is the Run() method which receives the Result back for the
request, retrieves the IHttpAsyncHandl er proxy instance and sends the Result
to it. It is at this point that the exception occurs.
public void Run()
{
//begin send stream process on sink
try
{
if(Sink != null)
{
Sink.SendStream (NewResult.Retu rnObject.ToStri ng(),
NewResult.Profi leID.ToString() , NewResult.Langu ageID.ToString( ),
NewResult.IsSuc cess);
Sink = null;
}
}
catch(Exception e)
{
LogEntry entry = new LogEntry(LogEnt ry.WARNING,
"Exception Closing HTTPSink.\r\n" + e.Message,
"Cp.Request","R equestManager.R un");
if(m_Logger!= null)
{
m_Logger.LogMes sage(entry, true);
}
}
//unmap sink in ResultRouter
m_ResultRouter. UnmapRequest(Ne wResult.ID);
}