|
Rank: Advanced Member Groups: Member
Joined: 8/24/2007 Posts: 130
|
Hi, I am attempting to use an asynchronous api to populate a TreeView. Hence, my OnItemPopulate handler has the following signature:
Code: C#
protected async void OnPopulateDirectories(object sender, NavigationItemEventArgs e)
I have applied the Page directive Async="true" However, when attempting to populate my TreeView, I am getting the following error: InvalidOperationException: An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle. If this exception occurred while executing a Page, ensure that the Page is marked <%@ Page Async="true" %>. This exception may also indicate an attempt to call an "async void" method, which is generally unsupported within ASP.NET request processing. Instead, the asynchronous method should return a Task, and the caller should await it. I have attempted to get around the problem using the RegisterAsyncTask method. This prevents the above error, but does not update the TreeView. Is there any way around this problem? I am forced to use the asynchronous API as there is no synchronous alternative. Kind Regards
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,229
|
Hi,
We have posted a new build that should fix this problem. Please see your private message for the download location. As you have already noticed, you must use RegisterAsyncTask. Just marking the event handler as async will not work.
Thanks!
|
|
Rank: Advanced Member Groups: Member
Joined: 8/24/2007 Posts: 130
|
Excellent!
That now works for me. Thanks for the quick turn around on this. Very good customer service.
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,229
|
Thanks for confirming the fix! Please feel free to let us know if there is anything else.
|
|
Rank: Advanced Member Groups: Member
Joined: 8/24/2007 Posts: 130
|
Hi, I have encountered an issue with using the TreeView with asynchronous Web Forms. I am able to populate the treeview on demand correctly using RegisterAsyncTask as follows:
Code: C#
protected void OnPopulateDirectories(object sender, NavigationItemEventArgs e)
{
Page.RegisterAsyncTask(new PageAsyncTask(() => BindDirectories(e.TreeNode)));
}
private async Task BindDirectories(TreeNode parentNode)
{
string boxFolderId;
TreeNodeCollection nodes;
if (parentNode == null)
{
boxFolderId = "0";
nodes = treeViewDirectories.TopGroup.Nodes;
}
else
{
boxFolderId = parentNode.ItemID;
nodes = parentNode.SubGroup.Nodes;
}
var folders = await BoxClientManager.GetFoldersAsync(boxFolderId);
foreach (BoxFolder folder in folders)
{
nodes.Add(new TreeNode(folder.Name)
{
PopulateOnDemand = true,
ItemID = folder.Id
});
}
}
However I am subsequently having a problem with selecting a recently populated node. When a recently populated node is selected, ClientSideOnItemClick fires correctly, and the node is styled as selected. However on a subsequent server side event handler (also asynchronous), the treeview.SelectedNode is set to null. I have tried setting the selected node manually in the client side event, and this has no effect server side. I modified my code, as a test, to populate the tree view via a synchronous call and the issue went away. Please could you look into this for me, as it is currently delaying the project I am trying to deliver. Many Thanks.
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,229
|
Hi,
We have looked into this issue and there is no easy way to make it work without changing programming interface. Particulary, the server side logic (ItemClicik event, SelectedNode, etc) depends on the completion of the ItemPopulate event since the client only sends the "item ID" back to the server. That means a variety of events (such as ItemClick event) will have to be postphoned until after the async task is done. The "proper" way to achieve is to use an async event handler and then await inside the event handler (or use RegisterAsyncTask). However this does not work in this case because the corresponding TreeNode needs to be populated before the event handler is called.
The easiest way for you to workaround this problem is to rely on some ID data instead of the whole TreeNode since that data is available rightway when a node is clicked. For example, you can store an ID value in the TreeNode's Value property, then use a ScriptEvent control to trigger a server event and pass that value as argument. This way you can handle the ScriptEvent's Command event and perform your additional logic solely based on the ID value you passed back through the ScriptEvent instead of relying on the whole TreeNode object, which would not be available at that point. You will need to turn RaisesServerEvent to false and rely on ClientSideOnItemClick if you use this approach.
Thanks!
|
|
Rank: Advanced Member Groups: Member
Joined: 8/24/2007 Posts: 130
|
Thanks for the reply. I managed to resolve the issue by using a hidden field to hold the node id.
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,229
|
Great. That will work too.
|
|