Внедрение пользовательской идентификации и 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, модель, Версия = 1.0.0.0, Культура = нейтральная, PublicKeyToken = NULL".

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

UPDATE: Я пробовал 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

Вот ссылка к статье, в которой более подробно описывается "Feature"


У меня была та же проблема. Я решил это, переместив мое основное создание из 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 и bang, я получил вышеприведенное сообщение.

licensed under cc by-sa 3.0 with attribution.