Showing posts with label various. Show all posts
Showing posts with label various. Show all posts

Wednesday, March 28, 2012

PageMethod Static Ajax WebService and User Controls

I have a page HostPage.aspx, which is a generic hostpage that will dynamically load Web User Controls at runtime, according to the needs of various other users. Those other Web User Controls will be created by the other users, such that they can put anything they like in that Web User Control, and it will be dynamically populated and put in the HostPage.aspx. They will always use HostPage.aspx, they cannot edit it. This is working as-is, and everything is great.

Now, some users want to put AJAX functionality in their User Controls, such that the HostPage.aspx will contain their User Control, the User Control will contain an UpdatePanel, a ScriptManager, etc.

To enable page methods, we have to set the EnablePageMethods="true" on the scriptmanager, and have to declare a static method *somewhere*. The requirements are such that we cannot be declaring these static methods in the HostPage.aspx, because it cannot know what the controls, and therefore static methods, are until runtime. On the other hand, if we declare these static methods in the User Control, it's not defined in the HostPage, and AJAX PageMethod callbacks fail ("Method myMethod is not defined"), because the page doesn't know of it's existence.

1. Has anyone tried to do something similar to this, namely having AJAX controls in a User Control, which is hosted in a page, yet also needs to use the Page Methods, yet cannot declare them in the page (I know, that's pretty specific).

2. Any ideas on how this might be accomplished?

I'm thinking of using Reflection or DynamicMethod (http://msdn2.microsoft.com/en-us/library/system.reflection.emit.dynamicmethod.aspx) to make this happen, such that at runtime, the page will examine its child controls for any static methods with the ScriptService attribute, and then dynamically create a static method on itself with the same name, calling the child, but that is rather involved and I fear the performance risk of this (if this whole idea is even possible). Plus, the generated method wouldn't exist until after the controls exist, and I'm not sure where that falls in relation to the timing of the AJAX extensions (looking for the MethodName). It might be (probable) that the handler is looking for the method even before the controls are initialized, in which case that idea won't fly.

You can't do that... as described here (http://www.singingeels.com/Articles/Using_Page_Methods_in_ASPNET_AJAX.aspx) Page Methods are only on pages :)

But you can get what you want if you make your user control register a "web service" as in this article:http://www.singingeels.com/Articles/Consuming_Web_Services_With_ASPNET_AJAX.aspx

If your users aren't able to add webserivces (I really don't know the situation your building)... then they can register a regular old "AsyncPostBack" and wire it up themselves (sorry, no article on that yet).


Right, I understand completely the concept of PageMethods, that they are on pages, etc. That's why this is a bit of a tricky spot.

I guess what I'm looking for is whether anyone has come up with anything clever to get around this situation (PageMethods from a Usercontrol). The usersare free to create and consume their own webservices, if they like, but if possible, I would like to give them this functionality for this situation.


OK, I believe it's Page.ClientScript.RegisterAsyncPostBack or maybe ScriptManager.RegisterAsycnPostBack ( I can't remember )... either way, it'll post back to the page... and ultimately the user control, and fire an event (on the user control).

That'll work just like the page methods... (a little better actually for what you're doing)

Wednesday, March 21, 2012

parseLocale ignores negative currency format

I have some JScript that is utilized by a custom TextBox control that does various validation and format functions on the client side. In particular, when the control receives focus I left-justify the value in the textbox and format it without currency and grouping characters. Just the raw number. Then when the control loses focus (blur), I re-format the contents based on a property that indicates which formatting to use. This custom TextBox accepts only numeric input. In the case of a curreny input (DisplayFormat = "C") and a negative number, the number is formatted using the current culture's CurrencyNegativePattern of CultureInfo.NumberFormat. AJAX handles all of this for me since I call the Number.localeFormat function. The problem is that when the TextBox receives focus, I try to strip all formatting to get the raw number but for a negative currency value AJAX'sparseLocale function does not recognize the parantheses that are added to the number when it is formatted bylocaleFormat. Example: -1000 is formatted as ($1,000.00) with a format string of "C2" but when you pass this toparseLocale you get "1000.00". Shouldn'tparseLocale recognize the negative patterns its counterpartlocaleFormat adds to the value?

function numberEditorFocus(src)
{
src.style.textAlign ='left';
var displayFormat ="D";
if (src.value !="")
{
var val = Number.parseLocale(stripCurrency(src.value));
alert(val);
if (isNaN(val) ==false)
{
var newValue = val.localeFormat(displayFormat);
src.value = newValue;
}
src.select();
}
}

Sounds like it may be a bug, take a look in the source code for the AJAX Framework or theissues list

-Damien


Nothing in the bug list. It's obvious from the source code in the AJAX library that the parseLocale (and subsequently the parse) function does not consider the negative currency pattern. It only accounts for the preceding +/- sign. So, is this a bug or is there some reason it was designed with way? AJAX team?

Number.parseLocale = function Number$parseLocale(value) { /// <param name="value" type="String"></param> /// <returns type="Number"></returns> var e = Function._validateParams(arguments, [ {name: "value", type: String} ]); if (e) throw e; return Number._parse(value, Sys.CultureInfo.CurrentCulture);}Number.parseInvariant = function Number$parseInvariant(value) { /// <param name="value" type="String"></param> /// <returns type="Number"></returns> var e = Function._validateParams(arguments, [ {name: "value", type: String} ]); if (e) throw e; return Number._parse(value, Sys.CultureInfo.InvariantCulture);}Number._parse = function Number$_parse(value, cultureInfo) { var valueStr = value.trim(); if (valueStr.match(/infinity/i) !== null) { return parseFloat(valueStr); } if (valueStr.match(/^0x[a-f0-9]+$/i) !== null) { return parseInt(valueStr); } var numFormat = cultureInfo.numberFormat; var decSeparator = numFormat.NumberDecimalSeparator; var grpSeparator = numFormat.NumberGroupSeparator; var numberFormatRegex = new RegExp("^[+-]?[\\d\\" + grpSeparator + "]*\\" + decSeparator + "?\\d*([eE][+-]?\\d+)?$"); if (!valueStr.match(numberFormatRegex)) { return Number.NaN; } valueStr = valueStr.split(grpSeparator).join(""); valueStr = valueStr.replace(decSeparator, "."); return parseFloat(valueStr);}


I'd modify the source and recompile for now so that it works for you, and I would log this as a bug...

-Damien