hello.
are you making the call to the server side? ie, have you used fiddler to see what's happening?
THanks for the suggetion. I know that my server side break point is never hit so assumed the request was never made to the server (WebMethod).
I shall look at Fiddler and report back.
Some problems using Fiddler with the Dev Server from VS2005 - it was unable to capture the traffic at all.
So I used FF & FireBug (which works with Localhost and various ports without issue) and found that the DataService was actually returning a code 500 "You need [ScriptService]" error. I should have guessed that this was also a requirement of a DataService as well as a WebService. My bad, so I added that as a directive to the DataService and gues what? Yep, it worked.
So it was a very good call - you were dead right to check the HTTP traffic.
So, any ideas how I can configure Fiddler to do the right thing, and do you know of any documentation amywhere for the DataService?
Thanks again
K
hello.
well, unfortuantely, fiddler stopped working correctly with IE 7 (i think that the problem is that the IE team decided to shortcut local requests and never goes throught he proxy - event if you configure it in the IE options). the workaround is to create a web app in iis and use the machine name to make capture the traffic. another option is to use firefox and confgirue it so that it goes through fiddle.
regarding the data service documentation, i don't know if there's much out there. do you need any special info?
Actually a simple workaround is to add a period at the end of the localhost. Like this:
http://localhost.:5953/AjaxSite/Test.aspx
hello.
cool...i didn't know this one! thanks for sharing.
@.Rama, nice, thanks I shall try that idea, sounds like the simpler solution :)
Edit: Ok tried it but get a
504 Gateway Time-OutDescription:Unable to connect to origin Web server.
As for info on the DataService, well its just such a new one on me and I'd like to know exactly what it is, and what it is designed to do. It *looks* very much like a WebService, except that it appears to be designed to have only 4 methods or so (Select, update, Insert, Delete) like some sortof Data Access Layer or Web based Table Adapter.
Because of the lack of docs, I decided to see what could be done using a standard Web Service in regard to data access. My idea was simply to see if a DataTable could be return FROM a web service (I KNOW that works), bound to some user controls, then the data updated on the client, and the entire DataTable sent back (or ideally, just the changes) TO the web service and used somehow to update the backend data store, again returning a DataTable to confirm the updates.
So my first problem has become sending a client side DataTable TO the Web Service. I can pass a string OK but as soon as I change th emethod to expect a DataTable then I get the following error (by way of an "alert" box that I didn't create myself!!:
"The server method 'setVendors" failed with the following error: System.NotSupportedException-- Specified method is not supported."
Now I have a strong feeling that a WebService (and indeed a DataService) by way of the "[ScriptService]" declaration is somehow able convert a .NET DataTable structure into JSON to send back to the client. However, perhaps the mechanism is not able to accept a JSON string from the client and convert that into a .NET DataTable. Firebug HTTP shows this 500 error from the server:
{"Message":"Specified method is not supported.","StackTrace":" at Microsoft.Web.Preview.Script.Serialization.Converters.DataTableConverter.Deserialize(IDictionary`2 dictionary, Type type, JavaScriptSerializer serializer)\r\n at System.Web.Script.Serialization.ObjectConverter.ConvertDictionaryToObject(IDictionary`2 dictionary, Type type, JavaScriptSerializer serializer)\r\n at System.Web.Script.Serialization.ObjectConverter.ConvertObjectToTypeInternal(Object o, Type type, JavaScriptSerializer serializer)\r\n at System.Web.Script.Serialization.ObjectConverter.ConvertObjectToType(Object o, Type type, JavaScriptSerializer serializer)\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth)\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeDictionary(Int32 depth)\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth)\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.BasicDeserialize(String input, Int32 depthLimit, JavaScriptSerializer serializer)\r\n at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer serializer, String input, Type type, Int32 depthLimit)\r\n at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize[T](String input)\r\n at System.Web.Script.Services.RestHandler.GetRawParamsFromPostRequest(HttpContext context, JavaScriptSerializer serializer)\r\n at System.Web.Script.Services.RestHandler.GetRawParams(WebServiceMethodData methodData, HttpContext context)\r\n at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)","ExceptionType":"System.NotSupportedException"}
So, I *think* that is telling me that the "Microsoft.Web.Preview.Script.Serialization.Converters.DataTableConverter.Deserialize" method failed!
So, I guess my question is, how do I pass rich data objects from Server to Client and back again? More specifically, how do I do it with DataTables or DataSets and what is it that the DataService is supposed to overcome (maybe you CAN send a datatable to a DataService)?
Any info at all would be useful.
So it appears that the info contained in this page is just plain wrong, or very out of date, such as the client DataTable does not support a "get_length()" method, the DataTable now just conists of a rows array, a columns array and a __type (System.Data.DataTable)attribute.:
http://aspadvice.com/blogs/garbin/archive/2006/03/05/15591.aspx
2. How can I pass a DataTable instance to the server?
When you are done with a client DataTable instance, you can pass it to any Page/Service method that accepts aSystem.Data.DataTable as an argument; the Atlas framework will take care of the serialization/conversion between types.
Note: actually it's not possible to pass a DataTable back to the server without building a custom type converter.
So it says one thing (Atlas will take care of it), and then somethuing else entirely. So the question now becomes "How do you build a custom type converter", and also why do you have to? (as this is not a custom typeI have created, this type is supplied by Microsoft).
hello.
you only need to change web.config to get serializaxtion
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization>
<converters>
<add name="DataSetConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataSetConverter, Microsoft.Web.Preview, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add name="DataRowConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataRowConverter, Microsoft.Web.Preview, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add name="DataTableConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataTableConverter, Microsoft.Web.Preview, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</converters>
</jsonSerialization>
...
Interesting. My Web.Config has (almost) exactly that, save for the MaxJsonLength property (which I altered from the default):
<system.web.extensions><scripting><webServices><!-- Uncomment this line to customize maxJsonLength and add a custom converter --><jsonSerialization maxJsonLength="50000"><converters><add name="DataSetConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataSetConverter, Microsoft.Web.Preview, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/><add name="DataRowConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataRowConverter, Microsoft.Web.Preview, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/><add name="DataTableConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataTableConverter, Microsoft.Web.Preview, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/></converters></jsonSerialization>
But My app fails: This is what is sent back from the server (Firebug)
{"Message":"Specified method is not supported.","StackTrace":" at Microsoft.Web.Preview.Script.Serialization
.Converters.DataTableConverter.Deserialize(IDictionary`2 dictionary, Type type, JavaScriptSerializer
serializer)\r\n at System.Web.Script.Serialization.ObjectConverter.ConvertDictionaryToObject(IDictionary
`2 dictionary, Type type, JavaScriptSerializer serializer)\r\n at System.Web.Script.Serialization.ObjectConverter
.ConvertObjectToTypeInternal(Object o, Type type, JavaScriptSerializer serializer)\r\n at System.Web
.Script.Serialization.ObjectConverter.ConvertObjectToType(Object o, Type type, JavaScriptSerializer serializer
)\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth
)\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeDictionary(Int32 depth
)\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth
)\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.BasicDeserialize(String input
, Int32 depthLimit, JavaScriptSerializer serializer)\r\n at System.Web.Script.Serialization.JavaScriptSerializer
.Deserialize(JavaScriptSerializer serializer, String input, Type type, Int32 depthLimit)\r\n at System
.Web.Script.Serialization.JavaScriptSerializer.Deserialize[T](String input)\r\n at System.Web.Script
.Services.RestHandler.GetRawParamsFromPostRequest(HttpContext context, JavaScriptSerializer serializer
)\r\n at System.Web.Script.Services.RestHandler.GetRawParams(WebServiceMethodData methodData, HttpContext
context)\r\n at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context,
WebServiceMethodData methodData)","ExceptionType":"System.NotSupportedException"}
Can you advise further? If it helps, this is my WebMethod:
[WebMethod]public DataTable setVendors(DataTable dTable) {// Do something with the Datatable DataTable localTable = dTable;return localTable; }
And this is my client JS:
function main(){ var _vendorsDataTable =null; var getVendors = function() { var onVendors = function(result) { _vendorsDataTable = result; $find("output").set_data(_vendorsDataTable.rows); } WebService.getVendors(onVendors);return false; } var setVendors = function() {// Do not play if we have no data yetif (!_vendorsDataTable) { alert("Please GET the data first");return false; } var onVendors = function(result) {// We never get here debugger; } WebService.setVendors(_vendorsDataTable, onVendors);return false; }// Wire up document.getElementById("btnGetVendors").onclick = getVendors; document.getElementById("btnSetVendors").onclick = setVendors;}
hello.
can you build a small demo and send it to me?
Sorry!
You cannot pass a datatable to a web method. This is not supported. The serialization of datatable works only one way: From C# to JSON. You cannot deserialize JSON to a DataTable or DataSet. These methods are not supported.
Right, thanks for the replies guys, its all very helpful & interesting indeed (lucky I'm not so busy at work at the moment!!).
So, I've discovered something quite major I didn't know. A Web Method such as this:
[WebMethod]public DataTable getData(){ DataTable dt =new DataTable(); ...return dt;}
when picked up on the client, has just 3 properties "rows", "cols" and "__type".
However, I came across this way to convert that simple structure into a feature rich client side DataTable:
var
realDataTable = Sys.Preview.Data.DataTable.parseFromJson(result);realDataTable is now very rich indeed.
So, I have tried a number of things to send the DataTable (or its changes) back to the server. For example, a WebMethod like this:
[WebMethod]public bool setVendors(DataTable dTable)
With client code like this:
WebService.setVendors(_vendorsDataTable, onVendors);
will ultimately cause a Stack overflow in the client browser! The code *does not fail* as such, but the client object seems too rich to process?
I HAVE had a little success tho: a web method like this:
[WebMethod]public bool setVendors(System.Collections.Generic.Dictionary<string,object> dTable) { Object[] insertedRows = (Object[])dTable["inserted"];for (int i = 0; i < insertedRows.Length; i++) { System.Collections.Generic.Dictionary<string,object> cols = insertedRows[i]as System.Collections.Generic.Dictionary<string,object>; String name = cols["Name"].ToString(); String accountnumber = cols["AccountNumber"].ToString(); }return true; }
with client code like this (note: JUST the dataTable changes)
WebService.setVendors(_vendorsDataTable.getChanges(), onVendors);
DOES successfully extract data on the server and could potentially update the back-end and send something back to the client. It's hardly ideal tho and I can't help but think that there must be an easier way.
the question now is, what would you like me to send you an example of, the Stack Overflow example (Sending DataTable to WebMethod expecting DataTable)?? Or something else?
hello.
Rama is correct. you can't pass datatables from client to the server side. why don't you use custom objects and retunr a collection or arrayof items from the client to the server? in my opinion, you shouldn't be using datatables or datasets for communicating between the client and the server
No comments:
Post a Comment