मैंने अपनी मूल पोस्ट में जो वर्कअराउंड किया था, उसे मैंने लागू किया, हालाँकि यह मेरे द्वारा मूल रूप से वर्णित की तुलना में थोड़ा अलग था। फिक्स को वास्तव में 2 भागों में विभाजित किया जा सकता है - एक कुकीज के अक्षम होने पर डेटाबेस को अपडेट करने की समस्या को ठीक करने के लिए, और दूसरा यह पता लगाने के लिए कि कुकीज़ को रीडायरेक्ट किए बिना कब अक्षम किया जाता है।
मैंने पहले ही कुकीज़ के अक्षम होने पर रिकॉर्ड बनाने वाली अनाम प्रोफ़ाइल का समाधान ।
तो अब मैं दूसरे भाग पर ध्यान केंद्रित करूंगा - अनुरोध किए गए पहले पृष्ठ से प्रोफ़ाइल में जानकारी प्राप्त करना। यह केवल तभी करने की आवश्यकता है यदि आप एनालिटिक्स ट्रैकिंग या कुछ इसी तरह कर रहे हैं - पहला भाग डेटाबेस को पूरी तरह से बेकार डेटा से भरने से बचाने का ध्यान रखेगा जब 1) कुकीज़ अक्षम हो जाती हैं और 2) अनाम प्रोफ़ाइल गुणों का उपयोग किया जाता है और से काम करता है दूसरा अनुरोध (या पहला पोस्टबैक) आगे।
जब मैंने यह देखने के लिए जाँच के मुद्दे पर शोध किया कि क्या कुकीज़ सक्षम हैं, तो अधिकांश समाधान एक ही पृष्ठ या एक अलग पृष्ठ पर रीडायरेक्ट का उपयोग करते हैं और फिर से वापस आते हैं। दिलचस्प है, MSDN वह था जो 2-रीडायरेक्ट समाधान के साथ आया था।
हालांकि कुछ परिस्थितियों में रीडायरेक्ट स्वीकार्य है, मैं नहीं चाहता था कि अतिरिक्त प्रदर्शन प्रभाव हमारे अधिकांश उपयोगकर्ताओं को प्रभावित करे। इसके बजाय, मैंने एक और तरीका चुना - पहला अनुरोध पूरा होने के बाद सर्वर पर कोड चलाने के लिए AJAX का उपयोग करें। जबकि इसका पुनर्निर्देशन न करने का लाभ है, जावास्क्रिप्ट के अक्षम होने पर कार्य न करने का नुकसान है। हालांकि, मैंने इस दृष्टिकोण को चुना क्योंकि प्रारंभिक अनुरोध पर खो जाने वाले डेटा का प्रतिशत महत्वहीन है और एप्लिकेशन स्वयं इस डेटा पर निर्भर नहीं है।
तो, प्रक्रिया की शुरुआत से अंत तक चलते हुए...
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
यह मेरी कस्टम पेजबेस क्लास में रखी गई पेज_लोड विधि है, जो प्रोजेक्ट के सभी पेजों से प्राप्त होती है। सबसे पहले हम यह जांचते हैं कि क्या यह सत्र की जाँच करके एक नया सत्र है। 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 कॉल इंजेक्ट करने की हमारी विधि है। ध्यान रखें, यह अभी भी आधार वर्ग है, इस पर ध्यान दिए बिना कि उपयोगकर्ता इस कोड पर लैंड करता है, पहले पेज के अनुरोध पर चलेगा।
जावास्क्रिप्ट के अंदर, हम पहले यह देखने के लिए परीक्षण करते हैं कि क्या कुकीज़ सक्षम हैं और यदि ऐसा है, तो AJAX और JQuery का उपयोग करके सर्वर पर एक कस्टम हैंडलर को कॉल करें। हम सर्वर से इस कोड में पैरामीटर पास कर रहे हैं (हालांकि उनमें से 2 क्लाइंट द्वारा अभी आपूर्ति की जा सकती थी, अतिरिक्त बाइट इतने महत्वपूर्ण नहीं हैं)।
दूसरी विधि प्रोफ़ाइल को अपडेट करती है और इसमें ऐसा करने के लिए मेरा कस्टम तर्क होगा। मैंने आंशिक यूआरएल से क्वेरीस्ट्रिंग मानों को पार्स करने के तरीके पर एक स्निपेट शामिल किया। लेकिन केवल एक चीज जो वास्तव में यहां जानने की जरूरत है वह यह है कि यह साझा विधि है जो प्रोफ़ाइल को अपडेट करती है।
महत्वपूर्ण: AJAX कॉल को कार्य करने के लिए, निम्न हैंडलर को web.config फ़ाइल के system.web अनुभाग में जोड़ा जाना चाहिए:
<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 जावास्क्रिप्ट फ़ंक्शन हैं (एक कस्टम .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 कुकी को पास किया जाता है (मेरी अन्य पोस्ट से बेनामीप्रोफाइल वर्ग का उपयोग करके एक बार फिर से जाँच की जाती है), जो रोबोट और अन्य स्क्रिप्ट को इसे निष्पादित करने से रोकेगा।
यदि आवश्यक हो तो हम सत्र ऑब्जेक्ट को अपडेट करने के लिए कुछ कोड चलाते हैं। किसी अजीब कारण के लिए, सत्र वास्तव में अद्यतन होने तक IsNewSession मान सत्य रहेगा, लेकिन केवल तभी जब सत्र_स्टार्ट के लिए हैंडलर ग्लोबल.एएसएक्स में मौजूद न हो। इसलिए इस कोड को Global.asax फ़ाइल के साथ और उसके बिना और सत्र ऑब्जेक्ट को अपडेट करने वाले किसी अन्य कोड के बिना काम करने के लिए, हम यहां एक अपडेट चलाते हैं।
कोड का अगला बिट मैंने यह पोस्ट और इसमें JSON.NET धारावाहिक के लिए एक निर्भरता है। मैं अतिरिक्त निर्भरता के कारण इस दृष्टिकोण का उपयोग करने के बारे में फटा हुआ था, लेकिन अंततः फैसला किया कि JSON धारावाहिक भविष्य में मूल्यवान होगा क्योंकि मैं साइट पर AJAX और JQuery जोड़ना जारी रखता हूं।
फिर हम केवल पैरामीटर प्राप्त करते हैं और उन्हें पेजबेस क्लास में हमारी साझा अपडेटप्रोफाइल विधि में पास करते हैं जिसे पहले परिभाषित किया गया था।
<!-- 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>
अंत में, हमारे पास प्रोफ़ाइल गुणों के लिए हमारा कॉन्फ़िगरेशन अनुभाग है, जिसे गुमनाम रूप से उपयोग करने के लिए सेट किया गया है (मैंने जानबूझकर कनेक्शन स्ट्रिंग अनुभाग को छोड़ दिया है, लेकिन एक संबंधित कनेक्शन स्ट्रिंग और डेटाबेस की भी आवश्यकता है)। यहां ध्यान देने वाली मुख्य बात प्रोफाइल पर इनहेरिट एट्रिब्यूट को शामिल करना है। यह एक बार फिर बेनामीप्रोफाइल वर्ग के लिए है जो मेरे अन्य पोस्ट ।