1

私はallowAnonymous="true"でASP.NETプロファイルを使用しています。ASP.NETメンバーシップを使用していません。最近、aspnetdbデータベースをよく調べたところ、私のサイトには毎日600〜800人のユニークな訪問者がいますが、データベースには4000〜5000人の「ユーザー」が作成されていることに気付きました。

明らかに、ここで起こっていることは、Cookieが無効になっているユーザーが、すべてのリクエストのレコードを作成することになるということです。

私の質問:クライアントがCookieをサポートしていない場合、またはCookieが無効になっている場合に、ユーザーとプロファイルのデータベースレコードが作成されないようにするにはどうすればよいですか?

4

1 に答える 1

1

多くの調査と試行錯誤の末、私はこの問題の解決策を発見しました。ただし、ユーザーが1つのリクエストからのみCookieをサポートしているかどうかを判断することは不可能であるため、このソリューションはユーザーが最初に行うリクエストに対しては機能しません。

最初のリクエストでプロファイルに設定を書き込むために、AJAXを使用してサーバーに2番目の(非表示の)リクエストを行う巧妙なソリューションを思いつきましたが、CookieとJavaScriptが有効になっている場合に限ります。もちろん、最初のリクエストでプロファイル設定を保存していない場合は、これを使用する必要はありません。詳細については、他の投稿を参照してください。

Imports System.Web.Configuration

Public MustInherit Class AnonymousProfile
    Inherits ProfileBase

    Public Shared ReadOnly Property AnonymousCookieName() As String
        Get
            Dim anon As AnonymousIdentificationSection = CType(ConfigurationManager.GetSection("system.web/anonymousIdentification"), AnonymousIdentificationSection)
            Return anon.CookieName
        End Get
    End Property

    Public Shared ReadOnly Property IsAnonymousCookieStored() As Boolean
        Get
            Dim cookies As String = HttpContext.Current.Request.Headers("Cookie")
            Return Not String.IsNullOrEmpty(cookies) AndAlso cookies.IndexOf(AnonymousCookieName) > -1
        End Get
    End Property

    Private ReadOnly Property IsWritable() As Boolean
        Get
            Return IsAnonymous = False OrElse IsAnonymous AndAlso IsAnonymousCookieStored
        End Get
    End Property

    Private Function IsObjectMatch(ByVal obj1 As Object, ByVal obj2 As Object) As Boolean
        If Not obj1 Is Nothing Then
            Return obj1.Equals(obj2)
        Else
            If obj2 Is Nothing Then
                Return True
            Else
                Return False
            End If
        End If
    End Function

    Public Overloads Sub SetPropertyValue(ByVal propertyName As String, ByVal propertyValue As Object)
        If (Not IsObjectMatch(Me.GetPropertyValue(propertyName), propertyValue)) AndAlso IsWritable Then
            MyBase.SetPropertyValue(propertyName, propertyValue)
        End If
    End Sub

    Public Overrides Sub Save()
        If IsWritable Then
            MyBase.Save()
        End If
    End Sub

End Class

簡単に言うと、このクラスは、プロファイルが匿名であり、匿名のCookieがブラウザからまだ受信されていない場合に、プロファイルが書き込まれたり保存されたりするのを防ぎます。

このクラスを使用するには、このクラスをApp_Codeディレクトリに配置し、次のようにweb.configファイルのprofile要素に「inherits」属性を追加します。

<profile defaultProvider="SqlProvider" inherits="AnonymousProfile">

ASP.NETは、自動的に生成されるときに、このクラスからProfileCommonクラスを継承します。

AnonymousCookieNameプロパティとIsAnonymousCookieStoredプロパティは公開共有されているため、次のようにプロジェクト内の他の場所で使用できます。

If AnonymousProfile.IsAnonymousCookieStored Then
   'It is safe to write to the profile here
End If

これにより、ユーザーが匿名Cookieを拒否した場合に実行する必要のないコードを実行することで、CPUサイクルを節約できますが、新しいプロファイルクラスはとにかくチェックするため、厳密には必要ありません。

このサンプルには別のバグ修正も含まれています。プロパティを既に含まれているのと同じ値に設定すると、元のプロファイルクラスは「ダーティ」になり、何も変更されていなくてもデータベースが更新されます。この問題を修正するオーバーロードされたSetPropertyValueメソッドにこの条件のチェックがあります。

Public Overloads Sub SetPropertyValue(ByVal propertyName As String, ByVal propertyValue As Object)
    If (Not IsObjectMatch(Me.GetPropertyValue(propertyName), propertyValue)) AndAlso IsWritable Then
        MyBase.SetPropertyValue(propertyName, propertyValue)
    End If
End Sub

参照:ProfileBaseクラス(MSDN)

于 2010-10-10T21:49:27.097 に答える