protected sealed override void FinishAjaxRequest()
        {
            // ajax request
            OSJSONResponse resp = CreateJSONResponse();

            if (!AjaxRedirectLocation.IsEmpty())
            {
                // ajax redirect...
                WriteAJAXClientRedirectResponse(Request, Response, AjaxRedirectLocation);
                return;
            }

            if (_partialViewStateBuckets.Count > 0)
            {
                // include in JSON response the updated viewstate buckets that is
                // at this moment stored in _partialViewStateBuckets
                foreach (string bucketName in _partialViewStateBuckets.Keys)
                {
                    resp.AddToHidden(bucketName, _partialViewStateBuckets[bucketName].ToString());
                }
            }
            // send the end request signal
            resp.AddToJs("OsEndRequest()");
            WriteJavascriptResponse(FormatJSONResponseString(resp), /*flush*/ false);

            return;
        }
        public string GetEndPageJavaScript()
        {
            string ret = "";
            // send all the queued javascript, if any
            string onloadVSUpdate = OnloadVSUpdate;

            if (onloadVSUpdate.Length > 0)
            {
                ret += "<script type=\"text/javascript\">outsystems.internal.$._waitForViewstate = true;" +
                       "outsystems.internal.$(document).ready(function() {outsystems.internal.$('input[name=__OSVSTATE]').val('" + onloadVSUpdate + "');" +
                       "outsystems.internal.$._waitForViewstate = false;});</script>\n";
            }

            if (_javascriptQueueResponse.Js.Count > 0)
            {
                if (IsFirstAjaxResponse)
                {
                    ret += JavascriptBeginTag + GetJsonUpdateScript() + JavascriptEndTag;
                }

                OSJSONResponse resp = new OSJSONResponse();
                resp.AddToJs("outsystems.internal.$(document).ready(function() {" + FormatJSONResponseString(_javascriptQueueResponse) + "});");

                ret += JavascriptBeginTag + FormatJSONResponseString(resp) + JavascriptEndTag;
            }

            return(ret);
        }
        private OSJSONResponse CreateJSONResponse()
        {
            OSJSONResponse resp = new OSJSONResponse();

            // ensure that block javascripts are sent in the first response
            resp.AddToBlockJs(BlocksJavaScript.BlockJavaScriptIncludeFilenames);
            return(resp);
        }
        public static void WriteAJAXClientRedirectResponse(HttpRequest request, HttpResponse response, string location)
        {
            OSJSONResponse resp = new OSJSONResponse();

            resp.AddOtherValues("__RedirectToURL", location);
            // write the JSON response
            try {
                WriteJavascriptResponse(request, response, FormatJSONResponseString(resp), /*flush*/ false);
                //this way the padding win't go on a separate chunk
                response.Flush();
            } catch {
                // Ignore errors writting the response (eg: client closed tab)
            }
        }
 public virtual void AddQueuedJavascript(string script)
 {
     if (IsAjaxRequest && !_isRefreshingWidget)
     {
         //immediate js
         OSJSONResponse resp = CreateJSONResponse();
         resp.AddToJs(script);
         WriteJavascriptResponse(FormatJSONResponseString(resp), /*flush*/ true);
     }
     else
     {
         //queue javascript
         _javascriptQueueResponse.AddToJs(script);
     }
 }
        protected override void SavePageStateToPersistenceMedium(object viewState)
        {
            string name;
            string value;

            ParseViewStateForCachedObjects(viewState);

            // clear previous partial viewstate buckets
            _partialViewStateBuckets.Clear();

            // save main viewstate bucket
            name = "__OSVSTATE";
            string hash;

            value = SerializeViewState(viewState, out hash);


            if (IsAjaxRequest)
            {
                RegisterPartialViewState(name, value, hash);
            }
            else
            {
                // register the viewstate field
                ClientScript.RegisterHiddenField(name, value);

                // Set VIEWSTATE = "" so that Page::RenderViewStateFields() doesn't go through the buggy code branch that renders a CR inside the element's ID...
                this.GetType().GetProperty("ClientState", BindingFlags.Instance | BindingFlags.NonPublic).GetSetMethod(true).Invoke(this, new object[] { "" });

                if (_resetViewStateField)
                {
                    // #110767 - Add queued javascript to run when document is ready and set the viewstate with the proper value
                    // This will override input field cache for the viewstate field.
                    OSJSONResponse resp = new OSJSONResponse();
                    resp.AddToHidden(name, value);
                    // Ensure that this is the first queued javascript to be executed!
                    //_javascriptQueueResponse.InsertToJs(0, FormatJSONResponseString(resp));
                    //_javascriptQueueResponse.AddToHidden(name, value);
                    OnloadVSUpdate = value;
                }
            }
        }
        private static void WriteJavascriptResponse(HttpRequest request, HttpResponse response, string script, bool flush)
        {
            try {
                bool isIE =

                    (request.Browser.Browser == "IE");

                response.ContentType = "text/html";



                // #90781
                // Internet explorer requires the first ajax response to be of at least 256 bytes, otherwise it will
                // only be executed when the receive buffer fills up in subsequent responses or when the request ends.
                // After that, subsequent responses can be of any size that they are executed promptly
                if (IsFirstAjaxResponse && isIE)
                {
                    // This padding string ensures that 256 bytes are sent, even when compression is enabled
                    // Using deflate compression stream, it outputs 256 bytes
                    // Using gzip compression stream, it outputs 266 bytes
                    // Using no compression, it outputs 334 bytes
                    string firstPadding = "<!-- OSPADDING VURGXTTJYZMCVZAFKKOPWKYUBXQDXDADFBRUSOSCDMISJYMZIROBPVAHBEFPZLMQVJXTEGNVRMLKCGGCLQQBLYJFAFTOEYYOARSAWSRCEVURGXTTJYZMCVZAFKKOPWKYUBXQDXDADFBRUSOSCDMISJYMZIROBPVAHBEFPZLMQVJXTEGNVRMLKCGGCLQQBLYJFAFTOEYYOARSAWSRCEVURGXTTJYZMCVZAFKKOPWKYUBXQDXDADFBRUSOSCDMISJYMZIROBPVAHBEFPZLMQVJXTEGNVRMLKCGGCLQQBLYJFAFTOEYYOARSAWSRCE -->";
                    response.Write(firstPadding);
                }

                if (IsFirstAjaxResponse)
                {
                    // Make sure the JSONUpdate function is defined in the current window
                    response.Write(JavascriptBeginTag + GetJsonUpdateScript() + JavascriptEndTag);
                    try {
                        //Add requestInfo necessary data for beacon in performanceprobe.js
                        OSJSONResponse resp       = new OSJSONResponse();
                        RequestTracer  perfTracer = AppInfo.GetAppInfo().OsContext.RequestTracer;
                        resp.AddToJs("OsSetRequestInfo('{0}','{1}','{2}')".F(perfTracer.RequestKey, perfTracer.EntryActionName, perfTracer.EntryActionKey));
                        response.Write(JavascriptBeginTag + FormatJSONResponseString(resp) + JavascriptEndTag);
                    } catch (Exception e) {
                        ErrorLog.LogApplicationError(e, null, "WebWidgets");
                    }
                    IsFirstAjaxResponse = false;
                }

                // This padding ensures that, if we are using a compression filter, that the output
                // is completely flushed to the underlying stream.
                // It is needed because the compression may flush every but the last few bytes.
                // Usually in a compressed flush the last one or two bytes will be missing.
                string padding = "<!-- OSPADDING -->";

                // write the respose and its end tag
                response.Write(JavascriptBeginTag + script + JavascriptEndTag);
                if (RuntimePlatformUtils.IsJava() || flush)
                {
                    response.Flush();
                }
                response.Write(padding);
                if (RuntimePlatformUtils.IsJava() || flush)
                {
                    //the padding goes on a separate chunk to make sure the actual content
                    //get's flushed to the client
                    response.Flush();
                }
            } catch {
                // Ignore errors writting the response (eg: client closed tab)
            }
        }
 //returns the output string from an OSJSONResponse object, ready to be interpreted by the osajax Javascript library included in AJAX aware pages
 private static string FormatJSONResponseString(OSJSONResponse resp)
 {
     return("OsJSONUpdate(" + resp.ToString() + ")");
 }
        public void AjaxRefresh(Control c, int rowIndex, string animationName, string listOperation, bool isTableRecord, object dataItem, StoreViewStateDelegate storeViewStateDelegate, string clientIdOverride)
        {
            // don't do nothing if not in a partial request or if the control is not accessible (e.g.: refreshing widgets inside table records from outside)
            if (!IsAjaxRequest || c == null)
            {
                return;
            }

            // mark that we are refreshing a widget, so that possible queued javascripts happening in the databind are queued
            // to be sent immediately after the control json (for web block preparations or user defined functions execution)
            _isRefreshingWidget = true;

            try {
                LocalState stackBackup = null;
#if JAVA
                HashSet <IAbstractTopLevelComponentWithMandatory> previousVisibleComponentsWithValidation = null,
                                                                  newVisibleComponentsWithValidation      = null;
#endif


                if (c is OSUserControl)
                {
                    OSUserControl blk = (OSUserControl)c;
                    stackBackup = ((IWebScreen)blk.Page).PushStack();
                }
                else
                {
                    stackBackup = ((IWebScreen)c.Page).PushStack();
                }

                if (listOperation == "")
                {
#if JAVA
                    previousVisibleComponentsWithValidation = GetVisibleComponentsWithValidation(c);
#endif

                    // databind the control
                    c.DataBind();

#if JAVA
                    newVisibleComponentsWithValidation = GetVisibleComponentsWithValidation(c);
#endif
                }
                else
                {
                    // some list operation

                    if (!isTableRecord)
                    {
                        // list records require the prerender phase before list append, insert and remove operations, since prerender creates the current child controls hierarchy
                        MethodInfo preRenderRecursiveInternal = typeof(Page).GetMethod("PreRenderRecursiveInternal", BindingFlags.NonPublic | BindingFlags.Instance);
                        preRenderRecursiveInternal.Invoke(c, null);
                    }

                    IListRefresh listWidget = (IListRefresh)c;
                    // execute the list refresh databind to restore LineCount and StartIndex runtime properties in the table / list record
                    listWidget.DoListRefreshDataBind();
                    // execute the operation in the list
                    switch (listOperation)
                    {
                    case "Append":
                        listWidget.AppendItem(dataItem);
                        break;

                    case "Insert":
                        listWidget.InsertItem(rowIndex, dataItem);
                        break;

                    case "Remove":
                        listWidget.RemoveItem(rowIndex);
                        break;

                    case "Refresh":
                        listWidget.RefreshItem(rowIndex);
                        break;

                    default:
                        System.Diagnostics.Debug.Assert(false, "unknown list operation: " + listOperation);
                        break;
                    }
                }

                // call store viewstate in the calling page / block

                storeViewStateDelegate();

                if (stackBackup != null)
                {
                    Debugger.Pop(stackBackup, true);
                }

                // save partial viewstate and get modified buckets

                Hashtable modifiedBuckets = PartialSaveAllState();

                OSJSONResponse resp = CreateJSONResponse();

                // build JSON response with the control rendering and modified buckets

                foreach (string bucketName in modifiedBuckets.Keys)
                {
                    resp.AddToHidden(bucketName, modifiedBuckets[bucketName].ToString());
                }

                string html = "";

                if (listOperation == "")
                {
                    // regular ajax refresh
                    // render control and add it to outers
                    resp.AddToOuter(c.ClientID, RenderControl(c));

#if JAVA
                    ProcessComponentsWithValidationTurnedInvisible(previousVisibleComponentsWithValidation,
                                                                   newVisibleComponentsWithValidation);
#endif
                }
                else
                {
                    // implicit ajax refresh via ListAppend, ListInsert or ListRemove
                    if (listOperation == "Append")
                    {
                        html = RenderAjaxListOperationRow(c);
                    }
                    else if (listOperation == "Insert")
                    {
#if JAVA
                        html = RenderAjaxListOperationRow(c, rowIndex);
#else
                        html = RenderAjaxListOperationRow(c);
#endif
                    }
                    else if (listOperation == "Remove")
                    {
                        // need to render the empty message?
                        if (((IListRefresh)c).IsEmpty)
                        {
                            html = RenderAjaxListOperationRow(c, true);
                        }
                    }
                    else if (listOperation == "Refresh")
                    {
                        // row refresh operation
                        html = RenderAjaxListOperationRow(c, rowIndex);
                    }

                    string oddLineStyle  = "";
                    string evenLineStyle = "";
                    bool   useBullets    = false;

                    if (c is OSDataGrid)
                    {
                        // get table record information to be sent to the client js
                        OSDataGrid dg = (OSDataGrid)c;
                        oddLineStyle  = dg.OddLineStyle ?? oddLineStyle;
                        evenLineStyle = dg.EvenLineStyle ?? evenLineStyle;
                    }
                    else
                    {
                        // get list record information to be sent to the client js
                        Iterator it = (Iterator)c;
                        useBullets = it.UseBullets;
                    }

                    resp.AddToList(clientIdOverride ?? c.ClientID, html, listOperation, rowIndex, isTableRecord, oddLineStyle, evenLineStyle, useBullets);
                }


                // Add call to animation registration
                if (animationName != null && animationName != "None")
                {
                    if (listOperation == "Remove" && animationName == "Highlight")
                    {
                        animationName = "ListRemoveHighlight";
                    }
                    resp.AddToJs("OsRegisterEffect" + animationName.Replace(" ", "") + "();");
                }

                // write and flush the response
                WriteJavascriptResponse(FormatJSONResponseString(resp), /*flush*/ true);

                // send all the queued javascript gathered in this refresh
                if (_javascriptQueueResponse.Js.Count > 0)
                {
                    resp = CreateJSONResponse();
                    resp.AddToJs("outsystems.internal.$(document).ready(function() {" + FormatJSONResponseString(_javascriptQueueResponse) + "});");
                    // clear it for next executions
                    _javascriptQueueResponse.ClearJs();
                    // write the response
                    WriteJavascriptResponse(FormatJSONResponseString(resp), /*flush*/ true);
                }

                // cleanup JavaScript includes so the next refresh will not re-include it
                BlocksJavaScript.CleanupAlreadyIncludedBlocksWithJavaScript();
            } finally {
                // we're no longer refreshing a widget
                _isRefreshingWidget = false;
            }
        }