Tuesday, April 17, 2007

ASP.NET Ajax - ‘AJAXControlToolkit is undefined’ - cachePolicy.SetLastModified((DateTime)GetAssemblyInfo(assembly).Second)

Problem declares itself as ‘AJAXControlToolkit is undefined’ on the client side (with few other client side exceptions before that). Server side exception info though provide enough insight into the problem...

That is another tricky one you can found in the ScriptResourceHandler.cs in the current ASP.NET Ajax.
Setting of the LastModified to anything that is newer than now from the server view is illegal (you will get ArgumentOutOfRangeException).
Though, how the GetAssemblyInfo(assembly).Second works?



private static DateTime GetLastWriteTime(Assembly assembly) {
string codeBase = GetCodeBaseWithAssert(assembly);
Uri codeBaseUri = new Uri(codeBase);
if (!codeBaseUri.IsFile) return DateTime.MinValue;
string localPath = codeBaseUri.LocalPath;

FileIOPermission p = new FileIOPermission(FileIOPermissionAccess.Read, localPath);
p.Assert();
return File.GetLastWriteTime(localPath);
}




The above takes the assembly the script located into and looks for it LastWriteTime.
Beware if you have that assembly copied from somewhere where this date may go ahead of the server time! That happens to us all the time when copying from Europe to USA :)!

P.S. Exception text on the server is like:

Event Type: Warning
Event Source: ASP.NET 2.0.50727.0
Event Category: Web Event
...
User: N/A
Computer: ... Description: Event code: ...
Event message: An unhandled exception has occurred.
....
Event sequence: 9 Event occurrence: 1 Event detail code: 0

Application information:
....

Process information: Process ID: ... Process name: ... Account name: ...

Exception information:
Exception type: ArgumentOutOfRangeException
Exception message: Specified argument was out of the range of valid values.
Parameter name: utcDate

Request information: Request URL: .../ScriptResource.axd?....
....

Stack trace: at System.Web.HttpCachePolicy.UtcSetLastModified(DateTime utcDate)
at System.Web.HttpCachePolicy.SetLastModified(DateTime date)
at System.Web.Handlers.ScriptResourceHandler.PrepareResponseCache(HttpResponse response, Assembly assembly)
at System.Web.Handlers.ScriptResourceHandler.ProcessRequest(HttpContext context)
at System.Web.Handlers.ScriptResourceHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext context)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

What would be the solution? - Touch the file your script resource is inside. There are few programs to do it, or you can just use simple .net console application for that:

class Program
    {
        static void Main(string[] args)
        {
            try
            {
                if (args.Length < 1)
                {
                    Console.WriteLine(String.Format(CultureInfo.InvariantCulture,
                        "Usage: SetFileModifiedDate \"FilePath\""));
                    return;

                }
                string filePath = args[0];

                if (!File.Exists(filePath))
                {
                    Console.WriteLine("File: \"" + filePath + "\" doesn't exist!");
                    return;

                }
                FileAttributes attr = File.GetAttributes(filePath);

                if ((attr & FileAttributes.ReadOnly) > 0)
                {
                    Console.WriteLine("File: \"" + filePath + "\" is readonly!");
                    return;
                }
                FileInfo fi = new FileInfo(filePath);
                fi.LastWriteTime = DateTime.Now.AddDays(-1);

                Console.WriteLine("Modified date is now set to: " + fi.LastWriteTime.ToString("ddMMMyyTHH:mm:ss fff"));
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
    }

The only principal lines you can shorten your solution to:

FileInfo fi = new FileInfo(filePath);
fi.LastWriteTime = DateTime.Now.AddDays(-1);

That should be only few lines of powershell script as well.


 

Post a Comment