1

I am implementing ASP.NET Identity in a system where used authentication with a User Model with Entity Framework and being controlled in WebApp by Session (yes it is a legacy system into web forms), we implemented, replaced the User model by ApplicationUser of Identity, everything working OK.

The problem is, there is a notification system, which is basically a Many to Many relationship between a Notification and User Model, these notifications are saved in SQL Server along with the rest of the system, but are also in a Cache Redis for faster reading and needs to be serialized for writing on it. We remove the User model, then added an ICollection of ApplicationUser in the Notification model and vice versa - making the relate between both.

But ApplicationUser inherits from IdentityUser, and even adding the annotation [Serializable] I get the exception:

Type 'Microsoft.AspNet.Identity.EntityFramework.IdentityUser' the assembly 'Microsoft.AspNet.Identity.EntityFramework, Version = 2.0.0.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35' is not marked as serializable

My question is, is there any way to serialize this? Or I will have to create another user model only to relate with notifications model?

ApplicationUser Model

[Serializable]
public class ApplicationUser : IdentityUser
{
    public ApplicationUser()
    {
        this.Notificacoes = new List<Notificacao>();
    }

    public ClaimsIdentity GenerateUserIdentity(IdentityConfig.ApplicationUserManager manager)
    {
        var userIdentity = manager.CreateIdentity(this, DefaultAuthenticationTypes.ApplicationCookie);
        return userIdentity;
    }

    public Task<ClaimsIdentity> GenerateUserIdentityAsync(IdentityConfig.ApplicationUserManager manager)
    {
        return Task.FromResult(GenerateUserIdentity(manager));
    }
    public bool ReceiveNotifications { get; set; }
    public int Permission { get; set; }
    public virtual ICollection<Notificacao> Notificacoes { get; set; }
}

Notification Model

[Serializable]
public partial class Notificacao
{
    public Notificacao()
    {
        this.Usuarios = new List<ApplicationUser>();
    }

    public int Codigo { get; set; }
    public string Mensagem { get; set; }
    public DateTime DataHoraNotificacao { get; set; }
    public int Tipo { get; set; }
    public virtual ICollection<ApplicationUser> Usuarios { get; set; }

}

Serialize Method used to Serialize a object to Redis (where it throws the exception)

static byte[] Serialize(object o)
{
    if (o == null)
    {
        return null;
    }

    BinaryFormatter binaryFormatter = new BinaryFormatter();
    using (MemoryStream memoryStream = new MemoryStream())
    {
        binaryFormatter.Serialize(memoryStream, o);
        byte[] objectDataAsStream = memoryStream.ToArray();
        return objectDataAsStream;
    }
}
Brendan Green
  • 11,676
  • 5
  • 44
  • 76
  • It is not marked as Serializable, you can look at the source code: https://aspnetidentity.codeplex.com/SourceControl/latest#src/Microsoft.AspNet.Identity.EntityFramework/IdentityUser.cs – Liviu Costea Sep 18 '15 at 07:14
  • hmm I see, well, I will do decyclone suggestion, thanks! – feliperochadev Sep 18 '15 at 17:32

2 Answers2

1

As you have no control over the assemly containing the IdentityUser class this cannot be done. An alternative solution could be to map your object to Dto's (data transfer objects) before caching, and the other way around upon fetching.

Other topics on the subject (related to WCF but still involves serializing IdentityUser):

asp-net-mvc-5-identityuser-in-wcf

how-do-i-serialize-an-identityuser-reference-in-web-api-2-2

Community
  • 1
  • 1
Indregaard
  • 1,195
  • 1
  • 18
  • 26
1

You don't want to serialize IdentityUser or any of it's sub-classes to the database. Period.

If you need to maintain relationships in database, create a POCO (Plain Old CLR Object - In simple words, a custom class).

Also, if you need to carry around IdentityUser in your user class, use composition instead of inheritance. Which means, don't inherit from IdentityUser but create a property of it in your class. And mark that property as NonSerializable.

decyclone
  • 30,394
  • 6
  • 63
  • 80