ASPX templates
Version 4.x > ASPX templates > Inline control and ajax... View modes: 
User avatar
Member
Member
rookie07 - 6/4/2009 3:58:02 AM
   
Inline control and ajax...
hello,

i've tried to create an inlinecontrol that is sending newsletter with an ajax functionality to cancel the sending-process.

unfortunately i think there is a problem with the ScriptManager because i can't see the javascript code that should be importet into the sourcecode.

i tried to include the ScriptManager after the CMSPageManager (as written in the docu) in my masterpage - but this doesn't work either.

of course i've also tried to include the ScriptManager into the inlinecontrol first - but the code doesn't show up in the sourcecode of the site either.

so how am i supposed to get ajax running in an inlinecontrol?

here's my code of the ascx-file:


<asp:ScriptManager ID="sm1" runat="server" EnablePageMethods="true">
<Scripts>
<asp:ScriptReference Path="~/CMSInlineControls/js/spy.js" />
</Scripts>
</asp:ScriptManager>
.
.
.
<asp:UpdatePanel runat="server" ID="up1" OnLoad="up1_Load">
<ContentTemplate>
<asp:GridView runat="server" ID="Headlines" EnableViewState="false" />
<asp:HiddenField runat="server" ID="LatestDisplayTick" />
</ContentTemplate>
</asp:UpdatePanel>

here's my code of the spy.js:

function Check(){
// Call the static page method.
PageMethods.GetLatestLogTick(OnSucceeded, OnFailed);
}
function OnSucceeded(result, userContext, methodName){
// Parse the web method's result and the embedded
// hidden value to integers for comparison.
var LatestTick = parseInt(result);
var LatestDisplayTick = parseInt($get('ctl00_ContentPlaceHolder1_txtLeft_PromontAM_sendNL1_Wizard1_LatestDisplayTick').value);

// If the web method's return value is larger than
// the embedded latest display tick, refresh the panel.
if (LatestTick > LatestDisplayTick)
__doPostBack('ctl00_ContentPlaceHolder1_txtLeft_PromontAM_sendNL1_Wizard1_up1', '');
// Else, check again in 1 second.
else
setTimeout("Check()", 1000);
}
// Stub to make the page method call happy.
function OnFailed(error, userContext, methodName) {}
function pageLoad(){
// On initial load and partial postbacks,
// check for newer articles in five seconds.
setTimeout("Check()", 1000);
}

User avatar
Member
Member
rookie07 - 6/4/2009 5:45:33 AM
   
RE:Inline control and ajax...
is it possible that it has something todo woth the web.config configuration of the system.webServer-section?

somehow ajax allready must be enabled in the web.config file isn't it?
perhaps i do have to use an other scriptmanager of the kentico-framework?

User avatar
Kentico Developer
Kentico Developer
kentico_helenag - 6/11/2009 7:19:53 AM
   
RE:Inline control and ajax...
Hello,

could you please the source code of page with inline contol if you add the Sciptmanager to master page?

<asp:ScriptManager ID="manScript" runat="server">
<Scripts>
<asp:ScriptReference Path="~/CMSInlineControls/js/spy.js" />
</Scripts>
</asp:ScriptManager>


The rendered HTML code should contain this line:
<script src="CMSInlineControls/js/spy.js" type="text/javascript"></script>

It is included?

Best regards,
Helena Grulichova

User avatar
Member
Member
rookie07 - 6/15/2009 3:40:36 AM
   
RE:Inline control and ajax...
hello & thanx for the hint!
anyway i think we have to search in an other direction: http://daptivate.com/archive/2007/03/19/pagemethods-not-found.aspx (see point 4).

i defined the scriptmanager once more in the kentico-inlinecontrol:

<asp:WizardStep ID="WizardStep3" runat="server" Title="Newsletter an Verteiler senden">
<asp:ScriptManager ID="manScript" runat="server" EnablePageMethods="true">
<Scripts>
<asp:ScriptReference Path="~/CMSInlineControls/js/spy.js" />
</Scripts>
</asp:ScriptManager>

i'm also able to see the js-file reference in the source-code of the page:

<script src="../../CMSInlineControls/js/spy.js" type="text/javascript"></script>

in firefox i get the hint: PageMethods is not defined

ff is claiming that the function GetLatestLogTick doesn't exist:

function Check(){
// Call the static page method.
PageMethods.GetLatestLogTick(OnSucceeded, OnFailed);
}

this function was defined and implemented in the cs-file of the inline-control

[WebMethod]
public static long GetLatestLogTick()
{
long ret = 0L;
DataTable dt = (DataTable)HttpContext.Current.Cache["Log"];
if (dt != null)
{
DataRow row = dt.Select("", "Datum DESC")[0];
ret = ((DateTime)row["Datum"]).Ticks;
}
return ret;
}

so everything is wright as far as i know. if i compare it with the sourcecode of the original script (there was no masterpage and no 'inline'-control), i can see the automatic generated code for the PageMethod like this:

<script src="../js/spy.js" type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
var PageMethods = function() {
PageMethods.initializeBase(this);
this._timeout = 0;
this._userContext = null;
this._succeeded = null;
this._failed = null;
}
PageMethods.prototype = {
_get_path:function() {
var p = this.get_path();
if (p) return p;
else return PageMethods._staticInstance.get_path();},
GetLatestLogTick:function(succeededCallback, failedCallback, userContext) {
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param>
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param>
/// <param name="userContext" optional="true" mayBeNull="true"></param>
return this._invoke(this._get_path(), 'GetLatestLogTick',false,{},succeededCallback,failedCallback,userContext); }}
PageMethods.registerClass('PageMethods',Sys.Net.WebServiceProxy);
PageMethods._staticInstance = new PageMethods();
PageMethods.set_path = function(value) {
PageMethods._staticInstance.set_path(value); }
PageMethods.get_path = function() {
/// <value type="String" mayBeNull="true">The service url.</value>
return PageMethods._staticInstance.get_path();}
PageMethods.set_timeout = function(value) {
PageMethods._staticInstance.set_timeout(value); }
PageMethods.get_timeout = function() {
/// <value type="Number">The service timeout.</value>
return PageMethods._staticInstance.get_timeout(); }
PageMethods.set_defaultUserContext = function(value) {
PageMethods._staticInstance.set_defaultUserContext(value); }
PageMethods.get_defaultUserContext = function() {
/// <value mayBeNull="true">The service default user context.</value>
return PageMethods._staticInstance.get_defaultUserContext(); }
PageMethods.set_defaultSucceededCallback = function(value) {
PageMethods._staticInstance.set_defaultSucceededCallback(value); }
PageMethods.get_defaultSucceededCallback = function() {
/// <value type="Function" mayBeNull="true">The service default succeeded callback.</value>
return PageMethods._staticInstance.get_defaultSucceededCallback(); }
PageMethods.set_defaultFailedCallback = function(value) {
PageMethods._staticInstance.set_defaultFailedCallback(value); }
PageMethods.get_defaultFailedCallback = function() {
/// <value type="Function" mayBeNull="true">The service default failed callback.</value>
return PageMethods._staticInstance.get_defaultFailedCallback(); }
PageMethods.set_path("/PromontAM_Services/newsletter/newsletter_send.aspx");
PageMethods.GetLatestLogTick= function(onSuccess,onFailed,userContext) {
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param>
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param>
/// <param name="userContext" optional="true" mayBeNull="true"></param>
PageMethods._staticInstance.GetLatestLogTick(onSuccess,onFailed,userContext); }
//]]>

</script>


also there are more automatic generated javascript functions like this:

<script type="text/javascript">
//<![CDATA[
Sys.WebForms.PageRequestManager._initialize('sm1', document.getElementById('form1'));
Sys.WebForms.PageRequestManager.getInstance()._updateControls(['tWizard1$up1'], [], [], 90);
//]]>
</script>


so i think it is a problem like mentioned in point 4 (http://daptivate.com/archive/2007/03/19/pagemethods-not-found.aspx).

is there a way to define the webmethod directly in the page?

best regards,
stefan!

User avatar
Kentico Developer
Kentico Developer
kentico_helenag - 6/16/2009 7:39:29 AM
   
RE:Inline control and ajax...
Hi Stefan,

yes, it seems the point 4 could be the problem - you are right.

Did you try to add your webmethod on ASPX template where you use the WYSIWYG editor (with possibility of inline controls)? I assume you use ASPX templates according placing of this forum thread.

Best regards,
Helena Grulichova

User avatar
Member
Member
rookie07 - 6/16/2009 7:47:55 AM
   
RE:Inline control and ajax...
yes it is like that.

i created an inline control and in that codebehind-file i included the webmethod. as far as this didn't work i tried to do the same stuff by putting the code into the masterpage (just der scriptmanager an js calls)...

but now it seems that i have to try to find a way to put the 'ajax-code' directly into the page...

or perhaps you know a better way?

thank you!

User avatar
Kentico Support
Kentico Support
kentico_jurajo - 6/24/2009 8:00:29 AM
   
RE:Inline control and ajax...
Hi,

I am sorry but I am not getting the meaning of " i have to try to find a way to put the 'ajax-code' directly into the page..."

Could you please explain it with more details what are you trying to achieve? Thank you.

Best Regards,
Juraj Ondrus

User avatar
Member
Member
rookie07 - 6/25/2009 4:21:26 AM
   
RE:Inline control and ajax...
ok, it's that simple: i want to use ajax in an inlinecontrol.

but it seems that it doesn't work. then i found this article: http://daptivate.com/archive/2007/03/19/pagemethods-not-found.aspx

the 4th paragraph mentions:

The page method must be defined on the page (either inline or in the code-behind). It cannot be defined in a control, master page, or base page.


so now i'm confused where to put the ajaxcode (scriptmaster aso...). i would have done it completely in the inline control, but this doesn't seem to work. i also read the kentico faq how to get ajax running wihtin kentico, that doesn't work either.

so perhaps yu know a way to get my ajax-tool running?

the functionality should be as follows: a userinterface (more or less a cancel-button) which shows a list of all the sent newsletter. the cancel-button should stop the working-thread of sending newsletter.

regards,
stefan.

User avatar
Kentico Support
Kentico Support
kentico_jurajo - 6/30/2009 2:35:49 AM
   
RE:Inline control and ajax...
Hi,

I am sorry but using the PageMethods is not possible in this way. Could you please try to use Callbacks to achieve this need?

Best Regards,
Juraj Ondrus

User avatar
Member
Member
rookie07 - 6/30/2009 3:29:45 AM
   
RE:Inline control and ajax...
so it is not possible to use ajax functionallity?

what do you mean by
...use Callbacks...
, server-side callbacks?

i'm a little confused perhaps could you give me some more information what you mean,
thank you!

greetings,
s.


User avatar
Kentico Developer
Kentico Developer
kentico_ondrejv - 7/2/2009 7:24:12 AM
   
RE:Inline control and ajax...
Hello,

you can see more info on msdn site. Please see it here: http://msdn.microsoft.com/en-us/library/system.web.ui.icallbackeventhandler.aspx

Best regards
Ondrej Vasil

User avatar
Member
Member
rookie07 - 7/6/2009 9:55:38 AM
   
RE:Inline control and ajax...
ok, this seems to be an endless story...i found time and tried some icallbackeventhandler-stuff - as far as i know the base is the same as ajax is, and so unfortunately it doesn't work either. moreover i think it's a question of putting the thread and web-gui (ajax or what ever) together...

into the masterpage i added the client-server communication (somewhere in the header-section):
this already shines up in the html source code if i execute the page in the browser


<script type="text/ecmascript">
var bIsRunning = false;
var hTimer = null;
function StartLoop() {
hTimer = setTimeout("ServerTasks()", 500);
bIsRunning = true;
document.getElementById("btnStart").disabled = true;
document.getElementById("btnStop").disabled = false;
}

function EndLoop() {
if (hTimer != null) {
clearInterval(hTimer);
bIsRunning = false;
CallServer("cancel", "");
document.getElementById("btnStart").disabled = false;
document.getElementById("btnStop").disabled = true;
}
}

function ServerTasks() {
CallServer("", "");

if (bIsRunning == true)
StartLoop();
}

function ReceiveServerData(rValue) {
if (rValue == "cancel")
EndLoop();
document.getElementById("ctl00_ContentPlaceHolder1_txtLeft_PromontAM_sendNL1_Wizard1_ResultsSpan").innerHTML = rValue;
}
</script>


in the inlinecontrol i putet the code like in my test-scenario into the last wizard-step. it consist of 2 buttons which should invoke the endless-loop clientside javascript polling to show whats going on, a start and a stop-button and a span in which i write the text from serverside...see the code above:

<asp:WizardStep ID="WizardStep3" runat="server" Title="Newsletter an Verteiler senden">
<div class="cmxform">
<fieldset>
<legend>Newsletter an Verteiler senden</legend>
<asp:Literal ID="litErr3" runat="server">
<div class='fehler'>
<noscript>Bitte aktivieren Sie in Ihrem Browser JavaScript damit die Seite vollständig angezeigt werden kann.</noscript>
</div>
</asp:Literal>
<ol>
<li>ACHTUNG!!! Der Sendevorgang kann nur durch die 'abbrechen'-Schaltfläche gestoppt werden.</li>
<li>
<button type="button" id="btnStart" onclick="StartLoop();">an Verteiler senden</button>
<button type="button" id="btnStop" onclick="EndLoop();" disabled="disabled">abbrechen</button>
</li>
<li>
<label>Sende-Protokoll</label><br />
<span id="ResultsSpan" runat="server"></span>
</li>
</ol>
</fieldset>
</div>
</asp:WizardStep>


finally in the codebehind file i puted the thread code which should send the newsletters and react on the client-side-clicks on the start/stop button. if the working-thread has ended it should alsso stop the client-side polling for news:

    /**********************
* Threading Methoden *
**********************/
protected static Thread _t = null; // globaler Thread

/// <summary>
/// Initialisiert den Cache
/// </summary>
private void LogInit()
{
Cache.Remove("Log");
DataTable dt = new DataTable("Log");
dt.Columns.Add("Datum", typeof(DateTime));
dt.Columns.Add("Beschreibung", typeof(string));
dt.Rows.Add(new object[] { DateTime.Now, "### Protokoll initialisiert ###" });
Cache["Log"] = dt;
}

/// <summary>
/// Fügt dem Protokoll einen Eintrag hinzu
/// </summary>
/// <param name="LogInfo"></param>
private void AddLog(string LogInfo)
{
DataTable dt = (DataTable)Cache["Log"];
if (dt != null)
{
dt.Rows.Add(new object[] { DateTime.Now, LogInfo });
Cache["Log"] = dt;
}
}

protected void StartWorkingThread()
{
// thread starten
_t = new Thread(new ThreadStart(this.Log));
_t.Priority = ThreadPriority.Lowest;
_t.Start();
_t.Join(); // don't return request until thread completes
}

protected void EndWorkingThread()
{
if (_t != null)
{
if (_t.IsAlive)
_t.Abort();
}
}

/// <summary>
/// Loop in dem der Worker-Thread abgearbeitet wird
/// </summary>
protected void Log()
{
DataTable dt = getVerteiler();
foreach (DataRow row in dt.Rows)
{
SendMail(tbBetreff2.Text, tbAnhang2.Text, tbText2.Text, row.ItemArray[0].ToString(), row.ItemArray[1].ToString(), row.ItemArray[2].ToString(), row.ItemArray[3].ToString(), row.ItemArray[4].ToString(), row.ItemArray[5].ToString(), false);
Thread.Sleep(100); // hier wird auf eventl. cancel gewartet 100 ist ein guter Wert
}
AddLog("### Ende Sendevorgang ###");
}

/// <summary>
/// Diese Funktion wird vom Client aufgerufen, sobald der 'start'-Button gedrückt wurde...
/// </summary>
/// <param name="eventArgument"></param>
public void RaiseCallbackEvent(String eventArgument)
{
if (bOnlyOnce) // start soll nur einmal ausgeführt werden
{
bOnlyOnce = false;
LogInit();
StartWorkingThread();
}

if (eventArgument == "cancel") // wurde stop gedrückt?
{
bOnlyOnce = true;
EndWorkingThread();
}
returnValue = WriteLog();

// wurde der Thread schon beendet soll auch der Client das Polling beenden
if (!_t.IsAlive && !bOnlyOnce)
returnValue = "cancel";
}

/// <summary>
/// Diese Funktion liest die Daten aus dem Cache und schreibt diesen zum Client zurück
/// </summary>
/// <returns></returns>
protected string WriteLog()
{
string sret = string.Empty;
DataTable dt = (DataTable)Cache["Log"];
if (dt != null)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
for (int i = 0; i < dt.Rows.Count; i++)
{
sb.Append(dt.Rows[0] + " / " + dt.Rows[1] + "<br />");
}

sret = sb.ToString();
}
else
sret = "!Kein Log zu schreiben!";
return sret;
}

/// <summary>
/// Ausgabe(string) wird zum Client retourniert
/// </summary>
/// <returns></returns>
public String GetCallbackResult()
{
return returnValue;
}


public partial class CMSInlineControls_PromontAM_admin_sendNewsletter : CMS.ExtendedControls.InlineUserControl, System.Web.UI.ICallbackEventHandler

what a pitty it does exactly the same thing as the ajax code with which i startet...

so perhaps i've done it wrong. in my testing envirmoent (without kentico and the code is just in an aspx-file) it works. so perhaps it doesn't work with usercontrols, or with the derived class i don't know...

greetings,
stefan.

User avatar
Member
Member
rookie07 - 7/7/2009 8:10:04 AM
   
RE:Inline control and ajax...
ok, just changes my test-scenario:

i puted the whole code in an web user control and now the ajax doesn't work anymore - so it seems that it has something todo with the usercontrol. if i would be able to write the asp.net-code directply into the page i'm sure i wouldn't have these problems...

regards,
stefan.

User avatar
Kentico Support
Kentico Support
kentico_jurajo - 7/22/2009 7:34:52 AM
   
RE:Inline control and ajax...
Hi,

That is very strange behavior. The only idea I have at this moment is to suggest you to consider another approach to achieve your need. You have chosen very complicated way to achieve your goal. Or, you can also try to use it as a web part in Kentico CMS.

Best Regards,
Juraj Ondrus

User avatar
Member
Member
rookie07 - 7/22/2009 1:17:19 PM
   
RE:Inline control and ajax...
than you for the reply. yes i was thinking to solve it in another way, becaus i've already tried to use a webpart, which didn't work too.

the only thing i need is a kind of responsive user interface to start, protcol (log) or to cancel the task which is going on in the background?

is there any workflow in kentico you would suggest?
by the way the kentico surface hase something similar if for example you are going to delete a document (you can cancel this by clicking a button)...that is very similar to the thing i need.

thank you anyway!

User avatar
Kentico Support
Kentico Support
kentico_jurajo - 7/23/2009 7:56:42 AM
   
RE:Inline control and ajax...
Hi,

For this are used the page call backs, also e.g. in content staging. There is a variable which is set if the cancel button is pressed, before each operation this property is checked, if the button was not pressed, it continues, if yes, the operation is finished.

Best Regards,
Juraj Ondrus

User avatar
Member
Member
rookie07 - 7/24/2009 3:04:35 AM
   
RE:Inline control and ajax...
hi,

that's funny because i've tried this also before (as you can read in the history). anyway i will find a workarround...

thank you!