2

My question goes hand in hand with this question (However, you might not be able to figure that out unless you read all the comments and answers there):

Does ASP.NET Identity 2 support anonymous users?

I'm just trying to elaborate or ask it a little more clearly. My question also is in regards to this Microsoft article about migrating Anonymous users:

https://msdn.microsoft.com/en-us/library/system.web.profile.profilemodule.migrateanonymous(v=vs.110).aspx

I guess the simplest question is, is that MSDN article still current/relevant for migrating anonymous users in MVC5 Identity 2.X? For one, it mentions this:

<authentication mode="Forms" >
  <forms loginUrl="login.aspx" name=".ASPXFORMSAUTH" />
</authentication>

However, in my web.config, I have this (which was added by something other than me... I assume Identity or the project template.):

<system.webServer>
<modules>
  <remove name="FormsAuthentication" />
</modules>

I am also using this in my web.config which seems to work well for dealing with anonymous users (it was added by me and is mentioned in the MSDN article):

<anonymousIdentification enabled="true" />

There would be two ways of going from anonymous to IsAuthenticated, either register or login.

Essentially, whatever the anonymous user is allowed to do, I'm grabbing the AnonymousID and dropping it into a separate table with the relevant info (e.g. CommentId => AnonymousId). (Theoretically, a user could be already registered and log out and still act as an anonymous user...in essence duplicating actions, which would need to be considered when migrating the data again when the user logs in so it doesn't create duplicates.)

Those two links I referenced and maybe a couple other articles touch on this subject, but nothing is really clear or well explained. In regards to the first chunk of code, is there a new authentication mode? Am I wrong in assuming we are not still using Forms? Is the MSDN example still current? What is a better example (if possible) or more current way of migrating anonymous users to IsAuthenticated along with any other table data the anonymous user might be linked to?

Thank you.

Update 1 (the next day): Here's what I have so far: Profile_OnMigrateAnonymous in the Global.asax still fires at successful register and logon events. Comments are added inside the example:

public void Profile_OnMigrateAnonymous(object sender, ProfileMigrateEventArgs args)
    {
        //Anything regarding this profile stuff appears to not be relevant to Identity...
        //... (and no using statements I can find will get rid of the squigglies...
        //... Even if I get rid of the Profile error, GetProfile has problems.)
        //ProfileCommon anonymousProfile = Profile.GetProfile(args.AnonymousID);

        //More Profile stuff and not even relevant to what I'm doing...
        //...and appears to be new fields you can add to the SimpleMembership Users table?
        //...and also related to the properties you add in your web.config which are also...
        //...not related to Identity.
        //Profile.ZipCode = anonymousProfile.ZipCode;
        //Profile.CityAndState = anonymousProfile.CityAndState;
        //Profile.StockSymbols = anonymousProfile.StockSymbols;

        ////////
        //// Delete the anonymous profile. If the anonymous ID is not 
        //// needed in the rest of the site, remove the anonymous cookie.
        //The ProfileManager line just hangs and barks about a network error...
        //...but there is no network error (without a doubt)...
        //...I have no idea what it would be deleting anyway.
        //ProfileManager.DeleteProfile(args.AnonymousID);
        //This is the only line that is successful and actually deletes the cookie.
        AnonymousIdentificationModule.ClearAnonymousIdentifier();

        //// Delete the user row that was created for the anonymous user.
        // Except that no user was written to any user rows...
        // ...Therefore, I didn't even bother trying this next line.
        //Membership.DeleteUser(args.AnonymousID, true);

    }

As you can see, only one line appears to work in that msdn example with Identity (...and in general, the cookie appears to not be related to Identity either.) The fact that I'm only getting a handful of search results for Profile_OnMigrateAnonymous and other items related to this, including international results, makes me think this wasn't a popular way of doing things? It also seems that SimpleMembership may have had anonymous users thought out a little more thoroughly? It actually appears anonymous users weren't thought of at all with Identity.

Community
  • 1
  • 1
Sum None
  • 2,164
  • 3
  • 27
  • 32

1 Answers1

0

Well... This is the best I could do without killing who knows how many more days. I won't mark it as the accepted answer as I don't really feel that it is. In the hopes of finishing this project sometime before I'm dead (since .NET is aging me ~1 year per day), I just had to take the neanderthal approach and step through this how it makes sense to me.

The first thing I did is create a unique constraint (no duplicates of the same two pieces of data in the same sql table ie. IncidentId and IUserId) on my table with this:

    CREATE UNIQUE NONCLUSTERED INDEX idx_incidentid_iuserid
    ON Likes(IncidentId, IUserId)

In my global.asax (that wasn't already there):

    ...
    using System.Web.Security;
    using Microsoft.AspNet.Identity;
    using ProjectSender.Models;
    ...
    ...
        public void Profile_OnMigrateAnonymous(object sender, ProfileMigrateEventArgs args)
        {
            ApplicationDbContext db = new ApplicationDbContext();
            var anonymousUser = args.AnonymousID;
            var identityUser = User.Identity.Name;
            var identityUserId = User.Identity.GetUserId();

            foreach (var item in db.Likes.Where(x => x.IUserId == anonymousUser).ToList())
            {
                //Try = Update anonymousId with identityUserId. 
                //Catch = Remove any duplicates caught by the exception/constraint
                try
                {
                    item.IUserId = identityUserId;
                    item.IUser = identityUser;
                    db.SaveChanges();
                }
                catch
                {
                    db.Likes.Remove(item);
                    db.SaveChanges();
                }
            }

            // Remove the anonymous cookie.
            AnonymousIdentificationModule.ClearAnonymousIdentifier();
        }
    ...

I think throwing an exception for that constraint is probably not the most performance conscience thing to do, but I just don't know any other way to perform that. There will only ever be a maximum of one duplicate record per IncidentId for that user, so it seems livable. However, I would love to know a better way.

Hope this helps some poor lost soul like myself. I would love to hear any other critiques, gotchas, recommendations, etc. Thanks.

Sum None
  • 2,164
  • 3
  • 27
  • 32