Evaluating Atlas
Sorry, I meant that I am evaluating Microsoft(R) ASP.Net(TM) Ajax(Patent Pending) Extentions :-).
I mentioned before that I am not really feeling overly excited about that whole Ajax thing. Because of a client constraints, I am unable to use MonoRail (but I use just about everything else from the Castle stack :-) ), so I thought that I would give Atlas a try. This is still very early in the project, but I like to understand how things works so I know why they broke. And for some reason, just about anything breaks when I start playing with it.
At any rate, I took the cascading style list demo for a spin, and managed to hit issues with its error reporting almost immediately. I didn't specify the full path to the service, which meant that it had very helpfully showed me a [method error 500], which I was not pleased to see. Maybe there is a way to get more infomration from it, but I couldn't find it.
Once I got over this hurdle, it was much easier. This is a fairly core scenario, so I wasn't surprised that it was easy, just wire the extenders to the correct controls and write the service methods. Here is my code:
public class NewPolicyRequestService : BaseScriptService
{
private NewPolicyRequestController controller;
public NewPolicyRequestController Controller
{
get { return controller; }
set { controller = value; }
}
[WebMethod]
public CascadingDropDownNameValue[] GetOptionsForPolicy(
string knownCategoryValues,
string category)
{
StringDictionary kv = CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);
string maybePolicyId = kv["Policies"];
ICollection<PolicyOptions> options = Controller.GetOptionsForPolicy(maybePolicyId);
List<CascadingDropDownNameValue> values = new List<CascadingDropDownNameValue>(options.Count);
foreach (PolicyOptions option in options)
{
values.Add(new CascadingDropDownNameValue(option.Name, option.Id.ToString()));
}
return values.ToArray();
}
[WebMethod]
public CascadingDropDownNameValue[] GetPolicies(
string knownCategoryValues,
string category)
{
ICollection<Policy> policies = Controller.GetPolicies();
List<CascadingDropDownNameValue> values = new List<CascadingDropDownNameValue>(policies.Count);
foreach (Policy policy in policies)
{
values.Add(new CascadingDropDownNameValue(policy.Name, policy.Id.ToString()));
}
return values.ToArray();
}
}
Couple of things to note here, BaseScriptService has all the appropriate attributes [ScriptService], [WebService], [Etc] :-). It is also responsible for injecting the correct controller, which is the one who is responsbile for the actual work. The service is here merely to unpack the data from the request and then translate the returned results to something that Atlas can understand.
So far, very easy. I don't like the fact that I have to duplicate code here, though. There may be a better way, but the only thing that I can think about is to add a template method that accept a couple of delegates, and I don't see that as adding to the maintainability of the system.
The more important concern that I have, though, is what happen when I need to extend this example. Imagine a scenario where I have this:
When a policy is selected, I need to update the child drop down, but I also need to update the policy description. I know how I can do it in MonoRail (easy), and I know how I can do it in using HTML/Javascript (not tough). I have no idea how hard it would be to make it work with ASP.Net/Atlas.*
I figure that I'll probably need to drop the drop down extenders completely (and handle all the updates to the drop downs myself {I have way more than 2, by the way} ), in order to be able to recieve more information than what the extender gives me. More annoying then that, I would have to use the horrible <%= Policies.ClientID %> all over the place, and get the lovely "Control Collection Could Not Be Modified" exceptions when I try to do more advance stuff.**
* I find it sad that I need to seperate ASP.Net from HTML
** Experiance hurts, I suggest avoiding it.
Comments
You could give Anthem.Net a try.
What about CascadingDropDown from the AjaxToolkit?
http://ajax.asp.net/ajaxtoolkit/CascadingDropDown/CascadingDropDown.aspx
Should make your life a lot easier.
@Oren,
That cascading is what I use, and what I worry about is having to do more than a single thing per callback, it looks like in this case I would have to do it all by hand.
Here are some tutorials for you
http://weblogs.asp.net/scottgu/archive/2007/02/12/free-asp-net-ajax-1-0-how-do-i-videos-updated-for-final-release.aspx
Can I be sarcastic? :) Hearing you talk about webforms is like me trying to make mono act like a webform. You are trying to make a webform be like mono.
They aren't the same. They require different approach :)
Um, what... ?
I actually am asking how I can do something that I can do fairly easily with MonoRail using WebForms.
I am not trying to do it the MonoRail way, because WebForms make it a lot harder, I am asking what the best way to do it in WebForms.
In other words, put your money where you mouth is, show me how the above can be dealt using WebForms.
Cool, Ayende talking about ASP.NET Ajax ;-)
I agree with you that sometimes - well, most of times - ASP.NET machinery makes things overly complicated and totally inflexible... maybe that's why they shipped the source code for both the framework and the Control Toolkit...
Let the extender handle the parent-child issue and add to your policies DropDownList an attribute to handle it's client-side "onchange" event that will put the current selected value in the label:
ddlPolicies.Attributes["onchange"] = "javascript:showCurrentPolicy(this)";
Another solution is to wrap your 2 DDLs with UpdatePanel and set the Trigger element to support the parent-child relation. In addition, Put the label in an UpdatePanel and set a Trigger on him for the onchange of the policy DDL. Now, set the AutoPostBack of your policies DDL to true and for each change of your policy, change the the child.
I guess that I can come up with 2-3 more solutions, but I would go on the first one. Good luck.
Comment preview