是否有比 ASP.NET 2.0 匿名配置文件更有效的替代方案?

发布于 2024-09-26 12:52:17 字数 2493 浏览 0 评论 0原文

几年前,我发现了 ASP.NET 配置文件,并发现可以快速、轻松地在我的网站中实现一些强大的功能。我最终只使用“匿名”配置文件属性,因为我没有使用 ASP.NET 会员资格,并且想要跟踪信息并为我的网站用户提供个性化,即使他们没有登录。

快进 3 年,现在我正在努力解决将我的 aspnetdb 数据库的大小保持在托管提供商规定的 3 GB 限制之内。一年前,我决定只保留 6 个月的配置文件数据,现在每个月我都必须运行 aspnet_Profile_DeleteInactiveProfiles 过程,然后向我的主机发出支持请求以截断数据库文件。

真正的缺点是,现在我已经实现了此功能,网站依赖于此数据库,并且每次需要截断时都会出现停机时间。今天真是太棒了 - 在对 aspnetdb 进行维护时,网站关闭了超过 12 个小时,我最终创建了 aspnetdb 数据库的故障转移副本,这样我就可以使网站再次上线(原来的 aspnetdb 数据库仍然关闭)当我写这篇文章时)。

去年,我重写了一些功能,因为它存储了一小部分二进制对象,我将其转换为存储逗号分隔的 ID 字符串,使其更小,便于存储。

我已经考虑过获得更多的磁盘空间,但现实是,仅仅为了做简单的事情(例如保留每个用户最近查看的产品的列表、跟踪)而拥有一个每年增长 4 GB 的数据库根本不值得。他们属于什么类别,“继续购物”按钮可以将他们带回,并存储购物车中的总金额(仅货币)。实际上,只有不到 5% 的数据被网站的重复访问者重复使用,但是无法提前知道哪些用户会回来访问他们的个人资料信息。

所以我的问题是是否有一种更有效的方法来存储配置文件数据,这样它就不会占用太多空间,或者是否有其他方法可以为每个用户创建配置文件数据库记录来支持此功能?

我查看了表配置文件提供程序,但是有人可以吗保证使用它是否会使用比默认提供程序更少的磁盘空间来存储数据?

更新:

我做了一些研究,似乎 nvarchar(max) 字段是 aspnetdb 默认实现使用的 ntext 字段的直接替换,但只需要一半的磁盘空间根据这篇文章< /a> 和这个。这意味着我应该能够创建 aspnetdb 的新副本,修改其架构和代码中的数据类型,并将数据传输到新数据库中。这应该可以修复数据的存储方式以及执行收缩操作时发生的任何碎片。

我现在已经完成测试并将该解决方案投入生产。起初我以为会有问题,因为 Microsoft 将 NText 数据类型硬编码到 SqlProfileProvider 内部的存储过程调用中。然而,事实证明 SQL Server 会将 NText 参数隐式转换为 nvarchar(MAX)。简而言之,除了 aspnet_Profiles 表的 PropertyNames 和 PropertyValuesString 列上的类型之外,我不需要更改任何其他内容。

必须将数据重写到磁盘以释放空间,但仅通过更改数据类型,我最终就节省了大约 30% 的空间。

另一个更新

我还发现,虽然每天大约有 700 个独立访问者,但 aspnet_Users 表中的每日“用户”数量平均约为 4000-5000。我推测这是由于某些用户在没有 cookie 的情况下进行浏览造成的。我做了一些测试,发现如果配置文件未更新,则不会创建用户,但如果您写入配置文件,如果未启用 cookie,则每个请求都会创建用户(和配置文件)。

我正在为此制定解决方法。我正在尝试编写用于对 webmethod 进行 AJAX 调用的 javascript。理论上,如果启用了 cookie,第二个请求(AJAX 调用)应该存在 .ASPXANONYMOUS cookie,因此我可以安全地写入配置文件。仅当会话开始时(由 Session.IsNewSession 属性确定),JavaScript 才会被注入到页面中。用户永远不应该知道 AJAX 调用 - 它只是告诉页面是否启用了 cookie,以便它可以更新配置文件。

当然,每个后续请求都可以简单地检查 cookie 集合以确保 .ASPXANONYMOUS cookie 存在。我很可能会创建一个共享函数,该函数既可以由称为 webmethod 的 AJAX 调用,也可以由 Page_Load 事件直接调用,并使用 IsNewSession 属性来确定允许哪个请求运行 cookie 检查和后续配置文件更新。

根据 Microsoft 的说法,使用会话来跟踪 cookie 是否已启用达不到目的(因为会话依赖于 cookie)。他们建议将您的 AreCookiesEnabled 值保存到数据库中,但他们没有提到您应该如何跟踪保存该值的位置 - 如果未启用 cookie,您如何将请求链接到数据库记录?

I discovered ASP.NET profiles a few years back and found it quick and easy to implement some powerful functionality in my web site. I ended up exclusively using "anonymous" profile properties because I am NOT using ASP.NET membership and wanted to track information and provide personalization for my site's users even though they weren't logged in.

Fast forward 3 years and now I am struggling with keeping the size of my aspnetdb database within the 3 GB limit of my hosting provider. I decided a year ago that I would only keep 6 months of profile data and every month I now have to run the aspnet_Profile_DeleteInactiveProfiles procedure followed by a support request to my host to truncate the database file.

The real downside is now that I have this functionality implemented, the web site relies on this database and there is downtime every time I need to truncate. Today really took the cake - the site was down for more than 12 hours while doing maintenance on aspnetdb and I ended up creating a failover copy of the aspnetdb database just so I could get the web site online again (the original aspnetdb database is still down as I write this).

Last year I rewrote some of the functionality because it was storing a small collection of binary objects and I converted it to store a comma delimeted string of IDs, making it smaller for storage.

I have looked into getting more disk space, but the reality is it simply isn't worth it to have a database that grows by 4 GB every year just to do simple things like keep a list of each user's most recently viewed products, keep track of what category they were in for a "continue shopping" button to take them back, and store the total amount (currency only) that is in their shopping cart. Realistically, less than 5% of the data is reused by repeat visitors to the site, however there is no way to tell in advance which of these users will make it back to access their profile information.

So my question is whether there is a more efficient way to store the profile data so it doesn't take up so much space or if there are alternatives to creating profile database records for every single user for supporting this functionality?

I took a look at the table profile provider, but can someone vouch whether using it will store the data using less disk space than the default provider?

Update:

I did some research and it seems that the nvarchar(max) field is a direct replacement for the ntext fields that are used by the default implementation of the aspnetdb, but will only require half of the disk space according to this article and this one. This means I should be able to create a new copy of aspnetdb, modify the datatype throughout its schema and code, and transfer the data into the new database. That should fix both the way the data is stored and any fragmentation that occurred when the shrink operation was performed.

I have now completed testing and moved this solution into production. At first I thought there would be a problem because Microsoft hard-coded the NText datatype into the stored procedure call inside of the SqlProfileProvider. However, as it turns out SQL Server will implicitly convert an NText parameter to nvarchar(MAX). In short, I didn't have to change anything other than the types on the PropertyNames and PropertyValuesString columns of the aspnet_Profiles table.

The data had to be rewritten to disk to free up the space, but I ended up saving about 30% overall just by changing the datatype.

Another Update:

I also discovered that although I am getting around 700 unique visitors every day, the average number of daily "users" in the aspnet_Users table averages about 4000-5000. I theororized that this was due to the fact that some users are browsing without cookies. I did some testing and discovered that a user won't be created if the profile is not updated, but if you write to the profile a user (and profile) will be created on every request if cookies are not enabled.

I am working on a workaround for this. I am attempting to write the javascript for an AJAX call to a webmethod. In theory, the second request (the AJAX call) should have the .ASPXANONYMOUS cookie present if cookies are enabled, and therefore I can safely write to the profile. The javascript will only be injected into the page if this is the beginning of the session (determined by the Session.IsNewSession property). The user should never be aware of the AJAX call - it is only there to tell the page whether cookies are enabled so it can update the profile.

Of course, every subsquent request can simply check the cookies collection to ensure the .ASPXANONYMOUS cookie is present. Most likely I will create a shared function that can be called both by an AJAX called webmethod and by the Page_Load event directly, and use the IsNewSession property to determine which request to allow to run the cookie check and subsequent profile update.

According to Microsoft, using session to keep track of whether cookies are enabled defeats the purpose (because session depends on cookies). They suggest to persist your AreCookiesEnabled value to a database, but they don't make mention of how you are supposed to keep track of where you kept the value - if cookies are not enabled, how can you link a request to a database record?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

青柠芒果 2024-10-03 12:52:17

我实现了我在原来的帖子中提出的解决方法,但结果与我最初描述的有点不同。该修复实际上可以分为两部分:第一部分修复禁用 cookie 时更新数据库的问题,第二部分检测 cookie 何时被禁用而不进行重定向。

我已经发布了 禁用 cookie 时匿名配置文件创建记录的解决方案

所以现在我将重点关注第二部分 - 从请求的第一页将信息获取到配置文件中。仅当您正在进行分析跟踪或类似操作时才需要执行此操作 - 第一部分将在 1) 禁用 cookie 和 2) 使用匿名配置文件属性并从以下位置工作时,负责保护数据库不被完全无用的数据填满从第二个请求(或第一次回发)开始。

当我研究检查 cookie 是否已启用的问题时,大多数解决方案都使用重定向到同一页面或不同页面并再次返回。有趣的是, MSDN 是提出 2-redirect 的人解决方案。

虽然在某些情况下重定向是可以接受的,但我不希望额外的性能影响影响我们的大多数用户。相反,我选择了另一种方法 - 在第一个请求完成后使用 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

这是放置在我的自定义 PageBase 类中的 Page_Load 方法,项目中的所有页面都继承自该类。我们首先检查 Session.IsNewSession 属性来检查这是否是一个新会话。如果禁用 cookie 或这是第一个请求,则此属性始终为 true。在这两种情况下,我们都不想写入数据库。

如果客户端接受会话 cookie,并且这不是对服务器的第一个请求,则“else if”部分将运行。关于此代码片段需要注意的是,两个部分不能在同一请求中运行,这意味着每个请求只能更新配置文件 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 中,我们首先测试是否启用了 cookie,如果启用,则使用 AJAX 和 JQuery 调用服务器上的自定义处理程序。我们将参数从服务器传递到此代码中(尽管其中 2 个参数可能刚刚由客户端提供,但额外的字节并不那么重要)。

第二种方法更新配置文件并将包含我的自定义逻辑来执行此操作。我包含了一个关于如何从部分 URL 解析查询字符串值的片段。但这里唯一真正需要知道的是,这是更新配置文件的共享方法。

重要提示:对于 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>

我决定最好在客户端测试 cookie,而不是如果禁用 cookie,则进行额外的 AJAX 调用。要测试 cookie,请使用以下代码:

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 文件中),它们只需写入 cookie 并将其读回以确定是否可以读取 cookie。然后它通过设置过去的过期日期来清理 cookie。

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

这是我们接收 AJAX 请求的自定义 HttpHandler 类。仅当传入 .ASPXANONYMOUS cookie(通过利用我的其他帖子中的 AnonymousProfile 类再次检查)时才会处理该请求,这将阻止机器人和其他脚本执行它。

接下来,如果需要,我们运行一些代码来更新会话对象。由于某些奇怪的原因,IsNewSession 值将保持 true 直到会话实际更新,但前提是 Global.asax 中不存在 Session_Start 的处理程序。因此,为了使此代码在有或没有 Global.asax 文件且没有任何其他更新会话对象的代码的情况下都可以工作,我们在此处运行更新。

我从这篇文章中获取的下一段代码并包含对 JSON.NET 序列化器的依赖。由于额外的依赖性,我对使用这种方法犹豫不决,但最终决定,随着我继续向网站添加 AJAX 和 JQuery,JSON 序列化器将来可能会很有价值。

然后我们只需获取参数并将它们传递给之前定义的 PageBase 类中的共享 UpdateProfile 方法。

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

最后,我们有配置文件属性的配置部分,设置为匿名使用(我故意省略了连接字符串部分,但还需要相应的连接字符串和数据库)。这里要注意的主要事情是在配置文件中包含继承属性。这再次适用于我的 其他帖子

I implemented the workaround I came up with in my original post, however it turned out to be a bit different than what I originally described. The fix can actually be broken into 2 parts - one to fix the problem with the database being updated when cookies are disabled, and the second to detect when cookies are disabled without doing a redirect.

I have already posted the solution to the anonymous profiles creating records when cookies are disabled.

So now I will focus on the second part - getting information into the profile from the first page requested. This only needs to be done if you are doing analytics tracking or something similar - the first part will take care of protecting the database from filling up with totally useless data when 1) cookies are disabled and 2) anonymous profile properties are used and works from the second request (or first postback) onwards.

When I researched the issue of checking to see if cookies are enabled, most solutions used a redirect either to the same page or a different page and back again. Interestingly, MSDN was the one who came up with the 2-redirect solution.

While in certain circumstances a redirect is acceptable, I didn't want the extra performance impact to affect the majority of our users. Instead, I opted for another approach - use AJAX to run code on the server after the first request has completed. While this has the advantage of not causing a redirect, it has the disadvantage of not functioning when JavaScript is disabled. However, I opted for this approach because the percentage of data that is being lost on initial request is insignificant and the application itself does not depend on this data.

So, walking through from the beginning of the process to the end...

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

This is the Page_Load method placed in my custom PageBase class, which all of the pages in the project inherit from. The first thing we check is whether this is a new session by checking the Session.IsNewSession property. This property is always true if cookies are disabled or if this is the first request. In both cases, we don't want to write to the database.

The "else if" section runs if the client accepted the session cookie and this is not the first request to the server. The thing to note about this code snippet is that both sections cannot run in the same request, meaning the profile can only be updated 1 (or 0) times per request.

The AnonymousProfile class is included in my other post.

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

Next, we have our method to inject an AJAX call into the page. Keep in mind, this is still the base class so regardless of the page that the user lands on this code will run on the first page request.

Inside the JavaScript, we first test to see if cookies are enabled and, if so, call a custom handler on the server using AJAX and JQuery. We are passing the parameters from the server into this code (although 2 of them could have just been supplied by the client, the extra bytes aren't that significant).

The second method updates the profile and will contain my custom logic to do so. I included a snippet on how to parse the querystring values from a partial URL. But the only thing that really needs to be known here is that this is the shared method that updates the profile.

Important: For the AJAX call to function, the following handler must be added to the system.web section of the web.config file:

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

I decided it would be best to test for cookies on the client and not make the extra AJAX call if cookies are disabled. To test the cookies, use this code:

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

These are 2 JavaScript functions (in a custom .js file) that simply write a cookie and read it back to determine if cookies can be read. It then cleans up the cookie by setting an expiration date in the past.

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

This is our Custom HttpHandler class that receives the AJAX request. The request is processed only if the .ASPXANONYMOUS cookie is passed in (checked once again by utilizing the AnonymousProfile class from my other post), which will prevent robots and other scripts from executing it.

Next we run some code to update the session object if it is required. For some strange reason, the IsNewSession value will stay true until the session is actually updated, but only if a handler for Session_Start doesn't exist in the Global.asax. So to make this code work both with and without a Global.asax file and without any other code that updates the session object, we run an update here.

The next bit of code I grabbed from this post and contains a dependency to the JSON.NET serializer. I was torn about using this approach because of the extra dependency, but ultimately decided that the JSON serializer will likely be valuable in the future as I continue adding AJAX and JQuery to the site.

Then we simply get the parameters and pass them to our shared UpdateProfile method in the PageBase class that was defined previously.

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

Lastly, we have our configuration section for the profile properties, set up to be used anonymously (I purposely ommitted the connection string section, but a corresponding connection string and database are also required). The main thing to note here is the inclusion of the inherits attribute on the profile. This once again is for the AnonymousProfile class that is defined in my other post.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文