ASP.NET 2.0 Membership Service with remote Data Portal

ASP.NET 2.0 Membership Service with remote Data Portal

Old forum URL: forums.lhotka.net/forums/t/1453.aspx


MaciejN posted on Wednesday, October 11, 2006

Hello everyone!

I am developing a C# web app which uses the ASP.NET 2.0 membership features for authentication. I have read p536-537 regarding what is needed for this solution to work but nevertheless still get this error when trying to "get" an object:

System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.ArgumentException: Object of type 'System.Runtime.Serialization.TypeLoadExceptionHolder' cannot be converted to type 'System.Security.Principal.IPrincipal'.

I have already created the MembershipPrincipal object and added it to my .Library porject.

I have two aspx pages to my app. login.aspx and default.aspx. The book also says that I should put the following in my global.asax AcquireRequestState event:

Csla.ApplicationContext.User = new MIHS.Web.Portal.Library.MembershipPrincipal(HttpContext.Current.User);

After I have successfully logged in I call my object like so

Client _Client = Client.GetClient(Guid.Empty, Context.Items["MIHSPortal_ApplicationName"].ToString());

and get the error above.

If anyone can help I would appreciate it. I am confused a bit since I think I have done everything correctly.

Specifically:

1. Must I use the <add key="CslaAuthentication" value="Csla" /> entry in the various config files since I am not using CSLA authentication?

Thanks.

Maciej

RockfordLhotka replied on Wednesday, October 11, 2006

Yes, you must set CslaAuthentication to Csla unless you are using Windows integrated authentication. Since you are using non-Windows authentication then this is required.

The data portal has one, very simple, requirement: the principal object must derive from Csla.Security.BusinessPrincpalBase. That's all it cares about.

So as long as you are certain that the client code (running in the web server) has HttpContext.Current.User set to something that derives from BusinessPrincipalBase then you should be good.

MaciejN replied on Thursday, October 12, 2006

Smile [:)]Rocky,

Thanks for the quick reply. Your reply makes sense to me and that is why I don't understand why I am receiving the error. Here is my MembershipPrincipal class:

using System;
using System.Collections.Generic;
using System.Text;

namespace MIHS.Web.Portal.Library
{
    [Serializable()]
    public class MembershipPrincipal : Csla.Security.BusinessPrincipalBase
    {
        private System.Security.Principal.IPrincipal _principal;

        public MembershipPrincipal(System.Security.Principal.IPrincipal principal) : base(principal.Identity)
        {
            _principal = principal;
        }

        public override bool IsInRole(string role)
        {
            return _principal.IsInRole(role);
        }
    }
}

Does this look good to you?

Here is the exact location of the exception in WebServicesProxy.cs:

    public Server.DataPortalResult Fetch(
      Type objectType, object criteria, Server.DataPortalContext context)
    {
      object result;
      Server.Hosts.WebServicePortal.FetchRequest request =
        new Server.Hosts.WebServicePortal.FetchRequest();
      request.ObjectType = objectType;
      request.Criteria = criteria;
      request.Context = context;

      using (WebServiceHost.WebServicePortal wsvc = GetPortal())
      {
       
result = Deserialize(wsvc.Fetch(Serialize(request)));
      }

      if (result is Exception)
        throw (Exception)result;
      return (Server.DataPortalResult)result;
    }

I am using CSLA 2.0.3.

Maciej

RockfordLhotka replied on Thursday, October 12, 2006

Perhaps the ASP.NET membership principal object isn't serializable - or perhaps it tries to do some automated work when it is being deserialized.

I did try wrapping the membership principal as I discuss in the book - but to be honest, I never did try to pass it through the data portal.

The exception you are getting doesn't, on the surface, seem to make any sense. Some code in that process is obviously trying to set the principal or cast to a principal, and that's failing. So you need to determine what code, during deserialization, is somehow trying to do that work - either your code, or (hopefully not) some code in the membership principal.

MaciejN replied on Thursday, October 12, 2006

I havn't modified your CSLA code in any way. I am just consuming it.

I have two lines of code:

Csla.ApplicationContext.User = new MIHS.Web.Portal.Library.MembershipPrincipal(HttpContext.Current.User);

This does not produce an error and:

Client _Client = Client.GetClient(Guid.Empty, Context.Items["MIHSPortal_ApplicationName"].ToString());

which does.

The Client object is just an object that inherits from BusinessBase and is located in the Library.

I am trying to mimic the PTWeb application except for trying to use ASP Membership and remote data portal.

Is their anything else I can do to help?

RockfordLhotka replied on Thursday, October 12, 2006

Are you using a remote data portal (application server), or are you running the data portal in local mode?

MaciejN replied on Thursday, October 12, 2006

I would like to use the remote data portal configuration. Specifically so all data access is done from the library running on another physical server and using WebServicesHost as my transport.

Here is are my CSLA web.config items:

  <add key="CslaAuthentication" value="Csla" />
  <add key="CslaDataPortalProxy" value="Csla.DataPortalClient.WebServicesProxy, Csla"/>
  <add key="CslaDataPortalUrl" value="http://someserver/MIHS.Web.Portal.WebServiceHost/CslaDataPortal.asmx"/>

I'm not sure if I need anything else.

MaciejN replied on Wednesday, October 18, 2006

Rocky,

I'm sure your very busy and I appreciate your time, but I would like to know your thoughts on this issue. Do you think this is an issue with CSLA or do you feel its my implementation.

Maciej

RockfordLhotka replied on Wednesday, October 18, 2006

As I mentioned earlier, I've never tried passing the ASP.NET membership principal across the data portal - so I have no idea if it can be done.
 
If I were you, what I'd do is try to clone the object (see the Clone() implementation in Chapter 3 and base your code off that) to force serialization/deserialization of the object without all the complexity of a network. See if that works or fails - and it might just fail right there if they are doing something wonky on deserialization.
 
If that _works_, then you'll have to troubleshoot it across the network.
 
Given the exception you are seeing, I am guessing it does have something to do with deserializing the membership provider.
 
Though to ensure it isn't some other problem, perhaps the FIRST thing you should do is get your code working with a regular custom principal - one that doesn't contain a membership principal - and make sure your code works from end to end. That would eliminate that possibility.
 
So in short, no, I don't think this is a CSLA issue. I think it is either an issue with your code or with some implementation detail of the membership principal that is triggered on deserialization.
 
Rocky


From: MaciejN [mailto:cslanet@lhotka.net]
Sent: Wednesday, October 18, 2006 1:57 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] ASP.NET 2.0 Membership Service with remote Data Portal

Rocky,

I'm sure your very busy and I appreciate your time, but I would like to know your thoughts on this issue. Do you think this is an issue with CSLA or do you feel its my implementation.

Maciej




MaciejN replied on Wednesday, October 18, 2006

Thank you for your quick and concise reply. I will attempt to do as you suggest.

Maciej

Copyright (c) Marimer LLC