3

I want to implement a webchat.

The backend is a dual WCF channel. Dual channel works in the console or winforms, and it actually works on the web. I can at least send and receive messages.

As a base I used this blog post so, the async operation completes.

When i debug the result, I see that the messages are all ready to send to the browser.

[AsyncTimeout(ChatServer.MaxWaitSeconds * 1020)] // timeout is a bit longer than the internal wait
public void IndexAsync()
{
  ChatSession chatSession = this.GetChatSession();
  if (chatSession != null)
  {
    this.AsyncManager.OutstandingOperations.Increment();
    try
    {
      chatSession.CheckForMessagesAsync(msgs =>
      {
        this.AsyncManager.Parameters["response"] = new ChatResponse { Messages = msgs };
        this.AsyncManager.OutstandingOperations.Decrement();
      });
    }
    catch (Exception ex)
    {
      Logger.ErrorException("Failed to check for messages.", ex);
    }
  }
}

public ActionResult IndexCompleted(ChatResponse response)
{
  try
  {
    if (response != null)
    {
      Logger.Debug("Async request completed. Number of messages: {0}", response.Messages.Count);
    }
    JsonResult retval = this.Json(response);
    Logger.Debug("Rendered response: {0}", retval.);
    return retval;
  }
  catch (Exception ex)
  {
    Logger.ErrorException("Failed rendering the response.", ex);
    return this.Json(null);
  }
}

But nothing is actually sent.

Checking Fiddler, I see the request but I never get a response.

[SessionState(SessionStateBehavior.ReadOnly)]  
public class ChatController : AsyncController

I also had to set the SessionStateBehaviour to Readonly, otherwise the async operation would block the whole page.

EDIT: Here is the CheckForMessagesAsync:

public void CheckForMessagesAsync(Action<List<ChatMessage>> onMessages)
{
  if (onMessages == null)
    throw new ArgumentNullException("onMessages");

  Task task = Task.Factory.StartNew(state =>       
  {
    List<ChatMessage> msgs = new List<ChatMessage>();
    ManualResetEventSlim wait = new ManualResetEventSlim(false);
    Action<List<ChatMessage>> callback = state as Action<List<ChatMessage>>;
    if (callback != null)
    {
      IDisposable subscriber = m_messages.Subscribe(chatMessage =>
      {
        msgs.Add(chatMessage);
        wait.Set();
      });
      bool success;
      using (subscriber)
      {
        // Wait for the max seconds for a new msg
        success = wait.Wait(TimeSpan.FromSeconds(ChatServer.MaxWaitSeconds));              
      }
      if (success) this.SafeCallOnMessages(callback, msgs);
      else this.SafeCallOnMessages(callback, null);
    }        
  }, onMessages);
}
private void SafeCallOnMessages(Action<List<ChatMessage>> onMessages, List<ChatMessage> messages)
{
  if (onMessages != null)
  {
    if (messages == null)
      messages = new List<ChatMessage>();
    try
    {
      onMessages(messages);
    }
    catch (Exception ex)
    {
      this.Logger.ErrorException("Failed to call OnMessages callback.", ex);
    }
  }
}

it`s the same idea as the in the refered blog post

EDIT2: Btw, when nothing is received, so the wait timeout comes into play, the reponse returns. so it seems to crash somewhere. any idea how to log this?

esskar
  • 10,638
  • 3
  • 36
  • 57
  • You set a breakpoint and verified that it is getting to the code where you call `this.AsyncManager.OutstandingOperations.Decrement();`? – Kirk Woll Jun 30 '11 at 21:14
  • Post relevant code in `CheckForMessagesAsync`, and add logging in the callback. – Samuel Neff Jul 01 '11 at 03:56
  • Not really related to your problem, but in `IndexAsync`'s catch clause, you should decrement the async operation counter. If you don't actually queue up the callback, then it will never get called. Alternatively, you can choose to only increment it after successfully returning from `CheckForMessagesAsync`. – Samuel Neff Jul 01 '11 at 03:57
  • thanks for that. i added log messages before and after the Increment/Decrement calls. This is what i get. – esskar Jul 01 '11 at 04:12
  • WebProject.Controllers.ChatController|Increment OutstandingOperations WebProject.Controllers.ChatController|Sending message to sip:xxx@xxxx.ext ChatDAL|Notify response: WebProject.DataAccessLayer.UnifiedMessagingGatewayService.ChatResponse ChatSession|Message received. WebProject.Controllers.ChatController|Decrement OutstandingOperations WebProject.Controllers.ChatController|Async callback finished. WebProject.Controllers.ChatController|Async request completed. Number of messages: 1 – esskar Jul 01 '11 at 04:14
  • so, it gets their. everything is fine, but nothing gets to the browser. – esskar Jul 01 '11 at 04:15

1 Answers1

1

I changed the jQUERY request (see original blog post) from POST to GET. That fixes it.

esskar
  • 10,638
  • 3
  • 36
  • 57