In my ASP.NET mvc app, I wrote my own custom IIdentity which I swap with the default FORMS identity. I do this using Application_PostAuthenticateRequest in Global.asax. This works for the most part as it gives me a more meaningful identity prior to invoking
actions on my MVC controller. Unforunately, things fall apart after the controller call. Something in the ASP.NET framework is bound and determined to serialize my identity and blows up during this process. I even made my custom identity serializable
but it still blows up. Note, I can serialize / deserialize this class in a unit test using the binary formatter.
After much weeping and nashing of teeth, I got it to work. When you inject your identity into the asp.net pipeline, for some reason your custom identity assembly must be strong named and present in the GAC to work correctly.
I've noticed that this issue only exists if you use the built-in Visual Studio Development Server. If you configure your web application project to use Local IIS Web server everything works fine.
It seems like there is a relation between the Visual Studio Development Server and Cassini? Can anyone confirm that? The following post tells a bit further what actually causes the issue:
skmcfadden
Member
35 Points
97 Posts
Custom identity problem / SerializationException: Type is not resolved for member
Sep 10, 2009 10:13 PM|LINK
In my ASP.NET mvc app, I wrote my own custom IIdentity which I swap with the default FORMS identity. I do this using Application_PostAuthenticateRequest in Global.asax. This works for the most part as it gives me a more meaningful identity prior to invoking actions on my MVC controller. Unforunately, things fall apart after the controller call. Something in the ASP.NET framework is bound and determined to serialize my identity and blows up during this process. I even made my custom identity serializable but it still blows up. Note, I can serialize / deserialize this class in a unit test using the binary formatter.
Here is the exception:
[SerializationException: Type is not resolved for member 'MvcTest.Models.SiteUser,MvcTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.] Microsoft.VisualStudio.WebHost.Server.GetProcessToken() +0 Microsoft.VisualStudio.WebHost.Host.GetProcessToken() +87 Microsoft.VisualStudio.WebHost.Request.GetUserToken() +35 Microsoft.VisualStudio.WebHost.Request.GetServerVariable(String name) +202 System.Web.HttpRequest.AddServerVariableToCollection(String name) +25 System.Web.HttpRequest.FillInServerVariablesCollection() +188 System.Web.HttpServerVarsCollection.Populate() +34 System.Web.HttpServerVarsCollection.Get(String name) +8633063 System.Collections.Specialized.NameValueCollection.get_Item(String name) +7 System.Web.Mvc.PathHelpers.GenerateClientUrlInternal(HttpContextBase httpContext, String contentPath) +274 System.Web.Mvc.PathHelpers.GenerateClientUrl(HttpContextBase httpContext, String contentPath) +63 System.Web.Mvc.UrlHelper.GenerateUrl(String routeName, String actionName, String controllerName, RouteValueDictionary routeValues, RouteCollection routeCollection, RequestContext requestContext, Boolean includeImplicitMvcValues) +183 System.Web.Mvc.UrlHelper.GenerateUrl(String routeName, String actionName, String controllerName, String protocol, String hostName, String fragment, RouteValueDictionary routeValues, RouteCollection routeCollection, RequestContext requestContext, Boolean includeImplicitMvcValues) +36 System.Web.Mvc.HtmlHelper.GenerateLinkInternal(RequestContext requestContext, RouteCollection routeCollection, String linkText, String routeName, String actionName, String controllerName, String protocol, String hostName, String fragment, RouteValueDictionary routeValues, IDictionary`2 htmlAttributes, Boolean includeImplicitMvcValues) +41 System.Web.Mvc.HtmlHelper.GenerateLink(RequestContext requestContext, RouteCollection routeCollection, String linkText, String routeName, String actionName, String controllerName, String protocol, String hostName, String fragment, RouteValueDictionary routeValues, IDictionary`2 htmlAttributes) +36 System.Web.Mvc.HtmlHelper.GenerateLink(RequestContext requestContext, RouteCollection routeCollection, String linkText, String routeName, String actionName, String controllerName, RouteValueDictionary routeValues, IDictionary`2 htmlAttributes) +31 System.Web.Mvc.Html.LinkExtensions.ActionLink(HtmlHelper htmlHelper, String linkText, String actionName, String controllerName, RouteValueDictionary routeValues, IDictionary`2 htmlAttributes) +72 System.Web.Mvc.Html.LinkExtensions.ActionLink(HtmlHelper htmlHelper, String linkText, String actionName, String controllerName) +103 ASP.views_shared_site_master.__Render__control1(HtmlTextWriter __w, Control parameterContainer) in c:\dev\CSharp\MvcTest\App\Views\Shared\Site.Master:25 System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +256 System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +19 System.Web.UI.Control.Render(HtmlTextWriter writer) +10 System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27 System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99 System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25 System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +134 System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +19 System.Web.UI.Page.Render(HtmlTextWriter writer) +29 System.Web.Mvc.ViewPage.Render(HtmlTextWriter writer) +59 System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27 System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99 System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1266
Here is how I inject my custom identity (global.asax)
protected void Application_PostAuthenticateRequest(object sender, EventArgs args)
{
if (Context.User != null)
{
if (Context.User.Identity.IsAuthenticated)
{
UserHelper ca = new UserHelper();
SiteUser user = ca.UserFromCookie(Context);
System.Threading.Thread.CurrentPrincipal = new GenericPrincipal(user, null);
return;
}
}
}
(web.config)
<compilation debug="true">
<assemblies>
<add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Web.Abstractions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Data.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Security, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
<add assembly="MvcTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</assemblies>
</compilation>
<!--
The <authentication> section enables configuration
of the security authentication mode used by
ASP.NET to identify an incoming user.
-->
<authentication mode="Forms">
<forms loginUrl="/authenticator/login" timeout="2880"/>
</authentication>
<membership>
<providers>
<clear/>
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ApplicationServices" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" applicationName="/"/>
</providers>
</membership>
<profile>
<providers>
<clear/>
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ApplicationServices" applicationName="/"/>
</providers>
</profile>
<roleManager enabled="false">
<providers>
<clear/>
<add connectionStringName="ApplicationServices" applicationName="/" name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
<add applicationName="/" name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
</providers>
</roleManager>
Any one else experienced this problem?
<div style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;" id="_mcePaste">protected void Application_PostAuthenticateRequest(object sender, EventArgs args)</div> <div style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;" id="_mcePaste"> {</div> <div style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;" id="_mcePaste"> if (Context.User != null)</div> <div style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;" id="_mcePaste"> {</div> <div style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;" id="_mcePaste"> if (Context.User.Identity.IsAuthenticated)</div> <div style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;" id="_mcePaste"> {</div> <div style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;" id="_mcePaste"> UserHelper ca = new UserHelper();</div> <div style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;" id="_mcePaste"> SiteUser user = ca.UserFromCookie(Context); </div> <div style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;" id="_mcePaste"> </div> <div style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;" id="_mcePaste"> System.Threading.Thread.CurrentPrincipal = new GenericPrincipal(user, null);</div> <div style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;" id="_mcePaste"> return;</div> <div style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;" id="_mcePaste"> }</div> <div style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;" id="_mcePaste"> } </div> <div style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;" id="_mcePaste"> }</div>custom identity SerializationException
skmcfadden
Member
35 Points
97 Posts
Re: Custom identity problem / SerializationException: Type is not resolved for member
Sep 13, 2009 04:25 PM|LINK
After much weeping and nashing of teeth, I got it to work. When you inject your identity into the asp.net pipeline, for some reason your custom identity assembly must be strong named and present in the GAC to work correctly.
Maybe someone can tell us why this is.
SerializationException custom identity
Michael Ulma...
Member
4 Points
3 Posts
Re: Custom identity problem / SerializationException: Type is not resolved for member
Feb 10, 2010 06:33 AM|LINK
I've noticed that this issue only exists if you use the built-in Visual Studio Development Server. If you configure your web application project to use Local IIS Web server everything works fine.
It seems like there is a relation between the Visual Studio Development Server and Cassini? Can anyone confirm that? The following post tells a bit further what actually causes the issue:
http://www.lhotka.net/weblog/CommentView,guid,cfcaf6c4-63cf-4cf1-8361-ed3db07496a4.aspx
baggadonuts
Member
5 Points
12 Posts
Re: Custom identity problem / SerializationException: Type is not resolved for member
Jun 28, 2012 09:13 PM|LINK
Adding it to the GAC is a horrible way to go about it.
To Fix it, do the following:
/// <summary> /// Stubs identity for offline authentication /// </summary> [Serializable] public class StubIdentity : IIdentity, ISerializable...
Implement the ISerializable interface:
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"); } }custom identity SerializationException