|
LATEST POSTS
Thursday, June 29, 2006
Another post saying that I haven't done anything useful recently. Have brought in a paycheque, yes, but all the interesting stuff happens extracurricularly in my life (unless you really want to know the inner workings of Open Text Livelink) and there hasn't been much extracurricular time. Plenty of excuses: just moved back home after six-months away, recent trip to London, my daughter has been doing her impression of Keith Moon's death the last two days while I'm being a single dad for the week.
So I've been trying to get organized again which at the moment means my workspace is wallpapered with sticky notes. Really need to try out some life hacks. In the meantime, thought I'd outline, for posterity, some of the major and semi-major projects that I've been neglecting:
- Full version of the app I demoed at Calgary Code Camp. Gonna be sweet. I have about 2500 songs to search through.
- Update the app I whipped up one weekend six years ago for my brothers' land surveying company. Interestingly enough, it uses some of the AJAX techniques I mentioned in my demo. Not so interestingly, they've become somewhat demanding for an update with new features.
- Build a small accounting system to manage a friend's financial statements. The current accounting systems all suffer from one basic flaw, they handle at most two currencies. My friend has accounts in six and Excel just isn't cutting it anymore.
- Build a user group in the Bahamas. And sweet Jesus, the Igloo Coder's series on just that could NOT have come at a better time. I have to make some minor adjustments to allow for a caribbean mentality but that series is pure gold baby.
- Finish the articles on search applications I start so many moons ago. I'm so bad at following through.
- Move my blog to something other than .Text (probably dasBlog 'cause I want to be Scott Hanselman).
These are the major unpaid items. Doesn't include my current full-time job. Or the side contract I have. Or my new consulting business I need to start developing. Or catching up on JP Boodhoo's blog. (Seriously, I know how many kids he has. Where does the guy find the time.) Or other little things like why the IIS service keeps throwing errors and restarting on my server since I installed .NET 2.0.
Anyway, I know I'm not alone in having a list of neglected side projects. So fess up. What's your list?
Wednesday, June 28, 2006
I love demonstrating the UpdatePanel to people on a paged, sortable GridView. Especially people who have tried to do the same thing manually. It's a very cool demo.
But I want to say a little something on the problem Atlas doesn't solve for this demo. Let's say you have a page that loads a grid on startup. Then you move ahead a couple of pages and sort the grid on a different field. It's pretty easy to configure the GridView for this so that it shows the proper results. That is, it will sort the results first, then render the third page.
Now let's say the user refreshes the page. If it's a normal ASP.NET page, you'll get the normal warning saying you are about to repost the data you submitted. It sucks that users have had to get used to this little quirk since in reality, what have you really submitted? But c'est la web and until some kid gets fed up enough to actually build Web 2.0 in his basement, we'll have to live with this.
Take the same example with an UpdatePanel. Page ahead two and resort. Again the results are displayed correctly and we have the benefit of not having to regenerate the entire page. But press refresh in this case and the page returns to its original state. I.E. Unsorted on page one. (You can see the effects of this in the sample app I did for Calgary Code Camp; it doesn't page but it sorts.)
In some respects, this is better in that you don't see the annoying popup (or the Page Expired message if you click Cancel). For the most part, though, it's more confusing for general users who would certainly wonder what happened to their results.
The reason this is a problem is familiar to anyone who has done AJAX work. On the one hand, you don't reload the entire page but on the other hand, but as a consequence, the browser hasn't registered that any page change has taken place while you've been merrily clicking away. When you reload a page in the browser, it will load the page as it was first rendered.
Incidentally, this also applies if you do any sort of DHTML work, too. For example, if you add rows to a table on the client, this will get lost when you refresh.
And at its core, Atlas is still AJAX. It doesn't solve any of the architectural problems that go along with AJAX, just some of the developmental ones (while introducing a couple of new ones). If you were to build this same page five years ago using AJAX, you would have the same problem. It's the nature of HTTP.
Note that you can get around this refresh problem with AJAX/Atlas through inventive/bastardized use of cookies. You store data about the grid's current state in a cookie and in the onload event for the body, do some mucking around with DHTML. I imagine this is pretty tough with AJAX because you'll need to know very intimately what the HTML looks like generated by ASP.NET.
But here's another question: what if the user wants to bookmark that exact page number and sort? A cookie won't work in this case. Or rather it might work if the user only ever wants to bookmark one page. Try to bookmark page four as well as page three and you're out of luck. With both AJAX and ASP.NET.
If you do need to support bookmarkable pages (or similarly, the ability to e-mail a page to a friend), the ultimate solution is pretty low tech: use an HTTP GET. Remember HTTP GETs? From the old ASP days? It seems so long, long ago in a galaxy far, far away.
Stick with QueryString parameters to figure out what page you're on and how you're sorting and in what direction. Google does it. Yahoo does it. MSN does it. All search engines do it. They have to. C'est la web. I know, I know. It's not as fun building apps like this in ASP.NET because you pretty much circumvent the entire event architecture they so desperately want you to use. And Request.QueryString seems so twentieth century.
But such is the sacrifice we make for our beloved users.
Wednesday, June 28, 2006
Blogged this entry from the airport recently so I could pretend I was too cool to waste precious minutes waiting for my flight to leave. My facade is dampened somewhat by the fact that I was in the Miami airport whose main culinary highlight is the fact that the Skittles in the kiosks have the new Limited Edition strawberry ice cream flavour. Donde es los wireless, MIA? Perhaps the bird's nest in the loft of the A terminal where I awaited my flight interfered with the signal somehow. Poor little fella. All he did was stare out the window wondering, "I know I got myself into this mess. How the &$*% am I going to get out of it?" The parallels to my own career are a little frightening.
A small update on my extender which is not forgotten but not progressing thanks to my recent trip to London (and if you're ever going to London, I'd suggest doing so during the World Cup). Got a couple of good suggestions from Ted Glaza on the Atlas forums. First was that my internal control should derive from Sys.UI.Control which is good to know.
The second is that a similar control is already in the works in the new toolkit. It's an accordion control and it's still in their prototype project. I didn't quite get it to work completely but enough to see how it was going to do it. I just glanced at the implementation briefly and I think I'll continue on the path I'm on. I think it does what I want but what I didn't like was that each panel had to be implemented within the accordion control itself. What I'd rather do is specify my panels in the HTML, then elsewhere, define an extender that references. This is how the other controls work and this is how I expect an extender to work. That's why it's called an extender.
Which is not to slight the accordion control, which is more robust in that it allows more than one panel to be defined instead of hardwiring it to two like I'm doing.
Anyway, haven't done any actual coding (hillbilly or otherwise) since I last pontificated. Stay tuned.
Wednesday, June 14, 2006
Phew! This Atlas Extender thing isn't as easy as I thought it would be. Have spent a good part of the day trying to build my dream toggle-able panels and am no further than I was yesterday. Gained a bit of knowledge though and yes, it is in fact a dangerous thing.
In my original attempt, I essentially duplicated the existing CollapsiblePanel extender so I'd have something to start from. My next task was to remove properties I didn't plan to implement: ExpandControlID, ExpandDirection, AutoCollapse and AutoExpand. ExpandControlID because I'm forcing the control to be a toggle. AutoCollapse and AutoExpand because they don't really make sense in this context. ExpandDirection because, frankly, I have enough to worry about.
Removing these properties from both the Properties.cs file and the Behavior.js file was pretty painless. I even got a little cocky and changed the animation parameters to make it a little smoother.
Then came the part when I tried to implement the second panel.
Every extender automatically implements a TargetControlID property because, well, we're extending an existing control so we should know which one it is. I decided to use this property to represent the panel that is initially visible and I added a second property, CollapsePanelID, to represent the sister panel that is collapsed on startup.
The actual javascript for the CollapsiblePanel that does the main work is fairly simple. When initialised, it creates an animation object that is tied to the target control:
_animation = new AtlasControlToolkit.NumberAnimination(); _animation.set_property("TargetHeight"); _animation.set_duration(.25); _animation.set_fps(10); _animation.set_target(this); _animation.ended.add(Function.createDelegate(this, this._onAnimateComplete));
In the click event for the control that collapses the panel, it sets the start value for the animation to the panel's current size and sets the end value to its collapsed size (which is usually zero but doesn't have to be). Then it plays the animation.
_animation.stop(); _animation.set_startValue(this._getTargetSize()); _animation.set_endValue(this._getCollapsedSize()); _animation.play();
The click event for the control that expands the panel is almost identical but sets the end value to the panel's expanded size.
My problem comes in the _animation.set_target line. What I'd really like to do is set up an animation for the second panel and execute it at the same time as the first one. This, to me, would be the easiest implementation because the Atlas framework does all the work and it's consistent with the rest of the implementation.
But it looks like set_target takes an object and I don't know what kind of object to pass in. I don't want to create a whole separate instance of my object to pass in because then I'll have to manage potential stack issues (since ToggledPanel objects will keep creating more ToggledPanel objects). But I'm also not familiar enough with the object model to know what else I could pass in. I tried Sys.UI.Panel but there is no such object as far as I know. And the documentation for animation is non-existent except for the actual code itself.
As I type this, an idea is forming, though. I'm wondering if I can create a second version of the ToggledPanel object. One that will still expand and collapse but that is designed to be controlled by another object. Stay tuned...
P.S. One thing I'm having trouble getting used to. When you modify the .js file for your extender, you need to recompile in order for the changes to be reflected. Been developin' these har web pages a long time and I ain't ne'er hadun ta compile ma javascript befur. And iffun I hafta compil'em, I reckon there should be some sorta benufit to it, see. Like compile time checkin'.
Saturday, June 10, 2006
I'm working on a production version of the app I demo'd at code camp and the need arose for me to create my own Atlas extender. Well, I could get away without using it but I want to see what these extenders are all about. So the next few posts will describe my journey through the process.
The extender I want is a ToggledPanel similar to the existing CollapsiblePanel. In the CollapsiblePanel, you specify the panel you want to collapse, the control to expand it and the control to collapse (the latter two can be the same which will create a toggle but not in the same way I want). In my slightly different ToggledPanel, you'll specify two panels and one control to toggle the two. I.E. You toggle between which panel is expanded at any given time.
One of the main drivers for this is an issue I came across with the CollapsiblePanel. In my example, I mimicked what I wanted by hooking up two existing CollapsiblePanels to the same LinkButton. This sort of gave me what I want although the animation is a little wonky.
The panel has to have its Visible property set to true in order for it to be rendered in the HTML. After that, the CollapsiblePanel uses client-side script to show or hide the panel depending on the value of the Collapsed property. If Visible is set to false, then the HTML for the panel isn't even rendered so there is nothing for the CollapsiblePanel to expand or collapse.
What it didn't give me is a way, server-side, to tell which panel is visible. Or rather, it doesn't remember if a given panel is visible or not as a result of it being expanded or collapsed. That is, the panel's Visible property is always set to whatever value it is set to initially. And for it to work with a CollapsiblePanel extender, the Visible property pretty much has to be set to true (see sidebar).
So I went about creating my own extender and as all good coders do, I started with someone else's code: namely, the existing CollapsiblePanel. I created a separate Atlas Control project to house all my at-present-non-existent extenders and mimicked the AtlasControlToolkit structure by creating a folder called ToggledPanel in it. (Incidentally, it should technically be called a ToggleablePanel but I'm not a fan of making up words.) Then I added an Atlas Control to this folder which created a bunch of files.
I'd already gone through the walkthrough so this didn't throw me too much. After that, I proceeded to copy and paste like it was going out of style. The Properties class, the Extender, the javascript file and the Designer were all blatantly lifted from the CollapsiblePanel class and I paused just long enough to change the namespace and delete the copyright notice. (I'm kidding about the copyright; call off the hounds.)
Without too much trouble, I was able to get the thing to compile and I added the necessary line to my aspx page:
<%@ Register Assembly="AtlasControlToolkit" Namespace="AtlasControlToolkit" TagPrefix="atlasToolkit" %>
so that I could use my extender in the page. Since it was an exact copy of the CollapsiblePanel, I just replaced the Atlas tags with my own and left everything else within them the same:
<suvius:ToggledPanelExtender ID="test" runat="server"> <suvius:ToggledPanelProperties TargetControlID="PanelSimpleSearch" ExpandControlID="LinkButtonPanelSwitch" CollapseControlID="LinkButtonPanelSwitch" Collapsed="False" TextLabelID="Label1" CollapsedText="Simple Search..." ExpandedText="Extended Search..." SuppressPostBack="true" /> <suvius:ToggledPanelProperties TargetControlID="PanelAdvancedSearch" ExpandControlID="LinkButtonPanelSwitch" CollapseControlID="LinkButtonPanelSwitch" Collapsed="True" TextLabelID="Label1" CollapsedText="Extended Search..." ExpandedText="Simple Search..." SuppressPostBack="true" /> < FONT>suvius:ToggledPanelExtender>
Refresh the page and voila!
As it turns out, my .js file was not set as an EmbeddedResource (and it really should have been done for me). As it also turns out, that didn't help me much as I got the same error. I double-checked the ClientScriptResourceAttribute and the Sys.TypeDescriptor.addType call in the javascript and they looked fine.
My next step was to look at the source code for the page and find where my javascript file was being loaded. It looks like the ScriptManager handles this part because I found the following in my source:
When I loaded these up in my browser, they referenced the various javascript files used by other extenders on the page. Except the second one which registered as a 404 error. Which means my script wasn't being brought into the page explaining why the behaviour wasn't registered.
The eventual solution: in a fit of Canadian-ness, I had renamed my ToggledPanelBehavior.js file to ToggledPanelBehaviour.js. I thought I saw where this file was registered and changed its name there, too but when I changed the name back, the error went away and the page began to work as its parent, the CollapsiblePanel, did.
And therein lies the issue with client-side technologies. You can make your error messages as helpful as possible but in the end, Atlas really didn't know why the type wasn't registered. There is no help at design time (in the form of Intellisense), no help at compile time and little help at runtime.
Which is not to imply that you shouldn't use Atlas. I think you should. When it makes sense (like any other tool). Like when you have a web page with so many postbacks, it looks like your site is having a seizure every time you click the page. There's some great stuff to be had with the Atlas framework. The browser compatibility layer alone is reason enough to use it. But expect an environment closer to ASP than to ASP.NET, despite the tremendous effort the Atlas team has gone through in order to hide that aspect of client-side development.
The full extender described here will be available when I'm done building it. And it might have been by now if I wasn't wasting my time talking to you people.
Wednesday, June 07, 2006
An interesting lesson learned during my Atlas presentation at the Calgary Code Camp that had to do with postbacks within an UpdatePanel. My application contains, at startup, a textbox, three buttons and two empty GridViews. As you search for music, both GridViews get populated. Click the image at the right for a sample.
The bottom GridView contains a LinkButton column in the far left that allows you to remove that row from the GridView. Since it's a LinkButton, this causes a postback. To be more specific, this causes the javascript function __doPostBack to be called. The __doPostBack function is output into the page at runtime by .NET although what actually performs this function is something I've never looked into. As far as I know, its job is to submit the form to itself so that the code-behind can be called. It is called by any control that causes a postback.
What I discovered is that if there are no controls that cause a postback, the __doPostBack function is not generated. So in the normal ASP.NET version of my application, the function is not generated at startup because the only controls are a textbox and three buttons. (The buttons are rendered as Submit buttons so do not need a mechanism to cause a postback.) But when the user adds a song to the selected music list, this causes a LinkButton to be generated in the second GridView and .NET will then generate the __doPostBack function. So far, so good. No problem in the normal ASP.NET world.
Switching to Atlas: We wrap the GridViews in UpdatePanel controls so that when the user clicks Search or Add to Selected, we don't actually refresh the entire page, just the GridViews. Herein lies the problem. When the page first loads, there are no controls that require the __doPostBack function so it isn't generated. When the user clicks Add to Selected, Atlas takes over and retrieves the HTML required for the UpdatePanel but nothing else. Well, that's not entirely true. It does retrieve a little more info but the important part is that it retrieves the HTML for the second GridView which now includes LinkButtons. These LinkButtons have references to a __doPostBack function that hasn't been generated because (I guess) that only happens when the entire page is reloaded. Essentially, Atlas is assuming that the __doPostBack function has been generated already at the page level.
The workaround I used is to include the following code in the Page_Load event:
Page.ClientScript.GetPostBackEventReference( new System.Web.UI.PostBackOptions( this.ButtonPlay ) );
This generates a PostBack reference for the play button. The button doesn't technically need one but I had to pick some control to pass in. The side effect I was looking for is that the __doPostBack javascript function is going to be generated every time the page loads now, including the first time. And in the Atlas version, that's the only time the page is loaded.
So if you are clicking on controls and getting an “object not set to a value” javascript error in UpdatePanel controls, see if the __doPostBack function actually exists in your page source. If not, you'll need to add it.
Sunday, June 04, 2006
Quick post today because I'm stuck in the land that time (and the Internet) forgot. I swear this is where they filmed Deliverance. Just wanted to point to a great account of last weekend's code camp.
And I make no apologies about my musical selections.
Friday, June 02, 2006
After speaking with Jean-Paul Boodhoo earlier this week, I'm convinced more than ever that I need to tread carefully into TDD waters. In my previous post on the subject, I think I came down harder than I intended, attacking the example more than the method.
It's not the paradigm-shift itself that gives me pause. After all, we're software developers. Paradigm shifts are what we do. Writing tests first? Sure, why not. If that's what the methodology says, that's what I'll do. I can see the benefit of it pretty easily. And frankly, there are already cases where I write code for methods that don't exist yet, although they are never unit tests.
What I want to be careful about is how I write these tests. This is where I can see frustration setting in. Again, the one test = one method is a simple enough rule to follow. But how granular do you make that method? How much should it do? How do you account for other potential clients for that method that may require changing the signature? (These are rhetorical questions; no need to flood my inbox with e-mails saying “it depends“.)
Fortunately, I believe this is a learned skill. Just like OO is a learned skill. The difference is that I spent years in university learning OO in a structured environment. This I have to learn on my own. And it's not like picking up a new framework that you can use Intellisense to explore and try things out. Some real live thought has to be put into what you're doing.
The other complication for me is that TDD encourages interface-based programming. This isn't as bad because while I haven't done a lot of it personally, it's something I can wrap my head around and can muddle my way through fairly easily.
The ultimate point of this post is basically the same as the original one: I'm interested enough that I want to figure out how to do it properly. My overall opinion has changed ever-so-slightly, though, in that it's probably something I would use somewhat regularly if I knew how to do it. Maybe not as the be-all and end-all of every project but like any good methodology, it's good to understand it so you can recognize when it's a good fit.
I still think there's something to this Conscientious Coding idea, though.
And JP, if you're reading, next lunch will be down at my neck of the woods. Best to come outside hurricane season.
Monday, May 29, 2006
The Atlas UpdatePanel is amazing. I've been enamored pretty much since I saw my first demo on it. This isn't like the demos you've seen on ASP.NET 1.0 dealing with DataConnections and DataAdapters. You know the ones: they'd drop a connection, an adapter and a dataset on the page, wire them all up and say, "Look how easy!". The problem there is that no one outside of a student facing a serious deadline would build their applications like that.
But the UpdatePanel not only makes a great demo, it is genuinely a better way to add AJAX to your applications. There is such little effort required to get a whole lot of benefit.
The idea behind the UpdatePanel is that you wrap it around existing pieces of your page, set it to trigger on certain events and....well, that's it. Atlas takes care of the details: loading the XMLHTTP object, setting up the asynchronous call, ensuring the readystate is set to 4, checking the status of the request, etc, etc. No changes to the code-behind required. No decorating your web services. No special Atlas versions of the ASP.NET controls.
In a previous post on the subject, I claimed it would be useful mostly for converting existing applications to use AJAX. I'm backtracking now. It is still great for that purpose. But I have no problem recommending it for new applications either. Two main reasons for using AJAX is to make your application more responsive (or, more importantly, making it APPEAR more responsive) and to reduce the network traffic that comes with regenerating an entire page which each postback. The UpdatePanel accomplishes both of these objectives. Yes, you have more control and can get greater bandwidth savings doing it yourself. But balance that with the cost of a developer's time to develop it (and for someone to maintain it).
Incidentally, I've also learned that it is the Atlas ScriptManager that ensures only the delta comes back from the server. Apparently, it overrides the Page's Render method. Why can't I think of these things?
Monday, May 29, 2006
I believe XSL is more underused than it should be. Few people at the recent code camp were familiar with it and it is my experience that people are aware of it and what it does but may not know how it does it.
XSL is used to convert an XML document into another format. The other format can be another XML document, HTML, text or any other format (and as far as I know, it has to be a text-based format). There are many good tutorials on XSL (my favorite resource is here; check out the Questions and Answers section) so I'm going to focus on a couple of the more obscure things.
xsl:apply-templates vs. xsl:for-each While XSL is underused, the xsl:for-each construct is, in my opinion, overused. People use it because they understand it. It has a direct correlation to modern programming languages and programmers know intuitively how it works. I almost never use it.
The next time you want to put in an xsl:for-each, consider using a separate template instead. That's what templates are for. Say, for example, you are building a table to display a list of Songs. Your XML would have a Songs root element with one or more Song elements. And perhaps each Song element has one or more Genre elements.
This, to me, warrants three templates: one for the Songs element, one for each Song element, and one for each Genre. The template for the Songs element looks like this (in pseudocode): <xsl:template match="Songs"> <table width="100%"> <thead> <tr> <th>Title</th> <th>Artist</th> <th>Genres</th> </tr> </thead> <tbody> <xsl:apply-templates select="Song" /> </tobdy> </table> </xsl:template> Notice where it uses <xsl:apply-templates>. This is where someone else may use <xsl:for-each>. As in, "for each song, output the following HTML". xsl:for-each lends itself to a small number of monolithic templates, rather than a larger number of small (and re-usable) templates. In my version, it says "apply the songs template for each Song element". It's almost the same thing but with a separate Song template, we can re-use it in another template or even another XML document. And if you want to change how the Song is displayed, it's easier to zero in on its template without wading through the Songs template.
A similar argument goes for displaying Genres within the Song template: <xsl:template match="Song"> <tr> <td><xsl:value-of select="SongTitle" /></td> <td><xsl:value-of select="Artist" /></td> <td><xsl:apply-templates select="Genre" /></td> </tr> </xsl:template> In this case, we output a single table row for each song. The list of genres will appear in a single table cell in some form (e.g. an unordered list or a comma-delimited list). Again, we keep the focus on the song, and not the extraneous stuff. An argument could be made here that Genre is insignificant enough that it could be included using xsl:for-each. I'll listen to that argument but still prefer to use templates for the most part.
The root template In many XSL documents, I'll see a template like this: <xsl:template match="/">. To me, this obviously matches the root element of the XML and is the template that triggers the whole thing.
Maybe it's my compulsive nature but I prefer not to use "/" in a template. In reality, it says, "apply this template to every element no matter what it is". The only thing that keeps it from rendering every element in your DOM is careful (and in many case, lucky) use of <xsl:apply-templates> elsewhere in your document. When you use <xsl:apply-templates>, it will find the template that most closely matches your select attribute. In my above example, <xsl:apply-templates select="Song" /> will look for a template that specifically matches Song. If one isn't found, it will use the one that matches "/" (provided no other less general templates exist).
This seems dangerous to me even if it usually doesn't turn out that way in practice. But if you know your root node is named "Songs", why not include a template that specifically matches "Songs"? It's more consistent with the rest of your templates and avoids any accidental use of the default template. Which is how it should be used: as a default template. I.E. If no other templates match, use this as the default template. Useful for formatting individual text the way you like it without having to create a template for every node.
Default namespaces XSL doesn't like 'em. Well, that's not totally true. XSL can deal with them just fine. But you may not be able to deal with how XSL uses them.
Say our Songs.xml file uses a default namespace: xmlns="http://www.suvius.com". This means that every node in the XML will be qualified with that namespace (if it isn't already explicitly qualified with another one). So when I say <xsl:apply-templates select="Song" />, XSL won't find any nodes. In this case, it's looking for unqualified Song nodes, which don't exist. The end result is that your transformation will show a whole lot of white space when you're expecting HTML.
To do this properly, you need to add that default namespace to your XSL...but not as a default namespace itself. Using the same default namespace mentioned in the previous paragraphy, I would add the following to the <xsl:stylesheet> element: xmlns:suvius="http://www.suvius.com". That is, the default namespace in the XML document is a named namespace in the XSL document.
Now, when I want to apply a template or reference a node, it'll look like this: <xsl:apply-templates select="suvius:Song" />.
Consider namespaces to be a substitution. I.E. XSL will replace the namespace with its contents. If a default namespace is used, all unqualified nodes in the XML will have that namespace prepended to it. So my Song node in the XML document is processed as if it looks like this: http://www.suvius.com:Song.
By adding a named namespace to the XSL, I would reference this node in the XSL document using suvius:Song, which the parser would convert to http://www.suvius.com:Song, thus matching the node in the original XML document.
A lot of work, to be sure. And the best way around this is: don't use default namespaces. Easier said than done when using web services. When you specify a namespace on a web service, it will be converted to a default namespace when the object being returned is serialized to XML. Depending on your needs, you can specify a blank namespace in your web service, which means no default namespace will be used. This might raise other concerns, though, especially if it is a public service.
This post was auto-generated by my fingers.
Disclaimer
The opinions expressed herein are my own personal opinions and do not represent
my employer's view in any way.
Copyright © 2010 Kyle Baley. All rights reserved.
|
|
|
CATEGORIES
|
|
LATEST POSTS
POPULAR POSTS
|
|
ARCHIVE
| August, 2010 (1) |
| July, 2010 (3) |
| June, 2010 (3) |
| May, 2010 (1) |
| April, 2010 (5) |
| March, 2010 (4) |
| February, 2010 (8) |
| January, 2010 (2) |
| December, 2009 (3) |
| November, 2009 (2) |
| September, 2009 (5) |
| August, 2009 (4) |
| July, 2009 (2) |
| June, 2009 (5) |
| May, 2009 (6) |
| April, 2009 (5) |
| March, 2009 (6) |
| February, 2009 (2) |
| January, 2009 (6) |
| December, 2008 (5) |
| November, 2008 (2) |
| October, 2008 (5) |
| September, 2008 (9) |
| August, 2008 (5) |
| July, 2008 (7) |
| June, 2008 (6) |
| May, 2008 (11) |
| April, 2008 (13) |
| March, 2008 (13) |
| February, 2008 (12) |
| January, 2008 (19) |
| December, 2007 (16) |
| November, 2007 (8) |
| October, 2007 (23) |
| September, 2007 (15) |
| August, 2007 (8) |
| July, 2007 (6) |
| June, 2007 (11) |
| May, 2007 (19) |
| April, 2007 (14) |
| March, 2007 (3) |
| February, 2007 (4) |
| January, 2007 (7) |
| December, 2006 (5) |
| November, 2006 (9) |
| October, 2006 (11) |
| September, 2006 (14) |
| August, 2006 (11) |
| July, 2006 (15) |
| June, 2006 (8) |
| May, 2006 (10) |
| April, 2006 (12) |
| March, 2006 (3) |
| February, 2006 (7) |
|
|
|