Sep 07, 2008, 12:16 PM
The GridPanel/Store saving description
Hi All,
I want to clarify the GridPanel/Store saving model:
The content of GridPanel can be saved using to approaches:
1. Using UpdateProxy
2. Using ajax request to the page which contains Store control.
If UpdateProxy is missing in Store then will be used second approach. For triggering saving need to call save function of GridPanel, for example
------------------
1. Saving using UpdateProxy.
If Store contain UpdateProxy then saving function will be pass saved data to update proxy. Examples of UpdateProxy
Example1
Example2
How to handle submitted data on server
The changed data submitted on server in "data" form field. You can retrieve with next code
This class allowing the developer represent the submitted data as Json string, as Xml or as Object collection (if you have bussines object on which can be mapped submitted data)
List<T> Inserted
List<T> Deleted
List<T> Updated
The developer can specified additional parameters which will be passed to server during save ajax request. The parameters can be specified in WriteBaseParams. In HtppHandler (or any page) these parameters can be retrieved from Request.Form collection, if using web service then each parameter must be in signature of web method
Let's see on example of saving data in HttpHandler
2. Saving with internal Store saving model
With this approach all form controls will be submit to server (as in classic postback)
When the UpdateProxy is not specified then will be used internal Store saving. If was specified any IDataSource(SqlDataSource, ObjectDataSource and etc) then they will be used (will be called Insert, Delete, Update of IDataSource). The IDataSource can be specified in DataSourceID of Store
The Store events sequence:
- BeforeAjaxPostBack - fired before any store ajax action: now supported "update" and "refresh" actions. Available next properties in BeforeAjaxPostBackEventArgs: Action, Data (StoreDataHandler which contains submitted data), Parameters (parameters collection passed from client)
if action == "refresh" then
- RefreshData - fired when the should be refresh data. The developer should bind new data on this event. In StoreRefreshDataEventArgs available next properies: Parameters (parameters from client), Start, Limit, Sort, Dir (for suppoerting remote paging and sorting)
if action == "update" then
-- BeforeStoreChanged - fired before all actions related with modifications.In the BeforeStoreChangedEventArgs available: Parameters (parameters from client), DataHandler (StoreDataHandler which contains submitted data). In this event the developer can implenet own logic batch saving (using data from DataHandler). The Developer can set Cancel property of BeforeStoreChangedEventArgs to true for cancel all automatic modification actions
if Cancel from BeforeStoreChangedEventArgs then perform next actions
--- BeforeRecordUpdated - fired for each changed record before updating. If using IDataSource specified in DataSourceID then will be used Update function of IDataSource after this event. If doesn't specified then in this event the developer can specify own logic of updating. In BeforeRecordUpdatedEventArgs available: Record (XmlNode with changed record), keys (id field of changed record), NewValues collection, OldValues (now always empty, in future will be contain old values).
The developer can cancel IDataSource action (set Cancel) or all Update actions (set CancelAll)
--- AfterRecordUpdated - fired after IDataSource update calling (or after BeforeRecordUpdated if IDataSource doesn't specified)
--- BeforeRecordDeleted
--- AfterRecordDeleted
--- BeforeRecordInserted
--- AfterRecordInserted
-- AfterStoreChanged - fired after all modification actions.
- AfterAjaxPostBack - fired after all actions before building response for client. The developer can change AjaxResponse object in AfterAjaxPostBackEventArgs
3. Saving with confirmation
By default the Store on client need only Succes field for confirmation all changes. But there are cases when such behaivor is not applicable (for example, when part of records are saved successfully and part not, or when need to pass new id's to client for inserted records)
For use confirmation need to set UseIdConfirmation="true" for Store. The Store has property RefreshAfterSaving (None, Auto, Always). The auto is default. The RefreshAfterSaving property manages refreshing behaivor after saving: None - no refreshing, Always - always refresh after saving, Auto - refresh if exists deleted or insterted records only. If using UseIdConfirmation="true" then RefreshAfterSaving can set to None.
If developer using confirmation then he must build confirmation list for returning to client.
Example if using UpdateProxy (HttpHandlers, aspx pages, web services and etc)
I want to clarify the GridPanel/Store saving model:
The content of GridPanel can be saved using to approaches:
1. Using UpdateProxy
2. Using ajax request to the page which contains Store control.
If UpdateProxy is missing in Store then will be used second approach. For triggering saving need to call save function of GridPanel, for example
<ext:Button runat="server" ID="btnSave" Text="Save" AutoPostBack="false" Icon="Disk">
<Listeners>
<Click Handler="#{GridPanel1}.save();" />
</Listeners>
</ext:Button>
I splitted description on several post for easy navigation------------------
1. Saving using UpdateProxy.
If Store contain UpdateProxy then saving function will be pass saved data to update proxy. Examples of UpdateProxy
Example1
<UpdateProxy>
<ext:HttpWriteProxy Method="POST" Url="../Shared/Save.ashx" />
</UpdateProxy>
In this example the changed records will be submit to HttpHandler Save.ashx (instead handler you can use any aspx page)Example2
<UpdateProxy>
<ext:HttpWriteProxy Method="POST" Url="../Shared/CustomerService.asmx/SaveCustomers" HandleSaveResponseAsXml="true" />
</UpdateProxy>
In this example we use WebService. Please pay attention that must be set two properties: Method=POST and HandleSaveResponseAsXml="true" (this indicate that save response from server will be has xml representation)How to handle submitted data on server
The changed data submitted on server in "data" form field. You can retrieve with next code
Request.Form["data]
If you use webservice then signature of saving method should be (of course the name can be free) [WebMethod]
public AjaxResponse SaveCustomers(string data)
{
.....
}
For easy handling of submitted data on server you can use StoreDataHandler class. The constructor of this class accept the HttpContext or submitted data (as string).This class allowing the developer represent the submitted data as Json string, as Xml or as Object collection (if you have bussines object on which can be mapped submitted data)
StoreDataHandler dataHandler = new StoreDataHandler(context); // where context is HttpContext
string json = dataHandler.JsonData;
ChangeRecords<Customer> data = dataHandler.ObjectData<Customer>(); //as object collection
XmlDocument xml = dataHandler.XmlData;
The Object data return ChangeRecords<T> class. This class contains three collectionList<T> Inserted
List<T> Deleted
List<T> Updated
The developer can specified additional parameters which will be passed to server during save ajax request. The parameters can be specified in WriteBaseParams. In HtppHandler (or any page) these parameters can be retrieved from Request.Form collection, if using web service then each parameter must be in signature of web method
Let's see on example of saving data in HttpHandler
public void ProcessRequest(HttpContext context)
{
//Create instance and passing to the constructor HttpContext for automatically retrieving submitted data
StoreDataHandler gd = new StoreDataHandler(context);
//Class for building save response for confirmation on client
AjaxResponse sr = new AjaxResponse(true);
try
{
//Convert data to business objects collection
ChangeRecords<Customer> data = gd.ObjectData<Customer>();
//performs update actions
foreach (Customer customer in data.Deleted)
{
Customers.Delete(customer);
}
foreach (Customer customer in data.Updated)
{
Customers.Update(customer);
}
foreach (Customer customer in data.Created)
{
Customers.Insert(customer);
}
}
catch (Exception e)
{
//if were errors then we should to tell client that saving request was unsuccessful
sr.Success = false;
sr.Msg = e.Message;
}
//Convert AjaxResponse to json string and send to client
sr.MakeAnswer();
}
Example with saving in WebService (please pay attention that for UpdateProxy should be set Method=POST and HandleSaveResponseAsXml="true"). The signature of web method can be siffer if using WriteBaseParams (in this case each parameter must be in signature) [WebMethod]
public AjaxResponse SaveCustomers(string data)
{
//Create instance and passing to the constructor the submitted data
StoreDataHandler gd = new StoreDataHandler(data);
... the same as in above example
//return answer
return sr;
}
2. Saving with internal Store saving model
With this approach all form controls will be submit to server (as in classic postback)
When the UpdateProxy is not specified then will be used internal Store saving. If was specified any IDataSource(SqlDataSource, ObjectDataSource and etc) then they will be used (will be called Insert, Delete, Update of IDataSource). The IDataSource can be specified in DataSourceID of Store
The Store events sequence:
- BeforeAjaxPostBack - fired before any store ajax action: now supported "update" and "refresh" actions. Available next properties in BeforeAjaxPostBackEventArgs: Action, Data (StoreDataHandler which contains submitted data), Parameters (parameters collection passed from client)
if action == "refresh" then
- RefreshData - fired when the should be refresh data. The developer should bind new data on this event. In StoreRefreshDataEventArgs available next properies: Parameters (parameters from client), Start, Limit, Sort, Dir (for suppoerting remote paging and sorting)
if action == "update" then
-- BeforeStoreChanged - fired before all actions related with modifications.In the BeforeStoreChangedEventArgs available: Parameters (parameters from client), DataHandler (StoreDataHandler which contains submitted data). In this event the developer can implenet own logic batch saving (using data from DataHandler). The Developer can set Cancel property of BeforeStoreChangedEventArgs to true for cancel all automatic modification actions
if Cancel from BeforeStoreChangedEventArgs then perform next actions
--- BeforeRecordUpdated - fired for each changed record before updating. If using IDataSource specified in DataSourceID then will be used Update function of IDataSource after this event. If doesn't specified then in this event the developer can specify own logic of updating. In BeforeRecordUpdatedEventArgs available: Record (XmlNode with changed record), keys (id field of changed record), NewValues collection, OldValues (now always empty, in future will be contain old values).
The developer can cancel IDataSource action (set Cancel) or all Update actions (set CancelAll)
--- AfterRecordUpdated - fired after IDataSource update calling (or after BeforeRecordUpdated if IDataSource doesn't specified)
--- BeforeRecordDeleted
--- AfterRecordDeleted
--- BeforeRecordInserted
--- AfterRecordInserted
-- AfterStoreChanged - fired after all modification actions.
- AfterAjaxPostBack - fired after all actions before building response for client. The developer can change AjaxResponse object in AfterAjaxPostBackEventArgs
3. Saving with confirmation
By default the Store on client need only Succes field for confirmation all changes. But there are cases when such behaivor is not applicable (for example, when part of records are saved successfully and part not, or when need to pass new id's to client for inserted records)
For use confirmation need to set UseIdConfirmation="true" for Store. The Store has property RefreshAfterSaving (None, Auto, Always). The auto is default. The RefreshAfterSaving property manages refreshing behaivor after saving: None - no refreshing, Always - always refresh after saving, Auto - refresh if exists deleted or insterted records only. If using UseIdConfirmation="true" then RefreshAfterSaving can set to None.
If developer using confirmation then he must build confirmation list for returning to client.
Example if using UpdateProxy (HttpHandlers, aspx pages, web services and etc)
public void ProcessRequest(HttpContext context)
{
StoreDataHandler gd = new StoreDataHandler(context);
AjaxResponse sr = new AjaxResponse(true);
//build initial confirmation list and passing to constructor id field name
ConfirmationList confirmationList = gd.BuildConfirmationList("CustomerId");
try
{
ChangeRecords<Customer> data = gd.ObjectData<Customer>();
foreach (Customer customer in data.Deleted)
{
Customers.Delete(customer);
//Confirm action for current record
confirmationList[customer.CustomerId].ConfirmRecord();
}
foreach (Customer customer in data.Updated)
{
Customers.Update(customer);
//Confirm action for current record
confirmationList[customer.CustomerId].ConfirmRecord();
}
foreach (Customer customer in data.Created)
{
Customers.Insert(customer);
confirmationList[customer.CustomerId].ConfirmRecord();
//DON'T FORGET TO PASS NEW ID WHEN CONFIRMING INSERTED RECORD
//if Id set on sql server side then need set new id when confirming record
//confirmationList[customer.CustomerId].ConfirmRecord(newId);
}
}
catch (Exception e)
{
sr.Success = false;
sr.Msg = e.Message;
}
StoreResponseData response = new StoreResponseData();
response.Confirmation = confirmationList;
sr.Data = response.ToString();
sr.MakeAnswer();
}
If using internal Store saving model the need confirm records in AfterRecord... events. If IDataSource exist then records will be confirm automatically (based on recordAffected argiment in IDataSource callback function but ned id must be setted by the developer manually). If no IDataSource then developer must confirm all actions private string insertedValue;
protected void SqlDataSource1_Inserted(object sender, SqlDataSourceStatusEventArgs e)
{
//use e.AffectedRows for ensure success action. The store read this value and set predefined Confirm depend on e.AffectedRows
//The Confirm can be granted or denied in OnAfterRecord.... event
//e.Command.Parameters["@SupplierID"] - output parameter of SqlDataSource
insertedValue = e.Command.Parameters["@SupplierID"].Value != null
? e.Command.Parameters["@SupplierID"].Value.ToString()
: "";
}
protected void Store1_AfterRecordInserted(object sender, AfterRecordUpdatedEventArgs e)
{
//If IDataSource specified then deleted and updated records confirms automatic (depending AffectedRows field)
//But you can override this in AfterRecordUpdated and AfterRecordDeleted event
//For insert we should set new id for refresh on client
//If we don't set new id then old id will be used
if(e.Confirmation.Confirm && !string.IsNullOrEmpty(insertedValueId))
{
e.Confirmation.ConfirmRecord(insertedValueId);
insertedValue = "";
}
}
Please don't hesitate to post your questions