sql >> Databáze >  >> RDS >> Sqlserver

Existují efektivnější alternativy k anonymním profilům ASP.NET 2.0?

Implementoval jsem řešení, se kterým jsem přišel ve svém původním příspěvku, ale ukázalo se, že je trochu jiné, než jsem původně popsal. Opravu lze ve skutečnosti rozdělit na 2 části – jednu pro vyřešení problému s aktualizací databáze, když jsou soubory cookie zakázány, a druhou pro zjištění, kdy jsou zakázány soubory cookie, aniž by bylo nutné provést přesměrování.

Již jsem zveřejnil řešení pro anonymní profily vytvářející záznamy, když jsou soubory cookie zakázány .

Nyní se tedy zaměřím na druhou část – získávání informací do profilu z první požadované stránky. To je potřeba udělat pouze v případě, že provádíte analytické sledování nebo něco podobného – první část se postará o ochranu databáze před zaplněním zcela zbytečnými daty, když 1) jsou zakázány soubory cookie a 2) jsou používány a fungují anonymní vlastnosti profilu druhý požadavek (nebo první postback) dále.

Když jsem zkoumal problém kontroly, zda jsou povoleny soubory cookie, většina řešení používala přesměrování na stejnou stránku nebo jinou stránku a zpět. Zajímavé je, že MSDN byl ten, kdo přišel s řešením 2 přesměrování.

I když je za určitých okolností přesměrování přijatelné, nechtěl jsem, aby další dopad na výkon ovlivnil většinu našich uživatelů. Místo toho jsem se rozhodl pro jiný přístup - použít AJAX ke spuštění kódu na serveru po dokončení prvního požadavku. I když to má tu výhodu, že nezpůsobuje přesměrování, má to tu nevýhodu, že nefunguje, když je JavaScript vypnutý. Rozhodl jsem se však pro tento přístup, protože procento dat, která jsou ztracena při prvním požadavku, je nevýznamné a samotná aplikace na těchto datech nezávisí.

Takže projít od začátku procesu do konce...

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    If Not Me.IsPostBack Then

        If Session.IsNewSession Then
            Me.InjectProfileJavaScript()
        ElseIf AnonymousProfile.IsAnonymousCookieStored Then
            'If cookies are supported, and this isn't the first request, update the
            'profile using the current page data.
            UpdateProfile(Request.RawUrl, Request.UrlReferrer.OriginalString, CurrentProductID.ToString)
        End If

    End If

End Sub

Toto je metoda Page_Load umístěná v mé vlastní třídě PageBase, kterou dědí všechny stránky v projektu. První věc, kterou zkontrolujeme, je, zda se jedná o novou relaci, a to kontrolou vlastnosti Session.IsNewSession. Tato vlastnost je vždy pravdivá, pokud jsou soubory cookie zakázány nebo pokud se jedná o první požadavek. V obou případech nechceme zapisovat do databáze.

Sekce "else if" se spustí, pokud klient přijal cookie relace a toto není první požadavek na server. U tohoto fragmentu kódu je třeba poznamenat, že obě sekce nemohou běžet ve stejném požadavku, což znamená, že profil lze aktualizovat pouze 1 (nebo 0)krát na požadavek.

Třída AnonymousProfile je součástí mého jiný příspěvek .

Private Sub InjectProfileJavaScript()

    Dim sb As New StringBuilder

    sb.AppendLine("$(document).ready(function() {")
    sb.AppendLine("  if (areCookiesSupported() == true) {")
    sb.AppendLine("    $.ajax({")
    sb.AppendLine("      type: 'POST',")
    sb.AppendLine("      url: 'HttpHandlers/UpdateProfile.ashx',")
    sb.AppendLine("      contentType: 'application/json; charset=utf-8',")
    sb.AppendFormat("      data: ""{3}'RawUrl':'{0}', 'ReferralUrl':'{1}', 'ProductID':{2}{4}"",", Request.RawUrl, Request.UrlReferrer, CurrentProductID.ToString, "{", "}")
    sb.AppendLine()
    sb.AppendLine("      dataType: 'json'")
    sb.AppendLine("    });")
    sb.AppendLine("  }")
    sb.AppendLine("});")

    Page.ClientScript.RegisterClientScriptBlock(GetType(Page), "UpdateProfile", sb.ToString, True)

End Sub

Public Shared Sub UpdateProfile(ByVal RawUrl As String, ByVal ReferralUrl As String, ByVal ProductID As Integer)
    Dim context As HttpContext = HttpContext.Current
    Dim profile As ProfileCommon = CType(context.Profile, ProfileCommon)

    Dim CurrentUrl As New System.Uri("http://www.test.com" & RawUrl)
    Dim query As NameValueCollection = HttpUtility.ParseQueryString(CurrentUrl.Query)
    Dim source As String = query.Item("source")
    Dim search As String = query.Item("search")
    Dim OVKEY As String = query.Item("OVKEY")

    'Update the profile
    profile.TestValue1 = source
    profile.TestValue2 = search

End Sub

Dále máme naši metodu, jak do stránky vložit volání AJAX. Mějte na paměti, že se stále jedná o základní třídu, takže bez ohledu na stránku, na které se uživatel dostane na tento kód, se spustí na první žádost o stránku.

Uvnitř JavaScriptu nejprve otestujeme, zda jsou povoleny soubory cookie, a pokud ano, zavoláme na serveru vlastní obslužnou rutinu pomocí AJAX a JQuery. Do tohoto kódu předáváme parametry ze serveru (ačkoli 2 z nich mohl právě poskytnout klient, bajty navíc nejsou tak významné).

Druhá metoda aktualizuje profil a bude obsahovat moji vlastní logiku. Zahrnul jsem úryvek o tom, jak analyzovat hodnoty řetězce dotazů z částečné adresy URL. Ale jediná věc, kterou je zde opravdu potřeba vědět, je, že toto je sdílená metoda, která aktualizuje profil.

Důležité: Aby volání AJAX fungovalo, musí být do sekce system.web souboru web.config přidán následující handler:

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

Rozhodl jsem se, že bude nejlepší otestovat soubory cookie na klientovi a neprovádět další volání AJAX, pokud jsou soubory cookie zakázány. Chcete-li otestovat soubory cookie, použijte tento kód:

function areCookiesSupported() {
    var c='c';var ret = false;
    document.cookie = 'c=2;';
    if (document.cookie.indexOf(c,0) > -1) {
        ret = true;
    } else {
        ret = false;
    }
    deleteCookie(c);
    return ret
}
function deleteCookie(name) {
    var d = new Date();
    document.cookie = name + '=1;expires=' + d.toGMTString() + ';' + ';';
}

Jedná se o 2 funkce JavaScriptu (ve vlastním souboru .js), které jednoduše zapíší soubor cookie a přečtou jej zpět, aby se zjistilo, zda lze soubory cookie číst. Poté vyčistí soubor cookie nastavením data vypršení platnosti v minulosti.

<%@ WebHandler Language="VB" Class="Handlers.UpdateProfile" %>

Imports System
Imports System.Web
Imports System.Web.SessionState
Imports Newtonsoft.Json
Imports System.Collections.Generic
Imports System.IO

Namespace Handlers

    Public Class UpdateProfile : Implements IHttpHandler : Implements IRequiresSessionState

        Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest

            If AnonymousProfile.IsAnonymousCookieStored Then

                If context.Session.IsNewSession Then
                    'Writing to session state will reset the IsNewSession flag on the
                    'next request. This will fix a problem if there is no Session_Start
                    'defined in global.asax and no other session variables are written.
                    context.Session("ActivateSession") = ""
                End If

                Dim reader As New StreamReader(context.Request.InputStream)
                Dim params As Dictionary(Of String, String) = JsonConvert.DeserializeObject(Of Dictionary(Of String, String))(reader.ReadToEnd())

                Dim RawUrl As String = params("RawUrl")
                Dim ReferralUrl As String = params("ReferralUrl")
                Dim ProductID As Integer = params("ProductID")

                PageBase.UpdateProfile(RawUrl, ReferralUrl, ProductID)
            End If
        End Sub

        Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
            Get
                Return False
            End Get
        End Property

    End Class

End Namespace

Toto je naše vlastní třída HttpHandler, která přijímá požadavek AJAX. Požadavek je zpracován pouze v případě, že je předán soubor cookie .ASPXANONYMOUS (zkontrolováno ještě jednou pomocí třídy AnonymousProfile z mého jiného příspěvku), což zabrání robotům a dalším skriptům v jeho spuštění.

Dále spustíme nějaký kód pro aktualizaci objektu relace, pokud je to vyžadováno. Z nějakého podivného důvodu zůstane hodnota IsNewSession pravdivá, dokud nebude relace skutečně aktualizována, ale pouze v případě, že v souboru Global.asax neexistuje handler pro Session_Start. Aby tento kód fungoval jak se souborem Global.asax, tak bez něj a bez jakéhokoli dalšího kódu, který aktualizuje objekt relace, spustíme aktualizaci zde.

Další kousek kódu jsem získal z tento příspěvek a obsahuje závislost na serializátoru JSON.NET. Z použití tohoto přístupu jsem byl rozrušený kvůli další závislosti, ale nakonec jsem se rozhodl, že serializátor JSON bude pravděpodobně v budoucnu cenný, protože budu na web nadále přidávat AJAX a JQuery.

Pak jednoduše získáme parametry a předáme je naší sdílené metodě UpdateProfile ve třídě PageBase, která byla definována dříve.

<!-- Required for anonymous profiles -->
<anonymousIdentification enabled="true"/>
<profile defaultProvider="SqlProvider" inherits="AnonymousProfile">
    <providers>
        <clear/>
        <add name="SqlProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="SqlServices" applicationName="MyApp" description="SqlProfileProvider for profile test web site"/>
    </providers>
    <properties>
        <add name="TestValue1" allowAnonymous="true"/>
        <add name="TestValue2" allowAnonymous="true"/>
    </properties>
</profile>

Nakonec máme naši konfigurační sekci pro vlastnosti profilu, nastavenou pro anonymní použití (záměrně jsem vynechal sekci připojovacího řetězce, ale je také vyžadován odpovídající připojovací řetězec a databáze). Hlavní věc, kterou je třeba poznamenat, je zahrnutí atributu zdědí do profilu. Toto je opět pro třídu AnonymousProfile, která je definována v mém jiný příspěvek .




  1. NHibernate Oracle - Nelze načíst DLL 'OraOps10w.dll'

  2. Přejmenujte tabulku MySQL pomocí příkazu SQL

  3. Vícenásobný výběrový příkaz v uložené proceduře k získání požadovaného výsledku

  4. Můžete věřit mysql_insert_id?