PDA

View Full Version : [CLOSED] GridPanel + Store - Amount of data sent to client when binding to a business object



jchau
Sep 05, 2008, 1:21 PM
Let say I have a business object with 20 properties. I create a store with JsonReader and 5 fields mapped to 5 of those 20 properties. Then I hook up a GridPanel with 5 columns to that store. I bind a generic list of those business objects to the store. When the page renders, I see all 20 properties for each object are sent to the client. Is there a way to only send the data specified in the store?

Also, is there a way to have the grid load the data on demand instead of rendering it onto the page? For example, when the page loads, the grid or store calls a webservice to load the data. I am guessing I have to use a different proxy for the store?

Timothy
Sep 05, 2008, 2:25 PM
In regards to your webservice question, check out the Sandbox for an example:

http://sandbox.ext.net/GridPanel/PlantDemo/Plants.aspx



Cheers,
Timothy

Timothy
Sep 05, 2008, 2:27 PM
Example of the Plants.aspx since you probably don't have SVN rights:



    <ext:Store runat="server" ID="Store1" AutoLoad="true" RemoteSort="true">
        <Proxy>
            <ext:HttpProxy runat="server" Method="POST" Url="../Shared/PlantService.asmx/PlantsPaging" />
        </Proxy>
        <Reader>
            <ext:XmlReader Record="Plant" TotalRecords="TotalRecords">
                <Fields>
                    <ext:RecordField Name="Common" Type="String" />
                    <ext:RecordField Name="Botanical" Type="String" />
                    <ext:RecordField Name="Light" />
                    <ext:RecordField Name="Price" Type="Float" />
                    <ext:RecordField Name="Availability" Type="Date" />
                    <ext:RecordField Name="Indoor" Type="Boolean" />
                </Fields>
            </ext:XmlReader>
        </Reader>
        <BaseParams>
            <ext:Parameter Name="start" Value="0" Mode="Raw" />
            <ext:Parameter Name="limit" Value="10" Mode="Raw" />
            <ext:Parameter Name="sort" Value="" />
            <ext:Parameter Name="dir" Value="" />
            <ext:Parameter Name="filter" Value="" />
        </BaseParams>
        <SortInfo Field="Common" Direction="ASC" />
    </ext:Store>


    <ext:Window 
        ID="Window1"
        runat="server" 
        Width="600" 
        Height="325" 
        Collapsible="true" 
        Icon="WeatherCloudy" 
        Title="Common Plants"
        Maximizable="true">
        <Content>
            <ext:FitLayout ID="FitLayout1" runat="server">
                <ext:GridPanel 
                    runat="server" 
                    ID="GridPanel1" 
                    AutoExpandColumn="Common"
                    Border="false"
                    StoreID="Store1">
                    <ColumnModel runat="server">
<Columns>
                        <ext:Column ColumnID="Common" Header="Name" DataIndex="Common" Width="220" Sortable="true" />
                        <ext:Column Header="Light" DataIndex="Light" Width="130" Sortable="true" />
                        <ext:Column Header="Price" DataIndex="Price" Width="75" Sortable="true">
                            <Renderer Format="UsMoney" />
                        </ext:Column>
                        <ext:Column Header="Indoor?" DataIndex="Indoor" Width="75" Sortable="true" Align="Center">
                            <Renderer Handler="return (value) ? 'Yes':'No';" />
                        </ext:Column>
                        <ext:Column Header="Availability" DataIndex="Availability" Width="100" Sortable="true" Align="Center">
                            <Renderer Fn="Ext.util.Format.dateRenderer('Y-m-d')" />                            
                        </ext:Column>
</Columns>
                    </ColumnModel>
                    <LoadMask ShowMask="true" />
                    <Bbar>
                        <ext:PagingToolBar ID="PagingToolBar1" runat="server" 
                            PageSize="10" 
                            StoreID="Store1"
                            DisplayInfo="true"
                            DisplayMsg="Displaying plants {0} - {1} of {2}"
                            EmptyMsg="No plants to display"                
                            />
                    </Bbar>
                </ext:GridPanel>
            </ext:FitLayout>
        </Content>
    </ext:Window> 





Cheers,
Timothy

geoffrey.mcgill
Sep 05, 2008, 4:43 PM
I modified the PlantsDemo .aspx page to include the full source code, see http://sandbox.ext.net/GridPanel/PlantDemo/Plants.aspx

The above sample does not demonstrate how to limit the properties being serialized into Json. We're discussing a couple ideas to handle this automatically based on the items added to the <ext:RecordField>, but nothing has been implemented yet.

If your data is being serialized into Json using the Coolite.Ext.Web.JSON.Serialze() Method, then you can also try adding the [JsonIgnore] attribute to properties you do not want serialized.

The Coolite Toolkit includes a full version of the Newtsonsoft Json.NET (http://www.codeplex.com/Json) library.

I'll post a sample demonstrating a modified PlantsDemo showing how to limit the properties being Serialized into Json.

Hope this helps.

Vladimir
Sep 05, 2008, 4:53 PM
About loading on demand. For reach this you need to set AutoLoad property to false. In this case you should manually triggering data loading:



<ext:Button runat="server" Text="Load">
<Listeners>
<Click Handler="#{GridPanel1}.load();" />
or if need to pass additional parameters
<Click Handler="#{GridPanel1}.load({params:{p1:'value', p2:'value'}});" />
</Listeners>
</ext:Button>

jchau
Sep 05, 2008, 4:53 PM
geoffrey.mcgill (9/5/2008)

The above sample does not demonstrate how to limit the properties being serialized into Json. We're discussing a couple ideas to handle this automatically based on the items added to the <ext:RecordField>, but nothing has been implemented yet.

If your data is being serialized into Json using the Coolite.Ext.Web.JSON.Serialze() Method, then you can also try adding the [JsonIgnore] attribute to properties you do not want serialized.


Thanks! I prefer not modifying my business object with an UI [JsonIgnore] attribute. There will be scenarios where one grid wants to show a property but another will not. It will be best if this can be part of the Ext:Store configuration. Kudos for the quick responses!

geoffrey.mcgill
Sep 06, 2008, 6:30 PM
Hi jchau,

We did some work on limiting the properties that get Json serialized to only those defined as <ext:RecordField> items.

The functionality will now work with objects added to the <ext:Store> .DataSource property or when the .DataSourceID is linked to a control of type IDataSource, such as <asp:SQLDataSource>, <asp:ObjectDataSource, <asp:LinqDataSource>.

You can set the .DataSource property with any IEnumerable object, such as a Generic List<Customer> and the <ext:Store> will filter the data returned to only include the properties with a matching <ext:ReaderField>.

There's one exception to the list of objects we're able to ignore... currently the filtering/ignoring will not work if the .DataSource is a typeof Array, such as object[].

The <ext:Store> will filter the results automatically. The filtering can be "turned off" by setting the <ext:Store> .IgnoreExtraFields property to "false". The default value is "true". The following code sample demonstrates how to disable the filtering/ignoring of superfluous fields.

Example


<ext:Store ID="Store1" runat="server" IgnoreExtraFields="false">

We can add the filtered serialization feature because when using a .DataSource or .DataSourceID properties, the data is returned inline to the page and is already being serialized into Json by the <ext:Store>. We just throw out properties that don't match up with the <ext:ReaderField>'s.

The DataSource and DataSourceID properties can be filtered, but... if using the <HttpProxy> we can not filter the data.

If using the <HttpProxy>, the Store will call (via ajax) to an external uri/url to retrieve the data. The data may be returned as Json, Xml or a simple object Array. The <ext:Store> "reads" the data as per the settings of the <Reader>. To read Json, you need to use the <ext:JsonReader> and define fields that should be parsed from the Json data.

This external Http data call is asynchronous, decoupled from the original Page logic and the <ext:Store> and <ext:GridPanel> have no influence over how the data is structured. They only know where the data should be coming from and hopefully how it should be structured. It's impossible for us to automatically filter what gets serialized and sent back in the response.

In general, the data endpoint (webservice/url/uri) shouldn't know (or care) what's consuming it's response. Because of this decoupling, if you want to somehow filter or limit the data being returned by the Json feed, then you must only return what you need.

Json serialization is probably the way to go. It's extremely flexible, easy to do, a widely accepted format and the data is self describing (similar to xml).

The Coolite.Ext.Web.Serialize() Method is a generalized all purpose serialization utility... actually it's just a convenience wrapper around the Newtonsoft Json.NET Serialize() Method. The .Serialize() Method will take an Object and convert it into a Json string. Very simple, but it serializes all properties, unless decorated with the [JsonIgnore] attribute, as noted earlier.

Of course generic "all-or-nothing" serialization is not the only option.

If you only want certain properties serialized, or have some unique requirements, the Newtonsoft Json.NET library includes several EXTREMELY powerful techniques for custom serialization. The Json.NET library is well documented (http://james.newtonking.com/projects/json/help/) and includes several custom serialization examples including LINQ-to-JSON. I would encourage you to read through the Json.NET documentation and James Newton-King's website (http://james.newtonking.com/pages/json-net.aspx).

We're building a Coolite Toolkit "Examples Explorer" to demonstrate everything within the Toolkit, and I'll make sure we include a couple samples demonstrating custom Json serialization.

Summary...
Automatic Json property filtering is now default functionality when adding data to the <ext:Store> via the .DataSource or .DataSourceID properties. To disable filtering set IgnoreExtraFields="false".
If using <ext:HttpProxy>, the Toolkit can not filter the results, so it's up to the data end point to decide what should be return.
Hope this helps.

jchau
Sep 06, 2008, 6:46 PM
You guys are awesome. Although we never use <asp:datasource>, I am sure this will help others out there that do. We always just bind to our own list of business objects. We will probably use HttpProxy most of the time as we are moving away from ANY types of postbacks or ajax callbacks. We are mainly focused on webservices and pagemethods to improve performance and usability. We are already wrapping our often bloated business objects with simpler 'info' objects, so we just continue down that path.

Thanks for the tips on Newtonsoft's Json Serializer. We have been using the .NET 3.5 Json Serializer and will take a look at replacing it with Newtonsoft's.

geoffrey.mcgill
Sep 06, 2008, 7:02 PM
Hi jchau,

Vladimir promptly reminded me that I forgot some features... I revised my response above to include that we not only support filtering properties within any IDataSource control, but also any IEnumerable object (except Array), including Generics such as <List>.

I haven't used the .NET 3.5 Json Serializer, but there must be a way to do custom Json serialization. Ultimately it really doesn't matter what tool you use to serialize the data into Json. We just chose to include Json.NET within the Toolkit so everyone had a great option to use by default, but when it comes to returning your serialized data, what tool you use is your choice.

Hope this helps.