Hello

I have a problem to setup custom state provider, can you please take a look what is wrong in code below?

problem: State is not restored

Code is bit longer as I tried to limit number of files.
So here is sample:

httpStateProviderHandler.ashx:
(just a pretty simple state handler, in my project is database driven state provider)

<%@ WebHandler Language="C#" Class="HttpStateProviderHandler" %>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.SessionState;
using Ext.Net;

public class HttpStateProviderHandler : IHttpHandler,IReadOnlySessionState {
	public class StateData
	{
		public int UserId { get; set; }
		public string Key { get; set; }
		public string Value { get; set; }
	}

	private static Dictionary<string, StateData> _dctState = new Dictionary<string, StateData>();

	public void ProcessRequest (HttpContext context)
	{

		if (context.Request.HttpMethod == "POST")
		{
			StateData data = new StateData()
			{
				UserId = int.Parse(context.Request["UserId"].ToString()),
				Key = context.Request["Key"],
				Value = context.Request["Value"]
			};

			if (_dctState.ContainsKey(data.Key))
			{
				_dctState[data.Key] = data;
			}
			else
			{
				_dctState.Add(data.Key,data);
			}

			
		}
		else if (context.Request.HttpMethod == "GET")
		{
			var userId = int.Parse(context.Request["userId"]);

			
			var ret = JSON.Serialize(_dctState.Select(item => new {item.Key,item.Value.Value}).ToDictionary(item => item.Key));
			context.Response.Write(ret);
		}
		else if (context.Request.HttpMethod == "DELETE")
		{
			var userId = int.Parse(context.Request["userId"]);
			var key = context.Request["key"];

			_dctState.Remove(key);

			var result = new Dictionary<string, string>();
			result.Add("success", "true");
			JSON.Serialize(result);
		}
	}

	public bool IsReusable {
		get {
			return false;
		}
	}

}

Page itself:

<%@ Page Language="C#" %>

<script runat="server">
   
	[DirectMethod(RethrowException = true)]
	public static object LoadData(string action, Dictionary<string, object> extraParams)
    {
            DateTime now = DateTime.Now;
		StoreRequestParameters prms = new StoreRequestParameters(extraParams);

            var ret = new object[]
            {
                new object[] {1, "3m Co", 71.72, 0.02, 0.03, now },
                new object[] {2, "Alcoa Inc", 29.01, 0.42, 1.47, now },
                new object[] {3, "Altria Group Inc", 83.81, 0.28, 0.34, now },
                new object[] {4, "American Express Company", 52.55, 0.01, 0.02, now },
                new object[] {5, "American International Group, Inc.", 64.13, 0.31, 0.49, now },
                new object[] {6, "AT&T Inc.", 31.61, -0.48, -1.54, now },
                new object[] {7, "Boeing Co.", 75.43, 0.53, 0.71, now },
                new object[] {8, "Caterpillar Inc.", 67.27, 0.92, 1.39, now },
                new object[] {9, "Citigroup, Inc.", 49.37, 0.02, 0.04, now },
                new object[] {10, "E.I. du Pont de Nemours and Company", 40.48, 0.51, 1.28, now },
                new object[] {11, "Exxon Mobil Corp", 68.1, -0.43, -0.64, now },
                new object[] {12, "General Electric Company", 34.14, -0.08, -0.23, now },
                new object[] {13, "General Motors Corporation", 30.27, 1.09, 3.74, now },
                new object[] {14, "Hewlett-Packard Co.", 36.53, -0.03, -0.08, now },
                new object[] {15, "Honeywell Intl Inc", 38.77, 0.05, 0.13, now },
                new object[] {16, "Intel Corporation", 19.88, 0.31, 1.58, now },
                new object[] {17, "International Business Machines", 81.41, 0.44, 0.54, now },
                new object[] {18, "Johnson & Johnson", 64.72, 0.06, 0.09, now },
                new object[] {19, "JP Morgan & Chase & Co", 45.73, 0.07, 0.15, now },
                new object[] {20, "McDonald\"s Corporation", 36.76, 0.86, 2.40, now },
                new object[] {21, "Merck & Co., Inc.", 40.96, 0.41, 1.01, now },
                new object[] {22, "Microsoft Corporation", 25.84, 0.14, 0.54, now },
                new object[] {23, "Pfizer Inc", 27.96, 0.4, 1.45, now },
                new object[] {24, "The Coca-Cola Company", 45.07, 0.26, 0.58, now },
                new object[] {25, "The Home Depot, Inc.", 34.64, 0.35, 1.02, now },
                new object[] {26, "The Procter & Gamble Company", 61.91, 0.01, 0.02, now },
                new object[] {27, "United Technologies Corporation", 63.26, 0.55, 0.88, now },
                new object[] {28, "Verizon Communications", 35.57, 0.39, 1.11, now },
                new object[] {29, "Wal-Mart Stores, Inc.", 45.45, 0.73, 1.63, now }
            };

		return new { data = ret.Skip(prms.Start).Take(prms.Limit), total = 29 };
    }
</script>

<!DOCTYPE html>

<html>
<head runat="server">
    <title>Simple Array Grid With Paging and Remote Reloading - Ext.NET Examples</title>

    

 
</head>
<body>
    <form runat="server">
        <ext:ResourceManager runat="server" Namespace="" />

        <ext:GridPanel
            ID="GridPanel1"
            runat="server"
            Stateful="True"
            StateID="GridPanel1"
            Title="Array Grid"
            Width="800">
            <Store>
                <ext:Store  ID="Store1" runat="server"  AutoLoad="True" PageSize="10" RemoteSort="true" RemotePaging="True">
                    <Model>
                        <ext:Model runat="server" IDProperty="id">
                            <Fields>
	                            <ext:ModelField Name="id" />
                                <ext:ModelField Name="company" />
                                <ext:ModelField Name="price" Type="Float" />
                                <ext:ModelField Name="change" Type="Float" />
                                <ext:ModelField Name="pctChange" Type="Float" />
                                <ext:ModelField Name="lastChange" Type="Date" />
                            </Fields>
                        </ext:Model>
                    </Model>
	                <Proxy>
		                <ext:PageProxy DirectFn="Ext.net.DirectMethods.LoadData">
		                </ext:PageProxy>
	                </Proxy>
                </ext:Store>
            </Store>
            <ColumnModel runat="server">
                <Columns>
                    <ext:Column runat="server" Text="Company" DataIndex="company" Flex="1" />
                    <ext:Column runat="server" Text="Price" Width="75" DataIndex="price">
                    </ext:Column>
                    <ext:Column runat="server" Text="Change" Width="75" DataIndex="change">
                    </ext:Column>
                    <ext:Column runat="server" Text="Change" Width="75" DataIndex="pctChange">
                    </ext:Column>
                    <ext:DateColumn runat="server" Text="Last Updated" Width="125" DataIndex="lastChange" Format="H:mm:ss" />
                </Columns>
            </ColumnModel>
         
            <View>
                <ext:GridView runat="server" StripeRows="true" />
            </View>
            <BottomBar>
                 <ext:PagingToolbar runat="server">
                   
                </ext:PagingToolbar>
            </BottomBar>
        </ext:GridPanel>
    </form>


<script>

	Ext.define('App.util.HttpStateProvider', {
		extend: 'Ext.state.Provider',
		requires: ['Ext.state.Provider', 'Ext.Ajax'],
		alias: 'util.HttpProvider',
		processStateSave: false,
		config: {
			userId: null,
			url: null,
			stateRestoredCallback: null
		},

		constructor: function (config) {
			if (!config.userId) {
				throw 'App.util.HttpStateProvider: Missing userId';
			}
			if (!config.url) {
				throw 'App.util.HttpStateProvider: Missing url';
			}

			this.initConfig(config);
			var me = this;

			//me.restoreState();
			me.callParent(arguments);
		},
		get: function () {
			return this.callParent(arguments);
		},
		set: function (name, value) {

			//if (this.processStateSave == false)
			//return;

			var me = this;

			if (typeof value == 'undefined' || value === null) {
				me.clear(name);
				return;
			}

			me.saveStateForKey(name, value);
			me.callParent(arguments);
		},

		initStateFromData: function (result) {
			for (var property in result) {
				if (result.hasOwnProperty(property)) {
					this.state[property] = this.decodeValue(result[property]);
				}
			}
		},
		// private
		restoreState: function () {

			var me = this,
				callback = me.getStateRestoredCallback();

			//debugger
			//if (localStorage["alaState"] != null) {
			//	this.initStateFromData(localStorage["alaState"]);
			//	console.info('init state from storage');
			//	return;
			//}
			Ext.Ajax.request({
				url: me.getUrl(),
				method: 'GET',
				params: {
					userId: me.getUserId()
				},
				success: function (response, options) {
					var result = JSON.parse(response.responseText.trim());
					//localStorage["alaState"] = result;
					this.initStateFromData(result);

					if (callback) {
						callback();
					}
				},
				failure: function () {
					console.log('App.util.HttpStateProvider: restoreState failed', arguments);
					if (callback) { callback(); }
				}
			});
		},

		// private
		clear: function (name) {

			var me = this;

			me.clearStateForKey(name);
			me.callParent(arguments);
		},

		// private
		saveStateForKey: function (key, value) {

			var me = this;
			Ext.Ajax.request({
				url: me.getUrl(),
				method: 'POST',
				params: {
					userId: me.getUserId(),
					key: key,
					value: me.encodeValue(value)
				},
				failure: function () {
					console.log('App.util.HttpStateProvider: saveStateForKey failed', arguments);
				}
			});
		},

		// private
		clearStateForKey: function (key) {

			var me = this;

			Ext.Ajax.request({
				url: me.getUrl(),
				method: 'DELETE',
				params: {
					userId: me.getUserId(),
					key: key
				},
				failure: function () {
					console.log('App.util.HttpStateProvider: clearStateForKey failed', arguments);
				}
			});
		}
	});

	var alaStateProvider = new App.util.HttpStateProvider({
		userId: 1,
		url: 'HttpStateProviderHandler.ashx',
		stateRestoredCallback: function () {

		}
	});
	Ext.state.Manager.setProvider(alaStateProvider);
</script>
</body>
</html>