Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Има ли по-ефективни алтернативи на анонимните профили на ASP.NET 2.0?

Приложих заобиколното решение, което измислих в първоначалния си пост, но се оказа, че е малко по-различно от това, което първоначално описах. Корекцията всъщност може да бъде разделена на 2 части - една за отстраняване на проблема с актуализирането на базата данни, когато бисквитките са деактивирани, а втората за откриване кога бисквитките са деактивирани, без да се прави пренасочване.

Вече публикувах решение за анонимните профили, създаващи записи, когато бисквитките са деактивирани .

Така че сега ще се съсредоточа върху втората част - получаване на информация в профила от първата поискана страница. Това трябва да се направи само ако извършвате аналитично проследяване или нещо подобно - първата част ще се погрижи за защитата на базата данни от запълване с напълно безполезни данни, когато 1) бисквитките са деактивирани и 2) се използват анонимни свойства на профила и работи от втората заявка (или първата поща) нататък.

Когато проучих проблема с проверката дали бисквитките са активирани, повечето решения използваха пренасочване към същата страница или към друга страница и обратно. Интересното е, че MSDN беше този, който излезе с решението за 2 пренасочвания.

Въпреки че при определени обстоятелства пренасочването е приемливо, не исках допълнителното въздействие върху производителността да засегне мнозинството от нашите потребители. Вместо това избрах друг подход - използвам AJAX за изпълнение на код на сървъра, след като първата заявка е завършена. Въпреки че това има предимството да не предизвиква пренасочване, има недостатъка да не функционира, когато JavaScript е деактивиран. Въпреки това избрах този подход, тъй като процентът на данните, които се губят при първоначална заявка, е незначителен и самото приложение не зависи от тези данни.

И така, преминавайки от началото на процеса до края...

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

Това е методът Page_Load, поставен в моя персонализиран клас PageBase, от който наследяват всички страници в проекта. Първото нещо, което проверяваме е дали това е нова сесия, като проверяваме свойството Session.IsNewSession. Това свойство винаги е вярно, ако бисквитките са деактивирани или ако това е първата заявка. И в двата случая не искаме да пишем в базата данни.

Секцията „друго ако“ се изпълнява, ако клиентът е приел сесийната бисквитка и това не е първата заявка към сървъра. Нещото, което трябва да се отбележи за този кодов фрагмент е, че и двата раздела не могат да се изпълняват в една и съща заявка, което означава, че профилът може да бъде актуализиран само 1 (или 0) пъти на заявка.

Класът AnonymousProfile е включен в моите друга публикация .

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

След това имаме нашия метод за инжектиране на AJAX извикване в страницата. Имайте предвид, че това все още е основният клас, така че независимо от страницата, на която потребителят попада, този код ще се изпълнява при заявка за първа страница.

Вътре в JavaScript първо тестваме дали бисквитките са активирани и ако е така, извикваме персонализиран манипулатор на сървъра, използвайки AJAX и JQuery. Предаваме параметрите от сървъра в този код (въпреки че 2 от тях може току-що да са били предоставени от клиента, допълнителните байтове не са толкова значими).

Вторият метод актуализира профила и ще съдържа моята персонализирана логика за това. Включих фрагмент за това как да анализирам стойностите на низа на заявката от частичен URL адрес. Но единственото нещо, което наистина трябва да се знае тук е, че това е споделеният метод, който актуализира профила.

Важно: За да функционира извикването на AJAX, следният манипулатор трябва да бъде добавен към секцията system.web на файла web.config:

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

Реших, че би било най-добре да тествам за бисквитки на клиента и да не правя допълнително AJAX извикване, ако бисквитките са деактивирани. За да тествате бисквитките, използвайте този код:

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() + ';' + ';';
}

Това са 2 JavaScript функции (в персонализиран .js файл), които просто записват бисквитка и я четат обратно, за да определят дали бисквитките могат да бъдат прочетени. След това изчиства бисквитката, като задава дата на изтичане в миналото.

<%@ 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

Това е нашият персонализиран клас HttpHandler, който получава AJAX заявката. Заявката се обработва само ако е предадена бисквитката .ASPXANONYMOUS (проверена още веднъж чрез използване на класа AnonymousProfile от другата ми публикация), което ще попречи на роботи и други скриптове да я изпълнят.

След това изпълняваме някакъв код, за да актуализираме обекта на сесията, ако е необходимо. По някаква странна причина стойността IsNewSession ще остане вярна, докато сесията действително не бъде актуализирана, но само ако манипулатор за Session_Start не съществува в Global.asax. Така че, за да накараме този код да работи както със, така и без файл Global.asax и без друг код, който актуализира обекта на сесията, ние изпълняваме актуализация тук.

Следващата част от кода, която взех от тази публикация и съдържа зависимост към JSON.NET сериализатора. Бях разкъсван да използвам този подход поради допълнителната зависимост, но в крайна сметка реших, че JSON сериализаторът вероятно ще бъде полезен в бъдеще, докато продължавам да добавям AJAX и JQuery към сайта.

След това просто получаваме параметрите и ги предаваме на нашия споделен метод UpdateProfile в класа PageBase, който беше дефиниран по-рано.

<!-- 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>

И накрая, имаме нашата конфигурационна секция за свойствата на профила, настроена да се използва анонимно (нарочно пропуснах секцията за низ за връзка, но съответният низ за връзка и база данни също са необходими). Основното нещо, което трябва да се отбележи тук, е включването на атрибута inherits в профила. Това отново е за класа AnonymousProfile, който е дефиниран в моя друга публикация .




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да конвертирате varchar в дата само когато съдържа валидна дата?

  2. Как да копирам дълбоко набор от данни и да променя FK препратките, за да сочат към всички копия?

  3. Външни ключове на SQL Server през границите на базата данни - техники за налагане

  4. Може ли SQL Server Pivot, без да знае получените имена на колони?

  5. Получаване на минимум две стойности в SQL