Click here to Skip to main content
15,896,063 members
Articles / Web Development / ASP.NET

ASP.NET DaST to wrestle with MVC and WebForms

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
26 Mar 2013CPOL82 min read 23.2K   152   11  
DaST is a new architectural pattern for building highly dynamic Web 2.0 applications. A web page is rendered as a set of randomly nested rectangles where each rectangle is controlled individually and every combination of rectangles can be partially updated via AJAX.
// --------------------------- COPYRIGHT NOTICE ---------------------------------
// ASP.NET DaST - LittleNonsense DEMO
// Copyright (C) 2011 by Roman Gubarenko
// http://www.makeitsoft.com/
// ------------------------------------------------------------------------------
//
// 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
// Project Home     : http://www.makeitsoft.com/
// Help & Support   : http://www.makeitsoft.com/forums/
// ------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using AspNetDaST.Web;

/// <summary>
/// Summary description for NonsenseAdvanced
/// </summary>
public class NonsenseExample3Controller : ScopeController
{
  public override string ProvideTemplate()
  {
    return Utils.LoadTemplate("NonsenseExample3.htm"); // load temlate content from anywhere
  }

  public override void InitializeModel(ControllerModelBuilder model)
  {
    // bind scopes individually using dedicated handlers
    model.SetDataBind(new DataBindHandler(DataBind_ROOT));
    model.Select("CustomerRepeater").SetDataBind(new DataBindHandler(DataBind_CustomerRepeater));
    model.Select("CustomerRepeater", "Customer").SetDataBind(new DataBindHandler(DataBind_Customer));
    model.Select("CustomerRepeater", "Customer", "OrderRepeater").SetDataBind(new DataBindHandler(DataBind_OrderRepeater));
    model.Select("CustomerRepeater", "Customer", "OrderRepeater", "Order").SetDataBind(new DataBindHandler(DataBind_Order));
    model.Select("CustomerRepeater", "Customer", "OrderRepeater", "Order", "ItemRepeater").SetDataBind(new DataBindHandler(DataBind_ItemRepeater));
    model.Select("CustomerRepeater", "Customer", "OrderRepeater", "Order", "ItemRepeater", "Item").SetDataBind(new DataBindHandler(DataBind_Item));

    // handle SubmitInput action coming from the client
    model.HandleAction("SubmitInput", new ActionHandler(Action_SubmitInput));
  }


  #region Action Handlers

  private void Action_SubmitInput(object arg)
  {
    // retrive values from JSON data passed by client action
    string scopeID = (string)((object[])arg)[0]; // scopeID is first element in array
    string input = (string)((object[])arg)[1]; // actual input text is second elemetn in array
    var info = (Dictionary<string, object>)((object[])arg)[2]; // last element is complex info object

    // get path to the scope where input is submitted (our target scope)
    object[] scopePath = DaSTUtils.ScopeID2Path(scopeID); 
    // use scope path to set appropriate scope params for partial rendering
    string custName = (string)info["Customer"]; // get string customer name
    if (!string.IsNullOrEmpty(custName)) // if customer is passed ...
    {
      var customer = DataLayer.GetCustomers().Single(c => (string)c.GetValue("Name") == custName); // find customer object
      CtrlPath(scopePath).Params.Set("CustomerObject", customer); // set customer object as scope parameter

      string orderID = (string)info["Order"]; // get string order id
      if (!string.IsNullOrEmpty(orderID)) // if order id is passed ...
      {
        var order = DataLayer.GetOrders(custName).Single(o => (string)o.GetValue("ID") == orderID); // find order object
        CtrlPath(scopePath).Params.Set("OrderObject", order); // set order object as scope parameter

        string itemName = (string)info["Item"]; // get string item name
        if ((!string.IsNullOrEmpty(itemName))) // if item name is set ...
        {
          var item = DataLayer.GetOrderItems(orderID).Single(i => (string)i.GetValue("Name") == itemName); // find item object
          CtrlPath(scopePath).Params.Set("ItemObject", item); // set item object as scope parameter
        }
      }
    }

    // pass user input text to the target scope to display this input text in the scope header
    CtrlPath(scopePath).Params.Set("PostedData", input);

    // refresh target scope
    CtrlPath(scopePath).Refresh();

    // send message to the client passing scope id in JSON data object
    CtrlPath().MessageClient("InputSubmitted", new { ScopeID = scopeID });
  }

  #endregion


  #region Binding Handlers

  private void DataBind_ROOT()
  {
    CurrPath().Replace("{TodayDate}", DateTime.Now.ToString("yyyy-MM-dd")); // output some example values
  }

  private void DataBind_CustomerRepeater()
  {
    var customers = DataLayer.GetCustomers(); // get all customers

    CurrPath().RepeatStart(); // must be called before repeating scope content
    foreach (var customer in customers) // loop through all customers and bind their values
    {
      CurrPath().Repeat(); // must repeat scope content before binding any values
      RenderGizmoHeaderValues(); // bind common header values

      CurrPath("Customer").Params.Set("CustomerObject", customer); // use scope params to pass customer object to next scope 
    }
  }

  private void DataBind_Customer()
  {
    var customer = CurrPath().Params.Get<object>("CustomerObject"); // retrieve customer object passed in params
  
    CurrPath().Replace("{CustomerName}", customer.GetValue("Name")); // bind customer name
    RenderGizmoHeaderValues(); // bind common header values 

    CurrPath("OrderRepeater").Params.Set("CustomerObject", customer); // use scope params to pass customer object to next scope
  }

  private void DataBind_OrderRepeater()
  {
    var customer = CurrPath().Params.Get<object>("CustomerObject"); // retrieve customer object passed in params
    var orders = DataLayer.GetOrders((string)customer.GetValue("Name")); // retrieve orders for this customer

    CurrPath().RepeatStart(); // must be called before repeating scope content
    foreach (var order in orders) // loop through all orders and bind their values
    {
      CurrPath().Repeat(); // must repeat scope content before binding any values
      RenderGizmoHeaderValues(); // bind common header values

      CurrPath("Order").Params.Set("OrderObject", order); // use scope params to pass order object to next scope
    }
  }

  private void DataBind_Order()
  {
    var order = CurrPath().Params.Get<object>("OrderObject"); // retrieve order object passed in params
  
    CurrPath().Replace("{OrderID}", order.GetValue("ID")); // bind order id
    RenderGizmoHeaderValues(); // bind common header values

    CurrPath("ItemRepeater").Params.Set("OrderObject", order); // use scope params to pass order object to next scope
  }

  private void DataBind_ItemRepeater()
  {
    var order = CurrPath().Params.Get<object>("OrderObject"); // retrieve order object passed in params
    var items = DataLayer.GetOrderItems((string)order.GetValue("ID")); // retrieve items for this order

    CurrPath().RepeatStart(); // must be called before repeating scope content
    foreach (var item in items) // loop through all order items and bind their values
    {
      CurrPath().Repeat(); // must repeat scope content before binding any values
      RenderGizmoHeaderValues(); // bind common header values

      CurrPath("Item").Params.Set("ItemObject", item); // use scope params to pass item object to next scope
    }
  }

  private void DataBind_Item()
  {
    var item = CurrPath().Params.Get<object>("ItemObject"); // retrieve item object passed in params
    
    CurrPath().Replace("{ItemName}", item.GetValue("Name")); // bind item name
    RenderGizmoHeaderValues(); // bind common header values
  }

  #endregion


  #region Helper Utils

  // shorcut to bind common header values
  private void RenderGizmoHeaderValues()
  {
    CurrPath().Replace("{Updated}", DateTime.Now.ToString("HH:mm:ss")); // bind update time
    CurrPath().Replace("{ScopeID}", CurrPath().ClientID); // bind scope client id
    if (CurrPath().Params.Has("PostedData")) // if PostedData param is set for the scope ...
    {
      var data = CurrPath().Params.Get<string>("PostedData"); // retrive posted data containing user input

      CurrPath().Replace("{PostedData}", data); // bind input value to output it
      CurrPath().AreaConditional("data-posted", true); // display data-posted conditional area 
    }
    else
    {
      CurrPath().AreaConditional("data-posted", false); // hide data-posted conditional area
    }
  }

  #endregion
}

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Canada Canada
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.

Comments and Discussions