This is a migrated thread and some comments may be shown as answers.

RadAjaxManagerProxy needs it's own client side and server side functions

5 Answers 350 Views
Ajax
This is a migrated thread and some comments may be shown as answers.
Dimitri Stoikof
Top achievements
Rank 1
Dimitri Stoikof asked on 01 Aug 2010, 08:47 PM
Hi Telerik,

After a week of researching this topic it seems that most people are confused about how to use RadAjaxManagerProxy when creating MasterPage/ContentPage sites and WebUserControls.

The problem with not being able to insert a RadAjaxManager in a ContentPage/UserControl is that if you call the clientside function ajaxRequest your call is made to the RadAjaxManager server side function, which you have no control over when you're developing the contentpage or usercontrol. We need to be able to fire callbacks and catch them in the contentpage or webusercontrol.

I know you can use ajaxRequestWithTarget but this has two problems - it requires you to register the expected postback variables in the Page or UserControl Render function as follows:

Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
     Page.ClientScript.RegisterForEventValidation(cmdProjectSelected.UniqueID, "2")
    Page.ClientScript.RegisterForEventValidation(cmdProjectSelected.UniqueID, "3")
    Page.ClientScript.RegisterForEventValidation(cmdProjectSelected.UniqueID, "4")
    Page.ClientScript.RegisterForEventValidation(cmdProjectSelected.UniqueID, "5")
    MyBase.Render(writer)
End Sub

And then you have to catch the event on the server side in RaisePostBackEvent - which implies that ajaxRequestWithTarget does a postback, not a callback like ajaxRequest, which is less efficient. The reason you need to register the expected postback variables is because if you don't, you'll get a security error from Asp.Net: "Sys.WebForms.PageRequestManagerServerErrorException: Invalid postback or callback argument" - meaning that ASP is preventing this postback because it doesn't know the data being posted since it wasn't in the ViewState for the target specified in ajaxRequestWithTarget. Also, it's not an elegant solution when you have to add a hidden button to your page which does the postback for you.

Most developers are now moving to nice elegant jQuery solutions that make callbacks everywhere, and if RadAjax does not have an elegant way to make callbacks simple then it's not a workable solution. 

I really like the simple way you can make a callback via the RadAjaxManager, but we really need this functionality in the RadAjaxManagerProxy as well!

Dimitri 

5 Answers, 1 is accepted

Sort by
0
Tsvetina
Telerik team
answered on 05 Aug 2010, 08:49 AM
Hello Dimitri,

RadAjaxManagerProxy may look like a separate AJAX control, but it is not. It just passes some AjaxSettings to the main RadAjaxManager control. So there cannot be separate event handlers for the proxy. When you need to work directly with RadAjaxManager in a content page/user control, you can access it via GetCurrent(Page) static method. 

Additionally, good overview of the idea and functionality of RadAjaxManagerProxy and explanations on how to properly use it can be found at this address.

Kind regards,
Tsvetina
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Daniel Gioulakis
Top achievements
Rank 1
answered on 16 Sep 2010, 05:59 PM

Dimitri I can't thank you enough for your post.  Has helped solve some major headaches around work this past week.

Telerik,

I could not find one reference to "RegisterForEventValidation" in your documentation for client-side API.  http://www.telerik.com/help/aspnet-ajax/ajxclientsideapi.html

If "ajaxRequestWithTarget" requires "RegisterForEventValidation" to be set and the Render method overridden on the page, I think you should definitely make note of it.  Had been receiving "Invalid postback or callback argument" for days and with no solid examples in your demos or documentation, we have had to come up with work-arounds just to make things work.

Much thanks again. :)

0
Tsvetina
Telerik team
answered on 17 Sep 2010, 08:01 AM
Hi Daniel,

By default registering the postback variables is not required when using ajaxRequestWithTarget. There must be something else causing the error on your page - it might be, for example, custom scripts that you are using or other controls apart from native ASP controls and RadControls.

If you would like us to investigate the issue further, you could open a formal support ticket and send us a sample project isolating the described problem, so we can take a closer look at it and let you know what are our findings.

Sincerely yours,
Tsvetina
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Dimitri Stoikof
Top achievements
Rank 1
answered on 26 Sep 2010, 11:50 PM
Hi Tsvetina,

I've come back to this issue several times now only to drop it again in frustration, but I do believe this is important, and that other developers will benefit from a solution as well.

I understand that RadAjaxManagerProxy is not a seperate control and that it only acts as, well, a proxy to the RadAjaxManager on the main page. This means that if you call ajaxManager.ajaxRequest(...) in javascript you are calling the server-side function of the RadAjaxManager on the main page/Masterpage. You can subscribe to this event in your usercontrol, but if you have multiple user controls subscribing to this event then they will ALL get all events, no matter which user control fired the event.

I've made a sample project which has a main page with a RadAjaxManager on it, and two simple user controls MyControlA and MyControlB. The two usercontrols are exactly alike to demonstrate the problem. They each have a label and a hyperlink which triggers the javascript call to ajaxManager.ajaxRequest(...). On the server-side of the usercontrol I set it's label with the text "MyControlX was clicked". What I would like to see happening is that if you click the link on MyControlA, it's own label is set to "MyControlA was clicked", and similar, if you click the link in MyControlB, it's label is set to "MyControlB was clicked".

Here is the code for default.aspx, the main page:

<%@ Page Language="VB" AutoEventWireup="false" CodeBehind="Default.aspx.vb" Inherits="RadAjaxManagerProxyIssue._Default" %>
  
<%@ Register src="MyControlA.ascx" tagname="MyControlA" tagprefix="uc1" %>
<%@ Register src="MyControlB.ascx" tagname="MyControlB" tagprefix="uc2" %>
  
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <telerik:RadScriptManager ID="RadScriptManager1" runat="server"/>
    <telerik:RadAjaxManager ID="RadAjaxManager1" runat="server"/>
    <table width="300">
        <tr>
            <td>
                <uc1:MyControlA ID="MyControlA1" runat="server" />
            </td>
            <td>
                <uc2:MyControlB ID="MyControlB1" runat="server" />
            </td>
        </tr>
    </table>
    </form>
</body>
</html>


Here is usercontrol A:

<%@ Control Language="vb" AutoEventWireup="false" CodeBehind="MyControlA.ascx.vb" Inherits="RadAjaxManagerProxyIssue.MyControlA" %>
  
<telerik:RadAjaxManagerProxy ID="RadAjaxManagerProxy1" runat="server">
    <AjaxSettings>
        <telerik:AjaxSetting AjaxControlID="RadScriptBlock1">
            <UpdatedControls>
                <telerik:AjaxUpdatedControl ControlID="lblMessage" />
            </UpdatedControls>
        </telerik:AjaxSetting>
    </AjaxSettings>
</telerik:RadAjaxManagerProxy>
 
<a href="javascript: ClickHandlerA()">Click MyControlA</a>
<br /><br />
<asp:Label ID="lblMessage" runat="server" Text=""></asp:Label>
 
<telerik:RadScriptBlock ID="RadScriptBlock1" runat="server">
        <script>
            function ClickHandlerA() {
                var ajaxManager = $find("<%= RadAjaxManager.GetCurrent(Page).ClientID %>");
                ajaxManager.ajaxRequest("MyControlA was clicked");
                return false;
            }
        </script>
</telerik:RadScriptBlock>

And the codebehind for MyControlA:

Imports Telerik.Web.UI
 
Public Class MyControlA
    Inherits System.Web.UI.UserControl
 
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        'Define AjaxRequest Server Handler
        Dim manager As RadAjaxManager = RadAjaxManager.GetCurrent(Page)
        AddHandler manager.AjaxRequest, New RadAjaxControl.AjaxRequestDelegate(AddressOf Ajax_Request)
    End Sub
 
    Protected Sub Ajax_Request(ByVal sender As Object, ByVal e As Telerik.Web.UI.AjaxRequestEventArgs)
        lblMessage.Text = e.Argument
    End Sub
 
End Class

MyControlB is exactly the same as A, except that all A's are replaced by B's. In a real scenario each control would do something completely different.

You'll see that if you click the link on MyControlA, both labels are set to "MyControlA was clicked", and if you click the link on MyControlB, both labels are set to "MyControlB was clicked".

Now I know this sample can easily be changed to just use an UpdatePanel, but I'm trying to demonstrate the problem you'll have if you try and do this in more complex scenarios where the usercontrols may be larger or that events are triggered via javascript actions that don't rely on controls like asp buttons or dropdown selection changes to make callbacks. (i.e. you can't use RadAjaxManagerProxy to ajaxify the callbacks)

In the link you mentioned the discussion only concerns the client side of such ajax calls for validation purposes, and here too the solution proposed is complex, and in the author's own words: "...it does require a couple of assumptions that make our code a little brittle".

I believe both client and server side problems could be solved by extending the RadAjaxManagerProxy control to have similar client-side and server-side events as the RadAjaxManager control. 

Do you have an alternative solution to such a scenario?

Thanks,
Dimitri Stoikof





0
Tsvetina
Telerik team
answered on 30 Sep 2010, 09:23 AM
Hello Dimitri,

First thing I need to note in your example is that it is not recommended to use the RadScriptBlock as an AJAX initiator, it would be more appropriate to set the RadAjaxManagerProxy to fire the AJAX request instead.

In this certain sample and in the general case as well, what you can do in order to differentiate between the user controls when you fire the request through javascript, is to pass a second argument which would be different for each user control and then, in the AjaxRequest server-side event handler, check which UserControl sent the argument:
function ClickHandlerA() {
            var ajaxManager = $find("<%= RadAjaxManager.GetCurrent(Page).ClientID %>");
            ajaxManager.ajaxRequest("MyControlA was clicked,A");
        }

Protected Sub Ajax_Request(ByVal sender As Object, ByVal e As Telerik.Web.UI.AjaxRequestEventArgs)
    If Split(e.Argument, ",")(1) = "A" Then
        lblMessage.Text = Split(e.Argument, ",")(0)
    End If
End Sub

I am attaching the modified sample to this post for you to look through.

All the best,
Tsvetina
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
Tags
Ajax
Asked by
Dimitri Stoikof
Top achievements
Rank 1
Answers by
Tsvetina
Telerik team
Daniel Gioulakis
Top achievements
Rank 1
Dimitri Stoikof
Top achievements
Rank 1
Share this question
or