Реализация пользовательских идентификаторов и IPrincipal в MVC

У меня есть базовое бета-приложение MVC 2, где я пытаюсь реализовать пользовательские классы Identity и Principal.

Я создал свои классы, которые реализуют интерфейсы IIdentity и IPrincipal, создал их экземпляры, а затем назначил объект CustomPrincipal моему Context.User в Application_AuthenticateRequest из Global.asax.

Это все удается, и объекты выглядят хорошо. Когда я начинаю отображать представления, страницы теперь перестают работать. Первая ошибка в представлении LogoOnUserControl по умолчанию в следующей строке кода:

 [ <%= Html.ActionLink("Log Off", "LogOff", "Account") %> ]

Если я вытащу это, то произойдет сбой в другой строке кода "Html.ActionLink".

Я получаю ошибку:

Исключение типа "System.Runtime.Serialization.SerializationException" произошло в WebDev.WebHost40.dll, но не было обработано в коде пользователя

Дополнительная информация: Тип не разрешен для члена 'Model.Entities.UserIdentity,Model, Version=1.0.0.0, Culture= нейтральный, PublicKeyToken=null'.

Есть ли какие-то дополнительные свойства, которые мне нужно реализовать в моем удостоверении, чтобы использовать настраиваемое удостоверение в MVC? Я пытался реализовать [Serializable()] в классе Identity, но, похоже, это не дало результата.

ОБНОВЛЕНИЕ: я попробовал 3-4 альтернативных способа реализовать это, но все еще терпит неудачу с той же самой ошибкой. Если я использую классы GenericIdentity/GenericPrincipal напрямую, это не ошибка.

GenericIdentity ident = new GenericIdentity("jzxcvcx");
GenericPrincipal princ = new GenericPrincipal(ident, null);
Context.User = princ;

Но это ни к чему не приводит, так как я пытаюсь использовать CustomIdentity для хранения нескольких свойств. Если я реализую интерфейсы IIdentity/IPrincipal или унаследую GenericIdentity/GenericPrincipal для моего CustomIdentity/CustomPrincipal, произойдет сбой с исходной ошибкой выше.

3 ответа

Решение

Я понял это с небольшой помощью из Интернета:) Хитрость в том, что вам нужно реализовать интерфейс ISerializable в вашем классе, который реализует IIdentity. Я надеюсь, что это поможет сэкономить кому-то еще немного времени:)

Объявление класса:

[Serializable]
    public class ForumUserIdentity : IIdentity, ISerializable

Реализация для ISerializable:

#region ISerializable Members

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (context.State == StreamingContextStates.CrossAppDomain)
            {
                GenericIdentity gIdent = new GenericIdentity(this.Name, this.AuthenticationType);
                info.SetType(gIdent.GetType());

                System.Reflection.MemberInfo[] serializableMembers;
                object[] serializableValues;

                serializableMembers = FormatterServices.GetSerializableMembers(gIdent.GetType());
                serializableValues = FormatterServices.GetObjectData(gIdent, serializableMembers);

                for (int i = 0; i < serializableMembers.Length; i++)
                {
                    info.AddValue(serializableMembers[i].Name, serializableValues[i]);
                }
            }
            else
            {
                throw new InvalidOperationException("Serialization not supported");
            }
        }

        #endregion

Вот ссылка на статью, которая более подробно рассказывает о "Особенностях"

У меня такая же проблема. Я решил эту проблему, переместив мое основное создание из MvcApplication_AuthenticateRequest в MvcApplication_PostAuthenticateRequest. Я не знаю, почему / как, но это решило проблему:)

        void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e)
    {
        HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
        if (authCookie != null)
        {
            string encTicket = authCookie.Value;
            if (!String.IsNullOrEmpty(encTicket))
            {
                FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(encTicket);
                BiamedIdentity id = new BiamedIdentity(ticket);
                GenericPrincipal prin = new GenericPrincipal(id, null);
                HttpContext.Current.User = prin;
            }
        }
    }

Со мной это работает, когда я наследую свой класс Identity от MarshalByRefObject,

Также обратите внимание: при использовании Linq-to-Sql проблем не было. Я переключился на Entity-Framework и взрыва, я получил вышеупомянутое сообщение.

Другие вопросы по тегам