[CLOSED] When HttpWriteProxy fails Save listener still invoked instead of SaveException listener

  1. #1

    [CLOSED] When HttpWriteProxy fails Save listener still invoked instead of SaveException listener

    Hi,

    I am finding is this:

    1. I use an HttpWriteProxy and in the ashx implementation if there is some error condition, I set the storeResponse's Success property to false
    2. When looking at the http requests and responses I see the correct Success (true or false) being set
    3. But by the time the Store listeners are invoked, it seems only the Save listener is invoked and it is only passed the message, not the success property
    4. The SaveException listener is not invoked

    This means it is hard to determine whether I am handling a save or failure condition (unless I structure the string message into a serialized JSON object with more information, but that feels like bit of a workaround).

    Question 1: Is this a bug and should SaveException listener be invoked instead?

    Question 2: If Save must always be invoked regardless of success or failure, can the arg also have the success property, because all I see is just the message property?

    Here's a working demo (with specific steps to reproduce below it):

    1) The ASPX

    <%@ Page Language="C#" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>Store Response Tests</title>
    
        <script type="text/javascript">
            var StoreResponseTests = {
                saveSuccess : function(store, object, arg) {
                    console.log("save succeeded", arg);
                },
    
                saveFailed : function(store, object, arg) {
                    console.log("save failed", arg);
                },
    
                simulationType : 'success',
    
                beforeSave: function(store, options) {
                    options.params.SimulationType = StoreResponseTests.simulationType;
                },
    
                doSave: function(store, simulationType) {
                    StoreResponseTests.simulationType = simulationType;
                    store.save();
                }
            };
    
        </script>
    </head>
    <body>
        <form id="HtmlForm" runat="server">
            <ext:ResourceManager ID="ResourceManager1" runat="server" />
           
            <ext:GridPanel ID="GridPanel1" runat="server" Title="Edit stuff and then save" AutoExpandColumn="name" Height="300">
                <Store>
                    <ext:Store ID="Store1" runat="server" ShowWarningOnFailure="false">
                        <Proxy>
                            <ext:HttpProxy Url="GetData.ashx" />
                        </Proxy>
                        <UpdateProxy>
                            <ext:HttpWriteProxy Method="POST" Url="UpdateData.ashx" />
                        </UpdateProxy>
                        <Reader>
                            <ext:JsonReader Root="Data" TotalProperty="TotalRecords">
                                <Fields>
                                    <ext:RecordField Name="id" />
                                    <ext:RecordField Name="name" />
                                </Fields>
                            </ext:JsonReader>
                        </Reader>
                        <WriteBaseParams>
                            <ext:Parameter Name="SimulationType" Value="success" />
                        </WriteBaseParams>
                        <Listeners>
                            <BeforeSave Fn="StoreResponseTests.beforeSave" />
                            <Save Fn="StoreResponseTests.saveSuccess" />
                            <SaveException Fn="StoreResponseTests.saveFailed" />
                        </Listeners>
                    </ext:Store>
                </Store>
                <ColumnModel ID="ColumnModel1" runat="server">
                    <Columns>
                        <ext:Column ColumnID="id" Header="Id" DataIndex="id" Width="20" Sortable="true" />
                        <ext:Column ColumnID="name" Header="Name" DataIndex="name">
                            <Editor>
                                <ext:TextField ID="NameEditorField" runat="server" />
                            </Editor>
                        </ext:Column>
                    </Columns>
                </ColumnModel>
                <TopBar>
                    <ext:Toolbar ID="Toolbar1" runat="server">
                        <Items>
                            <ext:Button ID="Button1" Text="Simulate Normal Save" runat="server">
                                <Listeners>
                                    <Click Handler="StoreResponseTests.doSave(#{Store1}, 'success');" />
                                </Listeners>
                            </ext:Button>
                            <ext:Button ID="Button2" Text="Simulate Save With Errors" runat="server">
                                <Listeners>
                                    <Click Handler="StoreResponseTests.doSave(#{Store1}, 'fail');" />
                                </Listeners>
                            </ext:Button>
                        </Items>
                    </ext:Toolbar>
                </TopBar>
                <LoadMask ShowMask="true" />
                <SaveMask ShowMask="true" />
            </ext:GridPanel>
        
        </form>
    </body>
    </html>
    2) Dummy GetData.ashx.cs

    using System.Collections.Generic;
    using System.Web;
    
    namespace Ext.Net.Tests.Grid.HttpWriteProxy
    {
        public class GetData : IHttpHandler
        {
            public void ProcessRequest(HttpContext context)
            {
                context.Response.ContentType = "application/json";
    
                var data = new List<Dictionary<string, object>>
                {
                    new Dictionary<string, object> { { "id", "1"}, { "name", "Name 1" } },
                    new Dictionary<string, object> { { "id", "2"}, { "name", "Name 2" } },
                    new Dictionary<string, object> { { "id", "3"}, { "name", "Name 3" } },
                    new Dictionary<string, object> { { "id", "4"}, { "name", "Name 4" } }
                };
    
                var plants = new Paging<Dictionary<string, object>>(data, 4);
    
                context.Response.Write(JSON.Serialize(plants));
            }
    
            public bool IsReusable
            {
                get { return false; }
            }
        }
    }
    3) Dummy UpdateData.ashx.cs

    using System.Web;
    
    namespace Ext.Net.Tests.Grid.HttpWriteProxy
    {
        public class UpdateData : IHttpHandler
        {
            public void ProcessRequest(HttpContext context)
            {
                context.Response.ContentType = "application/json";
    
                var storeResponse = new Response(true);
                var simulationType = context.Request["SimulationType"];
    
                storeResponse.Message = JSON.Serialize(simulationType);
                storeResponse.Success = simulationType == "success";
    
                storeResponse.Write();
            }
    
            public bool IsReusable
            {
                get { return false; }
            }
        }
    }
    To reproduce:

    1. Edit anything in the name column
    2. Press the first save button to simulate no errors - with Firebug open - note the response has success in it (as expected) and the console logs out the call to the save handler (as expected)
    3. Edit anything in the name column again
    4. This time press the second save button to simulate errors - with Firebug open - note the response has success false in it (as expected) and the console logs out the call to the save handler (not expected)


    Question 3: (least important) Would it be possible to have a method on your Store object to setUpdateParams bit like setBaseParams?
    I found that trying to dynamically update the Write params felt a bit more trickier than it needed to be: you can see in the button click handlers I had to call a method that would "cache" the simulation type in a custom save handler, then I'd also need to provide a beforeSave event handler to take that cached data and update the options accordingly.

    I tried to look for some kind of method to do this and couldn't see one, though I could certainly have missed it. If not, a store.setUpdateParams() or something like that could be quite handy. (Should I put this question 3 into a separate forum post?)
    Last edited by Daniil; Jun 15, 2011 at 7:37 PM. Reason: [CLOSED]
  2. #2
    Quote Originally Posted by anup View Post
    I am finding is this:

    1. I use an HttpWriteProxy and in the ashx implementation if there is some error condition, I set the storeResponse's Success property to false
    2. When looking at the http requests and responses I see the correct Success (true or false) being set
    3. But by the time the Store listeners are invoked, it seems only the Save listener is invoked and it is only passed the message, not the success property
    4. The SaveException listener is not invoked

    This means it is hard to determine whether I am handling a save or failure condition (unless I structure the string message into a serialized JSON object with more information, but that feels like bit of a workaround).

    Question 1: Is this a bug and should SaveException listener be invoked instead?
    Hi anup,

    This bug has been recently fixed. Please clarify how long ago did you update?
  3. #3
  4. #4
    Quote Originally Posted by anup View Post
    Question 2: If Save must always be invoked regardless of success or failure, can the arg also have the success property, because all I see is just the message property?
    No, Save must not be invoked when 'success' is false.

    Quote Originally Posted by anup View Post
    Question 3: (least important) Would it be possible to have a method on your Store object to setUpdateParams bit like setBaseParams?
    I found that trying to dynamically update the Write params felt a bit more trickier than it needed to be: you can see in the button click handlers I had to call a method that would "cache" the simulation type in a custom save handler, then I'd also need to provide a beforeSave event handler to take that cached data and update the options accordingly.

    I tried to look for some kind of method to do this and couldn't see one, though I could certainly have missed it. If not, a store.setUpdateParams() or something like that could be quite handy. (Should I put this question 3 into a separate forum post?)
    Well, I don't think that it's more trickier that it needed to be.

    I will try to explain my position.

    Imagine that Store has the following WriteBaseParams:
    <WriteBaseParams>
        <ext:Parameter Name="test" Value="test" Mode="Value" />
    </WriteBaseParams>
    It is rendered to client side as (you can see it in Page Sources):
    beforeSaveParams : function (store, options) {
        if (!options.params) {
            options.params = {};
        };
        Ext.apply(options.params, { "test": "test" });
        Ext.applyIf(options.params, {});
    }
    And this 'beforeSaveParams' is used within Ext.data.Store script this way:
    if (this.beforeSaveParams) {
        if (this.restful) {
            this.on("beforewrite", function (store, action, rs, options) { 
                return this.beforeSaveParams(store, options); 
            }, this);
        } else {
            this.on("beforesave", this.beforeSaveParams);
        }
    }
    So, the key point is using "beforesave" event (not "beforewrite" one, because you don't use restful).

    It would look a bit cumbersome if we would try to implement changing update parameters on the fly.

    I'd suggest you to don't use WriteBaseParams in according to your additional requirements, but use your own "beforesave" listener + store's custom config item like "updateParams".
  5. #5
    Daniil,

    Thanks for your quick response (always!)

    I just checked and the last time I updated from SVN just happened to be a few days before the fix! I will update and hopefully that will be a non issue for me.

    Regarding your point about using beforeSave instead of beforeWrite, if you see in my sample I am already doing that:

                beforeSave: function(store, options) {
                    options.params.SimulationType = StoreResponseTests.simulationType;
                },
    The thing was that this simulation type I had to "cache" in the StoreResponseTests, so in the button's click handler, before calling the store's save() method, I had to cache the simulation type, then know that the beforeSave handler will be invoked so that I can just call the store's save() method.

    But, if I understood right, your idea of not using WriteBaseParameters at all is interesting and just to use my own beforeSave listener instead. So WriteBaseParameters is useful if it is almost passthrough parameters (set once when store is created) and doesn't need to be edited. If, however, I may change the values of these update parameters based on user actions (like those two button clicks) then using my own beforeSave is probably easier? That sounds good; thanks for that.

    I will update from SVN and confirm my issue is solved shortly.
  6. #6
    Quote Originally Posted by anup View Post
    Regarding your point about using beforeSave instead of beforeWrite, if you see in my sample I am already doing that:

                beforeSave: function(store, options) {
                    options.params.SimulationType = StoreResponseTests.simulationType;
                },
    The thing was that this simulation type I had to "cache" in the StoreResponseTests, so in the button's click handler, before calling the store's save() method, I had to cache the simulation type, then know that the beforeSave handler will be invoked so that I can just call the store's save() method
    It seems I was not clear, apologize.

    I didn't mean that you need to use "beforewrite", just tried to explain how it is implemented in Ext.Net to show a way how you can implement it yourself in according to your requirements.

    Quote Originally Posted by anup View Post
    But, if I understood right, your idea of not using WriteBaseParameters at all is interesting and just to use my own beforeSave listener instead. So WriteBaseParameters is useful if it is almost passthrough parameters (set once when store is created) and doesn't need to be edited. If, however, I may change the values of these update parameters based on user actions (like those two button clicks) then using my own beforeSave is probably easier? That sounds good; thanks for that.
    Well, you understood the idea correctly.

    By the way. don't forget that you can use a function as parameter's value.
    var getTestParameter = function () {
        return 'testParameter';
    }
    
    <WriteBaseParams>
        <ext:Parameter Name="test" Value="getTestParameter " Mode="Raw" />
    </WriteBaseParams>
    It also can be a possible solution.
  7. #7
    Quote Originally Posted by Daniil View Post
    By the way. don't forget that you can use a function as parameter's value.
    var getTestParameter = function () {
        return 'testParameter';
    }
    
    <WriteBaseParams>
        <ext:Parameter Name="test" Value="getTestParameter " Mode="Raw" />
    </WriteBaseParams>
    It also can be a possible solution.
    That's a great suggestion. Many thanks for that.

    By the way, just got latest from SVN and it works, so you can close this thread now. Sorry for wasting your time :)
  8. #8
    No problem:)

    Thanks for the excellent explanation and code samples as always!

Similar Threads

  1. Replies: 12
    Last Post: Apr 04, 2012, 11:55 AM
  2. [CLOSED] Checkcolumn listener
    By albayrak in forum 1.x Legacy Premium Help
    Replies: 2
    Last Post: Feb 18, 2011, 2:43 PM
  3. [CLOSED] [1.0] Listener and DirectEvents
    By alliedwallet.com in forum 1.x Legacy Premium Help
    Replies: 1
    Last Post: Jun 30, 2010, 7:10 PM
  4. [CLOSED] [1.0] MVC and Listener AutoDataBind
    By Timothy in forum 1.x Legacy Premium Help
    Replies: 3
    Last Post: Mar 05, 2010, 5:19 PM
  5. [CLOSED] Listener Confirmation
    By alexp in forum 1.x Legacy Premium Help
    Replies: 2
    Last Post: Jul 07, 2009, 4:56 AM

Posting Permissions