Showing posts with label AJAX. Show all posts
Showing posts with label AJAX. Show all posts

Friday, 21 December 2007

.NET AJAX .axd give error regarding utcDate

Both WebResource.axd and ScriptResource.axd give an error at System.Web.HttpCachePolicy.UtcSetLastModified(DateTime utcDate) method, as shown below:

[ArgumentOutOfRangeException: Specified argument was out of the range of valid values.

Parameter name: utcDate]

System.Web.HttpCachePolicy.UtcSetLastModified(DateTime utcDate) +3258643
System.Web.HttpCachePolicy.SetLastModified(DateTime date) +47
System.Web.Handlers.ScriptResourceHandler.PrepareResponseCache

(HttpResponse response, Assembly assembly) +194
System.Web.Handlers.ScriptResourceHandler.ProcessRequest
(HttpContext context) +1154
System.Web.Handlers.ScriptResourceHandler.System.Web.IHttpHandler.
ProcessRequest(HttpContext context) +4
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication
.IExecutionStep.Execute() +154
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +64

First, look for the simple. If it's your machine's date time is in the past (or the future), then it is easy to fix. Just change your system clock.

In our case, it is not that straight forward. We have moved the time forward for a while, and ASP .NET 2.0 SP1 was installed while the time is in the future. So basically the assemblies and GAC modified date time is in the future. AJAX does not like it. I guess it is a bug.

We wanted to uninstall and reinstall SP1, but windows does not allow us to remove it. So we click "change" instead of "remove" in Add/Remove programs. Not sure what did windows do, but magically it works. It probably update all the installed dlls, so the modified date times are corrected.

Otherwise, we may have to "touch" all the files... :(

Thursday, 29 November 2007

.NET AJAX fail in FireFox

In short, if the following line exists in your web.config, REMOVE IT!!!

<xhtmlConformance mode="Legacy" />

It is in confiugration\system.web.


By default when you convert a VS2003 web project to VS3005, the legacy switch is added to your web.config automatically. I have found some background information about this magical line (click here).

Thursday, 11 October 2007

Button trigger UpdatePanel fails in FireFox

Firefox drove me crazy! I have spend hours to work out why it does not work, and the reason is: it does not have an image url but have alt text (and my Button is an ImageButton).

To demonstrate this, here is an example:

<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<div id="Html" runat="server" Visible="true">
Please submit
</div>

<asp:ImageButton id="SubmitButton" ImageUrl="submit_btn.gif"
onclick="SubmitButton_Click" alt="Submit" runat="server"
OnClientClick="this.style.display='none';"></asp:ImageButton>
<asp:ImageButton id="AmendButton" onclick="AmendButton_Click" alt="Amend"
runat="server" OnClientClick="this.style.display='none';"></asp:ImageButton>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="AmendButton" EventName="Click" />
<asp:AsyncPostBackTrigger ControlID="SubmitButton" EventName="Click" />
</Triggers>
</asp:UpdatePanel>

And the code behind is very simple:

        protected void SubmitButton_Click(object sender, ImageClickEventArgs e)
{
Html.InnerHtml = "Please Amend";
}

protected void AmendButton_Click(object sender, ImageClickEventArgs e)
{
Html.InnerHtml = "Please Submit";
}

The page looks like this:


s


If you click the submit button, it becomes:


a


As expected. However if you click the alt text "Amend", it will refresh the whole page instead of updating just the update panel. Basically I mean it does not work. The only solution is, of coz, give it a valid image!!!


Wasted me several hours! Now I am going home, it's 7:00pm already!

Friday, 21 September 2007

First .NET AJAX page

This is not my first AJAX page, but it's the first one I do for this project. Before this one I haven't really use .NET AJAX much although I have looked into all features and understand most theories about it. So I know a bit more than nothing, but not too much.

I've decided to document this purely for myself because I always forget what I have done, what I have encountered and what I have resolved.

First of all I've made this project into an AJAX enabled application by putting these sections into the web.config file:

1. In configuration\configSections\
<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="scriptResourceHandler" type=
"System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
requirePermission="false" allowDefinition="MachineToApplication"/>
<sectionGroup name="webServices" type=
"System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
>
<section name="jsonSerialization" type=
"System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
requirePermission="false" allowDefinition="Everywhere" />
<section name="profileService" type=
"System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
requirePermission="false" allowDefinition="MachineToApplication" />
<section name="authenticationService" type=
"System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
requirePermission="false" allowDefinition="MachineToApplication" />
</sectionGroup>
</sectionGroup>
</sectionGroup>

2. In configuration\system.web\
<pages validateRequest="false">
<controls>
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</controls>
</pages>

<compilation debug="true">
<assemblies>
<add assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</assemblies>
</compilation>

<httpModules>
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</httpModules>

3. In configuration\system.web\httpHandlers
<remove verb="*" path="*.asmx"/>
<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>

4. In configuration\
<system.web.extensions>
<scripting>
<webServices>
<!-- Uncomment this line to customize maxJsonLength and add a custom converter -->
<!--
<jsonSerialization maxJsonLength="500">
<converters>
<add name="ConvertMe" type="Acme.SubAcme.ConvertMeTypeConverter"/>
</converters>
</jsonSerialization>
-->
<!-- Uncomment this line to enable the authentication service. Include requireSSL="true" if appropriate. -->
<!--
<authenticationService enabled="true" requireSSL = "truefalse"/>
-->

<!-- Uncomment these lines to enable the profile service. To allow profile properties to be retrieved
and modified in ASP.NET AJAX applications, you need to add each property name to the readAccessProperties and
writeAccessProperties attributes. -->
<!--
<profileService enabled="true"
readAccessProperties="propertyname1,propertyname2"
writeAccessProperties="propertyname1,propertyname2" />
-->
</webServices>
<!--
<scriptResourceHandler enableCompression="true" enableCaching="true" />
-->
</scripting>

</system.web.extensions>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules>
<add name="ScriptModule" preCondition="integratedMode" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</modules>
<handlers>
<remove name="WebServiceHandlerFactory-Integrated" />
<add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode"
type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode"
type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</handlers>
</system.webServer>

Then I started to create my control. As everyone may already know, a ScriptManager is required.

<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>

Next I've added my UpdatePanel. My trigger is a drop down list. When I add the trigger in I thought it would automatically work, but it doesn't! I know this sounds stupid, but, anyway, I forgot to make the drop down list auto post back in the first place. So here is the piece of code I have:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<div id="Div1" runat="server" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="RandomDropDownList" EventName="SelectedIndexChanged" />
</Triggers>
</asp:UpdatePanel>

(to be continue... because my days usually pass too quick, I don't have too much time to do development...)

Thursday, 16 August 2007

Javascript AJAX - XML DOM HTTP Request

.Net AJAX extension is a easy and good tool, however there are two projects I have worked on cannot use .Net AJAX to accomplish the job (well, one was done before the AJAX 1.0 extension released). First project was in old fashion ASP. The second one is in .NET 2.0, but it has the application hold on an intra network machine, which for security reason has no internet access. However it requires a call to a web services on the client side.

Therefore javascript AJAX comes in by using XML DOM HTTP Request technique. Note that for javascript wa of AJAX, same as .NET AJAX 1.0, cannot call cross domain web services easily (.Net AJAX extension cannot call it at all without writing a proxies!). In Internet explorer, adding the external web service to the trusted site list will allow cross domain access.

Step 1: define XMLHTTP object variable

var xmlHttp;


Step 2: Create your action - in this example I will retrieve a list of book titles from the BibleWebservice provided by http://www.webservicex.net/.

function Button1_onclick() {

//Create SOAP Envelope
var xmlObj = new ActiveXObject("Msxml2.DOMDocument") ;
var sXml = "<?xml version=\"1.0\" ?>" ;
sXml += "<soap:Envelope "
sXml += "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" ; sXml += "xmlns:xsd=\http://www.w3.org/2001/XMLSchema/" ;
sXml += "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" ;
sXml += "<soap:Body>" ;
sXml += "<GetBookTitles xmlns=\"http://www.webserviceX.NET/\">";
sXml += "</GetBookTitles></soap:Body></soap:Envelope>" ;
xmlObj.loadXML(sXml) ;

xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
// Add Post, SOAP Action and Content-Type to the request header
xmlHttp.Open ("Post", "http://www.webservicex.net/BibleWebservice.asmx", false) ;
xmlHttp.setRequestHeader("SOAPAction", "http://www.webserviceX.NET/GetBookTitles") ;
xmlHttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8" ) ;
// When response received call OnRetrieveComplete method

xmlHttp.onreadystatechange = OnRetrieveComplete;
// Send request
xmlHttp.Send(xmlObj.xml) ;
}


Step 3: Create response handler

function OnRetrieveComplete(){

// readystate4 = Completed
if
(xmlHttp.readyState == 4 &&
xmlHttp.status == 200){

// Get response and perform your action
var
xmlResponse = xmlHttp.responseXML;
var bookXML = xmlResponse.selectSingleNode("soap:Envelope/soap:Body/
GetBookTitlesResponse/GetBookTitlesResult"
).text;
var bookXMLObj = new ActiveXObject("Msxml2.DOMDocument") ;
bookXMLObj.loadXML(bookXML);
var bookNodes = bookXMLObj.selectNodes("NewDataSet/Table");

for
(i=0; i<bookNodes.length; i++)
{
... do whatever you want

}
} }