views:

1043

answers:

1

I have a WCF Callback implemented in an asp.net web application using a wsdualhttpbinding that I would like to use to update the rows in a gridview on my page. I put the gridview in an update panel, and the callback is fireing on the client, but the data in the grid never gets updated. I have tried calling the update panel's Update() method after calling the databind to no avail. Is there something I am missing or something else that I need to do to get this to work?

Here is some of the code I am using:

In the page load, I attach to the WCF Callback, I inherit the interface for the callback, and in the implementation of the interface I bind to the grid with the data that is received from the Callback:

[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
public partial class activeJobs : System.Web.UI.UserControl, IAgentMessagingCallback
{
    AgentMessagingClient _messagingClient;

    protected void Page_Load(object sender, EventArgs e)
    {
        InstanceContext context = new InstanceContext(this);
        _messagingClient = new AgentMessagingClient(context, "AgentMessaging_IAgentMessaging");

        if (_messagingClient.Subscribe())
        {
            Page.Title = string.Format("Timeout will occur at {0}", DateTime.Now.AddMinutes(10));
        }
    }

    #region IAgentMessagingCallback Members

    public void ActiveJobs(SubmittedJob[] activeJobs1)
    {
        activeJobsGrid.DataSource = activeJobs1.ToList();
        //checked in the debugger, the data is actually recieved...
        activeJobsGrid.DataBind();

        //the update method for the updatepanel...tried this both ways, no go
        //activeJobsGridUP.Update(); 
    }

    #endregion
}

The Callback is defined as such:

[ServiceContract(CallbackContract = typeof(IAgentMessagingCallback))]
public interface IAgentMessaging
{
    [OperationContract(IsOneWay = true)]
    void SendActiveJobs(List<SubmittedJob> activeJobs);

    [OperationContract(IsOneWay = false)]
    bool Subscribe();

    [OperationContract(IsOneWay = false)]
    bool Unsubscribe();
}

public interface IAgentMessagingCallback
{
    [OperationContract(IsOneWay = true)]
    void ActiveJobs(List<SubmittedJob> activeJobs);
}

public class AgentMessaging : IAgentMessaging
{
    private static readonly List<IAgentMessagingCallback> _subscribers = new List<IAgentMessagingCallback>();

    #region IAgentMessaging Members

    public void SendActiveJobs(List<SubmittedJob> activeJobs)
    {
        _subscribers.ForEach(delegate(IAgentMessagingCallback callback)
        {
            if (((ICommunicationObject)callback).State == CommunicationState.Opened)
            {
                try
                {
                    callback.ActiveJobs(activeJobs);
                }
                catch (Exception ex)
                {
                    Messaging.ErrorMessage(ex, this.ToString());
                }
            }
            else
            {
                _subscribers.Remove(callback);
            }
        });
    }

    public bool Subscribe()
    {
        try
        {
            IAgentMessagingCallback callback = OperationContext.Current.GetCallbackChannel<IAgentMessagingCallback>();
            if (!_subscribers.Contains(callback))
            {
                _subscribers.Add(callback);
                return true;
            }
            else
            {
                return false;
            }
        }
        catch (Exception ex)
        {
            Messaging.ErrorMessage(ex, this.ToString());
            return false;
        }
    }

    public bool Unsubscribe()
    {
        try
        {
            IAgentMessagingCallback callback = OperationContext.Current.GetCallbackChannel<IAgentMessagingCallback>();
            if (_subscribers.Contains(callback))
            {
                _subscribers.Remove(callback);
                return true;
            }
            else
            {
                return false;
            }
        }
        catch (Exception ex)
        {
            Messaging.ErrorMessage(ex, this.ToString());
            return false;
        }
    }

    #endregion
}
A: 

Does the callback happen before you've returned from the Subscribe operation, or after Page_Load? If it happens after Page_Load, I'm concerned about whether the page will still be around when the callback happens.

You do realize that a new page instance is created on each request? And that the instance is discarded once the HTML has been sent to the client? Once the HTML has been sent to the client, there's nothing the server can do to change it.

John Saunders
The callback happens after the Page_Load. The code is written so that any instances that aren't around when the callback occurs, they will be removed from the subscribers list, and won't be sent to anymore.From what I am reading, is it not possible to do what I am trying to do?
sunmorgus
I can see through using the debugger that the WCF Callback is able to touch the page and attempt a bind on the GridView, but as you write, I assume, even with the UpdatePanel, I won't be able to update the grid with the new data. Is that correct?
sunmorgus
That's correct. Also, when I said instance, I meant the page instance, not the WCF instance. The page is destroyed right after the HTML is sent. You'll have to do the UpdatePanel thing the other way around. I've never done it before, so I can't advise you, but look for examples where a grid in an updatepanel binds to some data returned in a query. You may even be able to find an example of doing the same with an ObjectDataSource and a WCF service.
John Saunders