Tuesday 31 August 2010

More ASP.NET AJAX UpdatePanel excitement

I gave up. The UpdatePanel wasn't really designed to do what I want it to do. I thought initially that I could get nested UpdatePanels to just refresh localised content; i.e. if I created one inside a div then by setting it to conditional update I could just make it refresh the controls inside the div. This is not the case - event nested panels refresh everything.

The Conditional update flag is OK but you can't make a control that's outside the panel refresh it. And having a timer that refreshes content is a no - no for the reason discussed above; every ten seconds everything gets refreshed which means the text box you are typing into loses focus and the modal popup with a list of options pops down again.

I have a series of scripts that I have embedded into the main .aspx page via .ascx controls. These scripts open a new app hosted on an entirely seperate server in a new IE tab. Once the user has finished with this second app I need a way to refresh the content on the main .aspx page so what I ended up doing was navigating through the control structure of the main page from the .ascx control and finding the labels etc. that I want to update. I rigged up a modal popup with a giant refresh button and when the user jumps out to the second app this modal popup gets popped and it's the first thing the user sees when they close the second app. The refresh button then brings my main page up to date.

Navigating the control structure was a bit of a nightmare; set Me.Parent.Page and then iterate through five layers of controls to find the one I want (and that's just to pick out one label, there's more work to do). But at least I found a viable solution.

Thursday 26 August 2010

Fun (!) with the ASP.NET AJAX UpdatePanel

Still unlucky enough to be developing with the ASP.NET AJAX UpdatePanel? Me too. You have my condolences. After spending some time getting to grips with it you may be at the stage where you realise that you could use it to make real time updates to areas of your web app by using a Timer to run an automatic refresh.

The problem I found initially was that doing this tended to take over the entire web app and refresh everything. I also ran into problems with Triggers - i.e. I couldn't get certain parts of the app to update because I needed to fire them through an Asycnhronous trigger and it wasn't working.

So this afternoon I set out to try and solve the problem. I am working on an app that will 'branch out' to another application on another server in certain circumstances. The user completes some actions in this second app and will then close the IE window / tab and return to my app. When this happens I want some things to change - mainly text and contents of grid views. Should be achievable with the UpdatePanel. Right?

I have set up a web form that inherits from a MasterPage. First thing on the page is the ToolKitScriptManager control, followed by an UpdatePanel called 'upMain' with UpdateMode = Conditional. I have a div with some content, and then underneath this an Accordion control with five different panes.

First thing is a note on the timer. Initially I had a set of labels in the header div (inside on UP) and a grid in the fifth pane (inside a seperate UP) that I wanted to refresh. I tried setting a Timer on each of these and using them as ASync triggers on each UpdatePanel but that didn't work - only the first Trigger would fire for some reason. I tried creating one Timer inside the Main UP and using this as the Trigger for each sub - UP but that didn't work either - it just took over the entire app and started stopping data input half way through, for example (no good for the user experience).

The answer, it turns out, is to create the Timer inside the first sub - UP and wire up the ASync triggers for both sub-UP's to this Timer. That works OK and refreshes both sets of content. To get the second sub-UP to recognise the Timer you have to give it the Unique ID that ASP.NET assigns which is something like ctl00$main$... To get this set a breakpoint on your Timer event handler and check the value of sender when it breaks - you can interrogate the object and find the UniqueID value here.

More on this later.

Monday 23 August 2010

Do I really need to ditch ASP.NET?

Something I have been thinking about for a while is trying to move away from ASP.NET as the front end for the web applications that I work on, instead using a combination of Javascript / jQuery for the client and WCF to handle the transactional and data part of things. You'll see some recent posts that look at this relationship in a bit more detail.

But do I really need to ditch ASP.NET? It's taken me 6 years to become pretty proficient with the framework (and I still learn new stuff when I'm busy with projects). Starting from scratch with jQuery would probably be another six years - and for what? I see websites like Ticketmaster which must handle a crazy amount of traffic and I don't see much there that I couldn't handle in ASP.NET. Could I replicate the way that Facebook works? Probably not. But does that really matter? I guess there comes a time in the career of many professional footballers when they realise that they're never going to play for Liverpool. Same applies to me.

Thursday 19 August 2010

WCF and jQuery (Part 3 The Return)

So WCF is pretty incredible. It's not new by any means and there are plenty of cleverer people out there who use it every day and get results and that's cool. But if you've never used it before and you get something working like I have this week you can suddenly see all kinds of potential.

Firstly it's good for me that Microsoft enable this to happen pretty easily. I bought a Ruby on Rails book a couple of months ago and started going through the examples and was blown away by how you can get a simple RESTful application running in a few minutes. Well, now I can do that with the Microsoft platform too which means I can still code in VB.NET (great) and still use Visual Studio which I think is the best development environment on the market. Tried Aptana. Tried Eclipse. Tried Notepad. No competition.

Second it makes life easier for me as a developer because I can publish a service with access to all the data and let someone else decide how they want to consume the data. When writing SOAP web services you have to make a concious decision to return XML or an Object or a String or something else. If I wanted to return JSON I would have to get the data out of the database and transform it into JSON. It's not difficult but it takes time. With this WCF DataService the developer can say "I want to get the data in XML or JSON" just by flicking a switch in the code. I don't need to get involved (from what I read though JSON is what everyone wants and why not? Heck of a lot easier than parsing an XML document).

No more database objects to write and maintain. Before customers were saying "we want to see this subset data in this order", and then they would ask to see it in a different order and with something else appended. Again, not impossible but if you're working on a relatively small but important application a Business Objects license is out of the question because they're too expensive. So you have to do the reporting yourself. This RESTful stuff makes those leviathan reporting tools obsolete much like QlikView does (see my previous posts for some info on that amazing tool).

I guess that security is a concern, much more than it was before. If I stuck the service that I created in the demo onto the internet then anyone can come along and CREATE, UPDATE and DELETE records using request / response. So understanding security becomes important and I suppose a decision needs making about securing the web server (because I'm guessing you can restrict GET/POST/PUSH/DELETE there) or securing the DataService itself. Something to read up on.

My next goal is to get a meaningful Javascript app communicating with a service and doing some funky stuff, reading data into a grid, creating records, updating records, deleting records. The Javascript stuff is going to be much more difficult because I have never used it before but I do like a challenge.

WCF DataService and jQuery (Part 2 The Revenge)

Continuing from where I left off yesterday...

The WCF DataService is up and running and accessible via IIS on http://localhost. Now I can write a simple web page that uses jQuery to talk to the service and read some data. There are loads of other blog posts showing you how to do this; I based my solution on something that Shawn Wildermuth posted here: http://wildermuth.com/2010/02/23/WCF_Data_Services_and_jQuery.

Unfortunately I can't post the HTML because Blogger won't allow it and I haven't got time to set up my own domain with some blogging software that's more suited to a developer. But you can use the example I linked to above and figure it out. It's worth noting that Microsoft typically complicates things by adding a wrapper around the JSON that you get back so you have to do results.d.FieldName to get to the data.

What gets even crazier is that if I switch the GET to POST and add a data field to the $.ajax function (something like data: '{"CategoryName":"Test Category"}') then I can create a new record in the database without having to write a stored procedure or a SQL statement or anything. Pretty incredible.

Wednesday 18 August 2010

WCF DataService and jQuery

I have spent the last couple of days looking at WCF DataService and integrating it with jQuery. It's something I have been thinking about for a good few months now. We have some good reasons for wanting to do this; jQuery offers much more web development power than ASP.NET, RESTful web services are the way of the future and it's good to keep on top of what the private sector is already doing.

One of the frustrating things I find when undertaking a learning exercise like this one is how many dead ends you have to walk down before you arrive at the answer. I have spent two days Googling about a million different phrases and reading endless blog and forum posts about configuration, design and debugging. Even getting a simple RESTful web service via WCF up and running was a challenge but I finally cracked it and now I have a very simple web page making an asynchronous AJAX call to an IIS hosted WCF Data Service (which sits on top of the Northwind database), obtaining data in JSON and parsing through it. I had never done anything like this before so it has been an interesting (and at times frustrating) two days.

Here's a very quick walkthrough.

Fire up Visual Studio 2008 and create a new WCF Service Application (you might need to get the templates, or you might be lucky enough to have Visual Studio 2010 which has them pre-installed). Call it NorthwindService. I'm using VB.NET. Delete the IService1.vb and Service1.svc files that get created by default. Right click on the project and Add New Item. Select an ADO.NET Entity Data Model and call it NorthwindDataModel. This fires up a wizard so choose 'Generate from database' and create a connection to the Northwind database on your local machine or network. It's a good idea to create a SQL user on Northwind (i.e. northwind/northwind) and use this from the go rather than relying on integrated security - makes life easier when you deploy to IIS. If you choose to do this include the sensitive data in the connection string. Put ticks in all three boxes and hit Finish.

You'll get a nice ER diagram of Northwind which you can close. Add another new item, this time an ADO.NET Data Service. Call this NorthwindDataService. You get a Class file up. Make a few modifications. First, replace [[class name]] with NorthwindEntities. Second add config.UseVerboseErrors=true to the InitializeService sub (helps with debugging). Then uncomment the last two commented lines. Replace the first parameter in each method call with * and make sure they're both set to All rather than AllRead in the second parameter. Do a build and you should be good to go.

Let's test it out. Hit F5 and you should get IE up with a load of XML. You should recognise the tables from the Northwind database. Add /Categories after .svc and you will get just the Categories info - this is REST working in all its genius glory.

Publish to IIS next. Right click, publish. Target should be c:\inetpub\wwwroot\NorthwindService (remember that VS needs to be in Admin mode). Then open up IIS (which you installed, right, when you built your laptop) and create a new application on your default web site. Set the alias to NorthwindService and the path to where you just published to. You should now be able to browse to http://localhost/NorthwindService/NorthwindDataService.svc/. Try adding Categories after the final / in the URL and make sure you get the Categories data back.

How do I make jQuery talk to this service? That's dead easy but I will continue this tomorrow.