Good day to all!
I am using Beta 1 (and the previous test version) of CSLA 3.0 to grok the WcfPortal. I got Project Tracker working with the WcfPortal without any trouble. Great!
When I went to use this same CSLA functionality with my own business objects, I ran into a problem I have not been able to resolve. I added a reference to my business objects to the WcfPortal project and had my client access this portal via app.config. These business objects work fine when using the SimpleDataPortal.
When I call the Save(false) method on my ERO, I get an exception stating: "The underlying connection was closed: The connection was closed unexpectedly."
These business objects work fine when using the SimpleDataPortal within the same test app that I am using here.
When I turn logging on for the WcfPortal, I find the following in the log file after running my test:
"<ExceptionString>System.ServiceModel.CommunicationException: There was an error while trying to serialize parameter http://ws.lhotka.net/WcfDataPortal:UpdateResult. The InnerException message was 'Enum value '0' is invalid for type 'System.Security.Permissions.SecurityAction' and cannot be serialized. Ensure that the necessary enum values are present and are marked with EnumMemberAttribute attribute if the type has DataContractAttribute attribute.'. Please see InnerException for more details. System.Runtime.Serialization.SerializationException: Enum value '0' is invalid for type 'System.Security.Permissions.SecurityAction' and cannot be serialized. Ensure that the necessary enum values are present and are marked with EnumMemberAttribute attribute if the type has DataContractAttribute attribute."
I have looked at everything that I can think of to see any difference between my business objects (which are generated with a code generator) and the ProjectTracker business objects. I have yet to find anything that lead to a solution to this problem. Since the ProjectTracker objects work fine with WcfPortal, it must be something with the business object code that I am using, but what...? So any help here would be much appreciated.
I have tried to be brief here. If you need more info, just ask...
BTW, are there any specific instructions somewhere for setting up a WCF project in VS2005 for use as a WcfPortal for CSLA objects? I would imagine that it would be pretty much the same as the instructions for remoting on pg. 611 of the VB 2005 Business Objects book. I have also checked out http://www.lhotka.net/files/csla20/BuildCsla.pdf but it appears to be just CSLA 2.0. But I wonder if there is just something that I am missing here.
Best regards--
David Lutz
I can confirm that the BOs work fine with remoting. After adding a reference to my BOs in your remoting server, making the necessary config changes and working out the security principal, I was able to get my test app to create and save the business objects to the database using the remoting server.
One other thing I discovered after writing the first post: once a reference these business objects were added to your WcfHost project, not even ProjectTracker would work. A similarly worded error happened when trying to retrieve a project. Once the references were removed, ProjectTracker worked fine.
Best regards --
David Lutz
I can now add some additional info to this thread:
Once the BusinessPrincipal was implemented in my test app, the remoting test worked. However, I had to hack the class implementing the IIdentity interface to get around and error that returned: "Principal must be of type BusinessPrincipal, not System.Security.Principal.GenericPrincipal" when calling the GetIdentity method which called DataPortal.Fetch. ProjectTracker does not have this problem and calls the remoting server even though a BusinessPrincipal has not been created. I would someday like to understand this better, but for now I just hacked my way around this problem.
My hack was to create a constructor that took a name and set IsAuthenicated to True. So now I call this constructor and use the result to set the Csla.ApplicationContext.User. Once this is done the saving of these objects via the remoting server works. The same applies to the WCF Host.
I hope this provides some clarification to this ongoing situation.
Best regards --
David Lutz
dlutz52:My hack was to create a constructor that took a name and set IsAuthenicated to True. So now I call this constructor and use the result to set the Csla.ApplicationContext.User. Once this is done the saving of these objects via the remoting server works. The same applies to the WCF Host.
This is close to what you should do, but not quite. You need to implement a static/Shared Logout() method on your principal, that sets the current principal to an unauthenticated instance of your custom principal.
This is discussed in the book, and you'll notice that all three interfaces in ProjectTracker make sure to do a Logout() before any attempt at calling the data portal.
But in any case, this is a valuable clue to what's going on with the WcfProxy. I think that at least one server-side exception class (probably a WCF one) isn't serializable. I'll have to dig into that a bit - because what I think is happening is that an exception occurs on the server, and my code tries to pack up the server-side stack trace to return it to the client. That requires serializing the exception stack, and that appears to be what's failing.
Rocky/Andres --
Calling the Logout() method fixed everything - for both remoting and WCF. Lesson learned. Funny how you can read something in a book and not grok the full significance of what one has read, later yet remember it when you need it.
I thank you both for the help. I hope that this exercise has been helpful in spite of the fact that it arises out of the actions of a fumbling newbie - a fact that will change with time.
Best regards --
David
dlutz52:"<ExceptionString>System.ServiceModel.CommunicationException: There was an error while trying to serialize parameter http://ws.lhotka.net/WcfDataPortal:UpdateResult. The InnerException message was 'Enum value '0' is invalid for type 'System.Security.Permissions.SecurityAction' and cannot be serialized. Ensure that the necessary enum values are present and are marked with EnumMemberAttribute attribute if the type has DataContractAttribute attribute.'. Please see InnerException for more details. System.Runtime.Serialization.SerializationException: Enum value '0' is invalid for type 'System.Security.Permissions.SecurityAction' and cannot be serialized. Ensure that the necessary enum values are present and are marked with EnumMemberAttribute attribute if the type has DataContractAttribute attribute."
OK, I have isolated this issue. It appears to be a bug in the NetDataContractSerializer (the WCF replacement for the BinaryFormatter). As such, it is not at all clear to me that there's a fix or workaround short of Microsoft addressing the problem.
http://www.lhotka.net/weblog/WCFNetDataContractSerializerAndSecurityException.aspx
I haven't quite given up on a workaround yet, but it is hard to see any good solution I can provide...
Rocky, have you found any solution to this issue? I'm having the same problem, but only with certain BO, and only in our production environment, and only if trying to remote from a non-development machine. Any ideas?
http://forums.lhotka.net/forums/24987/ShowThread.aspx#24987
Yes, this was fixed in some point release (3.0.x) - it turns out that extra initialization of the SecurityException is required for it to serialize safely through the NDCS. So the issue should be resolved, unless one of the following is true:
I honestly don’t remember – it was months ago I
researched this :(
Some extra property needs to be set manually on the object if I
remember right.
I just looked at the CSLA code – it is the Action property
that must be explicitly set after the SecurityException object has been
created.
Rocky
From: dlabar
[mailto:cslanet@lhotka.net]
Sent: Sunday, July 27, 2008 1:35 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] Difficulties using WcfPortal in Beta 1
I'm running version 3.0.3, should I try upgrading to
3.5.0? I guess I could be throwing a security Exception myself (option
number 1). What is required to "fully initialize" it?
I honestly don’t remember – it was months ago I
researched this :(
Some extra property needs to be set manually on the object if I
remember right.
I just looked at the CSLA code – it is the Action property
that must be explicitly set after the SecurityException object has been
created.
Rocky
From: dlabar
[mailto:cslanet@lhotka.net]
Sent: Sunday, July 27, 2008 1:35 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] Difficulties using WcfPortal in Beta 1
I'm running version 3.0.3, should I try upgrading to
3.5.0? I guess I could be throwing a security Exception myself (option
number 1). What is required to "fully initialize" it?
System.Security.Permissions.SecurityAction
it is set to?
System.Security.Permissions.SecurityAction
I don’t know for sure…
From: dlabar
[mailto:cslanet@lhotka.net]
Sent: Sunday, July 27, 2008 1:49 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] RE: Difficulties using WcfPortal in Beta 1
Does it matter what
System.Security.Permissions.SecurityAction
it is set to?
System.Security.Permissions.SecurityAction
In answer to my own question... I'm going to guess not. I'm going to guess that the System.Security.SecurityException.Action enum is defaulted to a value of 0, which is not valid. I'm going to inherit from that class, and give it a default enum value, so that way I don't have to worry about it again.
Thanks a ton Rocky!
Sorry for all, sorry for replying in such an old thread. But i bumped into this issue as well since i'm doing Windows authentication and my AuthenticationType should be "Windows", but we are using csla objects in windows workflow foundation activity's in the designer of visual studio. During metadata execution there is no config for visual studio so ConfigurationManager.AppSettings["CslaAuthentication"] returns null and the authentication type is set to "Csla".
Too bad the ApplicationContext.AuthenticationType cannot be set in code (without modifying or reflection)
On topic:
Because we are using windows authentication and the authentication type is set to csla, the principal is assigned so there is an security exception raised in the server DataPortal without a Action (it's slashed away)
The exception cannot be serialized so the following exception is visible
There was an error while trying to serialize parameter http://ws.lhotka.net/WcfDataPortal:FetchResult. The InnerException message was 'Enum value '0' is invalid for type 'System.Security.Permissions.SecurityAction' and cannot be serialized. Ensure that the necessary enum values are present and are marked with EnumMemberAttribute attribute if the type has DataContractAttribute attribute.'. Please see InnerException for more details.
The code responsible:
if (ApplicationContext.AuthenticationType == "Windows") { // When using integrated security, Principal must be null if (context.Principal != null) { System.Security.SecurityException ex = new System.Security.SecurityException(Resources.NoPrincipalAllowedException); //ex.Action = System.Security.Permissions.SecurityAction.Deny; throw ex; } // Set .NET to use integrated security AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal); }
That code hasn't changed since we fixed the original issue a few years ago. I wonder if something changed with .NET since that time...
It appears we may have to entirely abandon the use of SecurityException - a breaking change, but one that may be necessary.
I've just come across the same problem which caused me to spend a couple days researching. It turns out the problem was simply that I forgot to put
<add key="CslaAuthentication" value="Windows" />
In my WcfPortal web.config file. But since the SecurityException wouldn't serialize, I had no clue what was going on.
I uncommented out the following line
//ex.Action = System.Security.Permissions.SecurityAction.Deny;
and tried again and the SecurityException was properly serialized and pointed me in the right direction, which is what it is supposed to do.
Presumably, this line was commented out because the enum 'Deny' is deprecated. However, it still works just fine. I recommend putting this line back in with the Deny value or putting it back in with the appropriate non-deprecated value (although I don't claim to know what is appropriate, I don't think it really matters).
Copyright (c) Marimer LLC