|
// ******************************************************************************
// ******************************************************************************
// ASP.NET DaST Rendering Engine
// Copyright (C) 2011 Roman Gubarenko
// Project Home: http://aspnetdast.sourceforge.net/
// ******************************************************************************
// ******************************************************************************
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
// ******************************************************************************
// Primary Contact: rgubarenko@gmail.com
// Learn More: http://aspnetdast.sourceforge.net/
// Project Repository: http://sourceforge.net/projects/aspnetdast/
// ******************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.IO;
using System.Text.RegularExpressions;
using System.Web.UI.HtmlControls;
using AspNetDaST.Web.Private;
namespace AspNetDaST.Web
{
public abstract class DaSTPage : System.Web.UI.Page
{
private LiteralControl _ltrlBeforeHead;
private LiteralControl _ltrlAfterHead;
private LiteralControl _ltrlAfterBody;
private HtmlGenericControl _htmlTagBody;
internal bool IsAsyncPostBack { get; private set; }
protected override void OnPreInit(EventArgs e)
{
//
// PREPARE ASPX PAGE
//
// reorganize ASPX page to have needed structure of controls
// no matter what controls it already has in its .aspx markup
_ltrlBeforeHead = new LiteralControl("<html>\r\n");
_ltrlAfterHead = new LiteralControl("\r\n");
_ltrlAfterBody = new LiteralControl("\r\n</html>");
_htmlTagBody = new HtmlGenericControl("body");
Page.Controls.Clear();
Page.Controls.Add(_ltrlBeforeHead);
Page.Controls.Add(new HtmlHead());
Page.Controls.Add(_ltrlAfterHead);
Page.Controls.Add(_htmlTagBody);
Page.Controls.Add(_ltrlAfterBody);
_htmlTagBody.Controls.Add(new LiteralControl("\r\n "));
_htmlTagBody.Controls.Add(new HtmlForm() { ID = "DaSTPageForm" });
_htmlTagBody.Controls.Add(new LiteralControl("\r\n"));
// add script manager on the page
ScriptManager scriptManager = new ScriptManager();
scriptManager.ID = "DaSTPageScriptManager";
scriptManager.EnablePartialRendering = true;
scriptManager.Scripts.Add(new ScriptReference("AspNetDaST.Resources.AspNetDaST.js", "AspNetDaST"));
_htmlTagBody.FindControl("DaSTPageForm").Controls.AddAt(0, scriptManager);
// disable some standard features
Page.EnableViewState = false;
base.OnPreInit(e);
}
protected override void OnLoad(EventArgs e)
{
// detect async postback using script manager
IsAsyncPostBack = ScriptManager.GetCurrent(Page).IsInAsyncPostBack;
//
// BUILD DATA SCOPE TREE
//
// get page (root) scope controller
var rootController = ProvideRootController();
if (rootController == null) throw new DaSTException("Invalid root controller");
// build tree structure
ScopeTreeModel scopeTree = new ScopeTreeModel(rootController);
scopeTree.State = ScopeTreeModel.RenderState.BuildingTree;
// restore state
if (IsPostBack)
{
string strSavedState = Request.Form["__ASPNETDASTSTATE"];
ScopeTreeTools.DaSTState.RestoreDaSTState(strSavedState, scopeTree);
}
//
// PROCESS SCOPE ACTIONS
//
if (IsPostBack)
{
scopeTree.State = ScopeTreeModel.RenderState.HandlingActions;
string eventTarget = Request.Form["__EVENTTARGET"];
string eventArgument = Request.Form["__EVENTARGUMENT"];
try
{
PathExact actionPath = ScopeTreeTools.ClientBridge.ConvertClientID2ScopePath(eventTarget);
string actionName = eventArgument.Substring(0, eventArgument.IndexOf('|'));
object actionArg = Utility.JSON.ParseJSON(eventArgument.Substring(actionName.Length + 1));
// before invoking the hanlder, we need to restore
// part of scope tree lying on current action path
scopeTree.RebuildControllerModelsOnPath(actionPath);
// get current pointed node
var actionNode = scopeTree.GetNode(actionPath);
// invoke actual action handler
scopeTree.InvokeScopeActionHandler(
actionNode.Controller.TreeNode,
actionPath,
actionNode.Controller.TreeNode.NodePath,
actionName,
actionArg);
}
// TODO: throw more detailed error here
catch (Exception ex) { throw new Exception("Invalid postback action data"); }
}
//
// RENDER DATA SCOPE TREE
//
scopeTree.State = ScopeTreeModel.RenderState.RenderingTree;
var scopeOutputs = new Dictionary<PathExact, string>();
var treeRenderer = new ScopeTreeRenderer(scopeTree);
if (IsAsyncPostBack)
{
foreach (var renderPath in scopeTree.RefreshScopePaths)
{
using (MemoryStream stream = new MemoryStream())
{
treeRenderer.RenderSubtree(renderPath, stream);
string result = Encoding.ASCII.GetString(stream.ToArray());
// add refreshed scope output
scopeOutputs.Add(renderPath, result);
}
}
}
else
{
using (MemoryStream stream = new MemoryStream())
{
treeRenderer.RenderSubtree(PathExact.Empty, stream);
string result = Encoding.ASCII.GetString(stream.ToArray());
// add single root scope output
scopeOutputs.Add(PathExact.Empty, result);
}
}
//
// SERIALIZE RENDERED SCOPE TREE
//
string strNewState = ScopeTreeTools.DaSTState.BuildDaSTState(scopeTree);
ScriptManager.RegisterHiddenField(Page, "__ASPNETDASTSTATE", strNewState);
//
// WRITE PAGE OUTPUT
//
scopeTree.State = ScopeTreeModel.RenderState.WritingOutput;
if (IsAsyncPostBack)
{
StringBuilder output = new StringBuilder();
// add updatePanel response nodes
foreach (var kv in scopeOutputs)
{
string scopeClientID = ScopeTreeTools.ClientBridge.ConvertScopePath2ClientID(kv.Key);
output.AppendFormat("{0}|updatePanel|{1}|{2}|", kv.Value.Length, scopeClientID, kv.Value);
}
// add panelsToRefreshIDs response node
var updatePanelIDs = scopeOutputs.Select(kv => ScopeTreeTools.ClientBridge.ConvertScopePath2ClientID(kv.Key));
string strUpdatePanelIDs = string.Join(",", updatePanelIDs.ToArray());
output.AppendFormat("{0}|panelsToRefreshIDs||{1}|", strUpdatePanelIDs.Length, strUpdatePanelIDs);
// just write it directly to response
Page.Response.Write(output.ToString());
}
else
{
string output = scopeOutputs.Single().Value;
// break entire html document into parts
var htmlDoc = Utility.Rendering.DecomposeHtmlDoc(output);
if (htmlDoc == null) throw new DaSTException("Resulting HTML document has invalid structure");
// assign this parts to controls on ASPX page
if (htmlDoc.Title != null) Page.Title = htmlDoc.Title;
_ltrlBeforeHead.Text = htmlDoc.BeforeHead;
_ltrlAfterHead.Text = htmlDoc.AfterHead;
_ltrlAfterBody.Text = htmlDoc.AfterBody;
Header.Controls.Add(new LiteralControl(htmlDoc.Head));
Form.Controls.Add(new LiteralControl(htmlDoc.Body));
// also add body tag attributes
foreach (string key in htmlDoc.BodyAttrs.Keys)
{
_htmlTagBody.Attributes.Add(key, htmlDoc.BodyAttrs[key]);
}
// add client API startup script
Page.ClientScript.RegisterStartupScript(
this.GetType(),
"ASP.NET DaST Initialization Script",
"DaST.Scopes.initialize();\r\n",
true);
}
}
protected abstract ScopeController ProvideRootController();
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Software Architect with over 15 years in IT field. Started with deep math and C++ Computer Vision software. Currently in .NET and PHP web development. Creator of DaST pattern, open-source frameworks, and plugins. Interested in cutting Edge IT, open-source, Web 2.0, .NET, MVC, C++, Java, jQuery, Mobile tech, and extreme sports.