Recently I needed to parse a complex query string from a Url, and configure a map based on those settings. This parsing occurs in the server side Page_Load event, and the general process of parsing the Querystring NameValueCollection is straight forward.
The complex part comes from the fact that my application is heavily Ajax based - other than the initial markup, everything else is fetched from the server via HTTP GET's to ASP.NET JSON web services. Still sounds good. But - here's the trick. The query string is passed to the page, not the web service. I guess I could have tried to write all the parsing in javascript and handled it on the client side but there are some pretty complex options that involve database lookups, and I like me some MBUnit Row Tests, so server side was a better option.
The first though is - ok - I'll parse the query string, and stuff the resultant "map settings" object into session, and have the client fetch that from the web service. Nice, but no cigar, since the web service can not access the HttpContext that the page is running in. So much for simple solutions.
Next contender was ASP.NET "page methods" (aka web methods). These are static methods They should work, as they can access the HttpContext of the page. After parsing and stuffing the "map settings" into the session state, the client side code could call back to the "Page Method", which would grab the map settings from the session and send back to the client. Sweet. After some head scratching and reviewing of sample code that does this, and a bunch of Googling, I found that Page Methods do not work on User Controls (ascx). Since I was creating a module for use in DotNetNuke, there was no way around using a user control. Time to get ugly...
Yep - the old inject-it-as-it-renders trick. Ugly, but it works. So, in page load, I parse query string, create and populate the map settings class and then use the System.Web.Script.Serialization.JavascriptSerializer to convert my object to JSON. Some people have reported issues with this serializer, but it's been working smoothly for us so far. If you have problems, you can roll your own or use an open source option like JRock or JSON.Net. From there, I just emit it into the page as part of a script block:
//Serialize out to the browser as JSON
JavaScriptSerializer jss = new JavaScriptSerializer();
//Use this Replace operation to escape out the dates
//see: http://forums.asp.net/t/1070058.aspx post by dotnetsamurai from 5/4/2007
string json = jss.Serialize(initialMapSettings).Replace(@"\", @"\\");
string script = "<script>mapSettingsJson = '" + json + "';</script>";
//Now send the json out
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "mapsettings", script);
As alluded to the in the comments, I ran into all kinds of trouble with dates. Read the referenced forum article for the "why" behind the string replacement bit.
Then in the client side Page_Load (I'm using the MSAjax stuff, so we get a Page_Load that automatically linked into the client page lifecycle), we use the client side deserializer to convert our JSON string back into a handy dandy javascript object.
//Deserialize back into an objectmapSettings = Sys.Serialization.JavaScriptSerializer.deserialize(mapSettingsJson);
From here we just proceed with the rest of the page startup, and we get the correct map.
If you have .NET 3.5 installed, then JavaScriptSerializer is marked as deprecated, and suggests you use the DataContractJsonSerializer. And if you are using Complex types (like I am) you will need to add the [DataContract] and [DataMember] attributes to the classes being serialized. I tried both ways and for me they both worked.
"Nice, but no cigar, since the web service can not access the HttpContext that the page is running in"
I'm Dave and this is my blog. I'm usually writing about .NET Software Development, ArcGIS, or Agile Practices, but other stuff does creep in from time to time. I hope you find something of use, and feel free to contact me if you have any questions. You can also check out my profile on LinkedIn
dojo.DTSAgile.com is our technology preview / demo site. As I and my team cook up cool things we post them here.
ArcDeveloper.net is a site that hosts a set of open source projects related to ArcGIS. This includes Tile Cache for .NET (TC4N) and Feature Server for .NET (FS4N). Come over and check it out!
Assembla is a free service that provides Subversion source control, wikis and work Tracking. The ArcDeveloper project is run from here. It rocks. Check them out today.
Agilistas is a LinkedIn group focused on discussing and promoting Agile practices. Everyone is welcome to join in the conversation as we evolve the process of creating software to make it more enjoyable for all involved.