私たちは実際にscriptresource.axdを含む、ページ上のすべてのコントロールからすべてのjを自動的に抽出し、それらを単一のキャッシュファイルに保存するScriptManagerの上にコントロールを作成しました。これにより、自動化されているため、パフォーマンスが大幅に向上し、保守作業が軽減されます。私たちは.Net 2.0から始まりました。ScriptManagerが同じ機能を提供するかどうかは分かりませんが、言及する価値はあると思いました。ここで
は、私たちのこのクラスの実装です:上記のコードで
Option Explicit On
Option Strict On
Imports System.Collections.Generic
Imports System.Web.SessionState
Public Class OurScriptManager
Inherits ScriptManager
Implements IRequiresSessionState
Private m_ScriptBuilder As New StringBuilder
'Private m_sSessionIndex As String = ""
Private m_cScripts As List(Of ScriptReference)
Private m_fIsCached As Boolean
Private m_sScriptName As String = ""
Private m_sScriptFileName As String = ""
Const CACHED_SCRIPTS_DIR As String = "/scriptcache/"
Public Sub New()
' default constructor
End Sub
Public Property ScriptName() As String
Get
Return m_sScriptName
End Get
Set(ByVal value As String)
m_sScriptName = value
End Set
End Property
Private ReadOnly Property ScriptFileName() As String
Get
If String.IsNullOrEmpty(m_sScriptFileName) Then
m_sScriptFileName = "~" & CACHED_SCRIPTS_DIR & Me.ScriptName & ".js"
End If
Return m_sScriptFileName
End Get
End Property
Protected Overrides Sub OnInit(ByVal e As System.EventArgs)
' Exceptions are handled by the caller
MyBase.OnInit(e)
If String.IsNullOrEmpty(Me.ScriptName) Then
Me.ScriptName = Me.Page.ToString
End If
' this compiled script should be cached on the server
' check for the file, if it exists, load that file instead of generating it
If Configuration.HasPageScriptBeenCached(Me.ScriptFileName) AndAlso File.Exists(Me.Page.Server.MapPath(Me.ScriptFileName)) Then
m_fIsCached = True
Else
m_cScripts = New List(Of ScriptReference)
End If
End Sub
Protected Overrides Sub OnResolveScriptReference(ByVal e As System.Web.UI.ScriptReferenceEventArgs)
Try
MyBase.OnResolveScriptReference(e)
If Not m_fIsCached Then
' First, check to make sure this script should be loaded
Dim fIsFound As Boolean
For Each oXref As ScriptReference In m_cScripts
If oXref.Assembly = e.Script.Assembly AndAlso oXref.Name = e.Script.Name AndAlso oXref.Path = e.Script.Path Then
fIsFound = True
Exit For
End If
Next
' If this script is found within the list of scripts that this page uses, add the script to the scripthandler.aspx js output
If Not fIsFound Then
Dim oReference As ScriptReference
Dim oElement As ScriptReference
Dim fIsPathBased As Boolean
oElement = e.Script
If String.IsNullOrEmpty(oElement.Path) AndAlso Not String.IsNullOrEmpty(oElement.Name) AndAlso String.IsNullOrEmpty(oElement.Assembly) Then
' If resource belongs to System.Web.Extensions.dll, it does not
' provide assembly info that's why hard-coded assembly name is
' written to get it in profiler
oElement.Assembly = "System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
End If
'check to see what type of script this is
If Not String.IsNullOrEmpty(oElement.Path) Then
' this script is a physical file
oReference = New ScriptReference(oElement.Path)
fIsPathBased = True
ElseIf Not String.IsNullOrEmpty(oElement.Assembly) AndAlso Not String.IsNullOrEmpty(oElement.Name) Then
' this script is generated by an assembly
oReference = New ScriptReference(oElement.Name, oElement.Assembly)
Else
' Couldn't find script, so bail to allow standard processing to take place.
Return
End If
If Not fIsPathBased Then
Dim sUrl As String
Dim oRequest As HttpRequest
Dim sScriptResourcePath As String
sUrl = GetUrl(oReference)
sScriptResourcePath = String.Format("{0}{1}{2}{3}{4}{5}{6}{7}", Context.Request.Url.Scheme, "://", Context.Request.Url.Host, ":", Context.Request.Url.Port, "/", Context.Request.ApplicationPath, "/ScriptResource.axd")
oRequest = New HttpRequest("scriptresource.axd", sScriptResourcePath, sUrl.Substring(sUrl.IndexOf("?"c) + 1))
Try
Using oWriter As New StringWriter(m_ScriptBuilder)
Dim oHandler As IHttpHandler = New System.Web.Handlers.ScriptResourceHandler
oHandler.ProcessRequest(New HttpContext(oRequest, New HttpResponse(oWriter)))
End Using
Catch theException As Exception
Call ReportError(theException)
' Since we couldn't automatically process this, just bail so that standard processing takes over
Return
End Try
Else
' If this script is from a file, open the file and load the
' contents of the file into the compiled js variable
Dim sAbsolutePath As String
sAbsolutePath = Context.Server.MapPath(oElement.Path)
Try
If System.IO.File.Exists(sAbsolutePath) Then
Using oReader As New StreamReader(sAbsolutePath, True)
m_ScriptBuilder.Append(oReader.ReadToEnd())
End Using
Else
Throw New Exception("File " & sAbsolutePath & " does not exist")
End If
Catch theException As Exception
Call ReportError(theException, New ExtraErrorInformation("File", sAbsolutePath))
' Since we couldn't automatically process this, just bail so that standard processing takes over
Return
End Try
End If
m_ScriptBuilder.AppendLine()
' add this script to the script reference library
Dim oNewElement As New ScriptReference
oNewElement.Name = e.Script.Name.ToString()
oNewElement.Assembly = e.Script.Assembly.ToString()
oNewElement.Path = e.Script.Path.ToString()
m_cScripts.Add(oNewElement)
End If
End If
' a script filename is provided for caching
e.Script.Assembly = String.Empty
e.Script.Name = String.Empty
e.Script.Path = Me.ScriptFileName
Catch theException As Exception
HttpContext.Current.Response.Write(ReportError(theException))
HttpContext.Current.Response.End()
End Try
End Sub
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
' Exceptions are handled by the caller
MyBase.Render(writer)
If Not m_fIsCached Then
If Not String.IsNullOrEmpty(Me.ScriptName) Then
' Save script to file for caching
Using fsFile As New FileStream(Me.Page.Server.MapPath(Me.ScriptFileName), FileMode.Create, FileAccess.Write, FileShare.Read)
Using oWriter As New StreamWriter(fsFile)
oWriter.Write(m_ScriptBuilder.ToString)
oWriter.Flush()
oWriter.Close()
End Using
fsFile.Close()
End Using
' Record that the script file has been cached
Configuration.RecordPageScriptCached(Me.ScriptFileName)
End If
m_ScriptBuilder = Nothing
End If
End Sub
Private Function GetUrl(ByVal oReference As ScriptReference) As String
' Exceptions are handled by the caller
If String.IsNullOrEmpty(oReference.Path) Then
Try
Dim oMethod As MethodInfo
oMethod = oReference.GetType.GetMethod("GetUrl", BindingFlags.NonPublic Or BindingFlags.Instance)
If oMethod IsNot Nothing Then
Return DirectCast(oMethod.Invoke(oReference, New Object() {Me, False}), String)
Else
Return String.Empty
End If
Catch ex As Exception
Return String.Empty
End Try
Else
Return Me.ResolveClientUrl(oReference.Path)
End If
End Function
End Class
、でReportErrorは、イベントログおよび/またはファイルに例外を記録します。これを独自のメカニズムで置き換えることができます。
ここでの設定コードです:
Private Shared m_cCachedPageScripts As Collections.Generic.List(Of String)
''' <summary>
''' This method is used to determine whether or not the script for the page has been cached.
''' This is used for script combining.
''' </summary>
''' <param name="sKey"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function HasPageScriptBeenCached(ByVal sKey As String) As Boolean
' Exceptions are handled by the caller
SyncLock CacheSyncObject
If m_cCachedPageScripts IsNot Nothing AndAlso m_cCachedPageScripts.Contains(sKey) Then
Return True
End If
End SyncLock
End Function
''' <summary>
''' This method is used to record the fact that the page script has been cached.
''' This is used for script combining.
''' </summary>
''' <param name="sKey"></param>
''' <remarks></remarks>
Public Shared Sub RecordPageScriptCached(ByVal sKey As String)
' Exceptions are handled by the caller
SyncLock CacheSyncObject
If m_cCachedPageScripts Is Nothing Then
m_cCachedPageScripts.Add(sKey)
End If
m_cCachedPageScripts.Add(sKey)
End SyncLock
End Sub
[ASP.netで複数のJavaScriptファイルを組み合わせるとキャッシュ]の可能な重複(http://stackoverflow.com/questions/47937/combining-and-caching-は、複数のjavascript-files-in-asp-net) –
Hmm。しかし、申し訳ありませんが、それを見つけませんでした...その質問から参照されるコントロールは.NET 3用です。残念ながら、私は現在、私のホスティングによって.NET 2.0にバインドされています。 –
[このスレッド](http://forums.asp.net/t/1525305.aspx/1)によると、 "ASP.Net 2.0 AJAX拡張機能"のセットをインストールする場合、 'ScriptManager'を使用することができます。 –