wcf - callbacks

wcf - callbacks

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


Curelom posted on Thursday, May 17, 2007

I have setup a remote Business Object that uses wcf to iis to update.  I also have a separate service to iis under the same domain that is setup for a callback.  The callback fires fine, but when I try doing a refresh of the business object, I get the following error.  I'm not sure what it means. Any ideas?

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.

 

RockfordLhotka replied on Friday, May 18, 2007

What are you trying to pass through your callback? A CSLA business object? Or FetchResult, which would contain a business object?

You can't do that without digging relatively deep into WCF. The WCF data portal channel may not look overly complex, but it does use a couple deep extensibility features of WCF to ensure that the correct serialization engine is used. If you don't do that, the default engine is used (DataContractSerializer) and it simply can't handle the kinds of object graphs used in a typical business model.

Curelom replied on Tuesday, May 22, 2007

I'm passing a simple string in the callback.  I noticed another thread having a similar problem.

http://forums.lhotka.net/forums/thread/14905.aspx

 

Curelom replied on Tuesday, May 22, 2007

A little more info, here is the interface of my callback

namespace Company.Helpdesk.Library.Wcf {

//The interface the serice exposes

[ServiceContract(Name = "WcfTicketService",

Namespace = "http://localhost/HelpDesk/services/WcfTicketService/",

SessionMode = SessionMode.Required,

CallbackContract = typeof(ITicketChangedCallback))]

public interface ITicketChangedPub {

[OperationContract(IsInitiating = true)]

void Subscribe(string id);

[OperationContract(IsTerminating = true)]

void Unsubscribe(string id);

[OperationContract(IsOneWay=false)]

int Count();

}

}

 

namespace Company.Helpdesk.Library.Wcf {

//The interface that clients must implement

public interface ITicketChangedCallback {

[OperationContract(IsOneWay = true)]

void TicketChanged(string id);

}

}

RockfordLhotka replied on Tuesday, May 22, 2007

I haven't done any callbacks, so I'm not going to be much help troubleshooting the specifics.

However, can you confirm that your DataPortal_XYZ code is running on the server before the failure? In other words, can you find out if the exception is occurring on the way to the server, or after execution is already there?

Curelom replied on Wednesday, May 23, 2007

I should have given these details up front.

I have a BusinessList object with a static method called GetUserActiveTicketList.

This businesslist object also implements the WcfTicketServiceCallback interface from the above post.

In the GetUserActiveTicketList method I fill a criteria object and call the dataportal fetch method.  Once the dataportal fetch has completed, I then hookup the callback to the other wcf service.  Right now, for testing purposes,  this callback webservice has a timer that fires the callback after 1 minute.  When the callback fires, I have the businesslist close the callback client, and fire an event.  The client application then calls the GetUserActiveTicketList again.  This is where it errors out.  If I call the GetUserActiveTicketList again, before the callback fires, it works fine.

 

RockfordLhotka replied on Wednesday, May 23, 2007

It is important to realize that the data portal is not designed with callbacks in mind. I would be VERY suspicious of anything that calls back to the client-side instance of a business object, because that object should be considered obsolete as soon as the data portal has been called.

 

Remember that the data portal clones the object across the wire, and then the server-side object is cloned back to the client and that new instance MUST replace the old instance on the client.

 

If you do a callback, you’d be calling back to the effectively dead and obsolete original object, which seems pointless, as that object should have been, or should be, discarded.

 

Rocky

 

 

From: Curelom [mailto:cslanet@lhotka.net]
Sent: Wednesday, May 23, 2007 9:52 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] wcf - callbacks

 

I should have given these details up front.

I have a BusinessList object with a static method called GetUserActiveTicketList.

This businesslist object also implements the WcfTicketServiceCallback interface from the above post.

In the GetUserActiveTicketList method I fill a criteria object and call the dataportal fetch method.  Once the dataportal fetch has completed, I then hookup the callback to the other wcf service.  Right now, for testing purposes,  this callback webservice has a timer that fires the callback after 1 minute.  When the callback fires, I have the businesslist close the callback client, and fire an event.  The client application then calls the GetUserActiveTicketList again.  This is where it errors out.  If I call the GetUserActiveTicketList again, before the callback fires, it works fine.

 



Curelom replied on Wednesday, May 23, 2007

Here is the code I am calling.  I am not putting the callback on the old list, but the newly created one.

public static TicketList GetUserActiveTicketList(string user) {

if (!CanGetObject())

throw new System.Security.SecurityException("User not authorized to view a TicketList");

TicketCriteria crit = new TicketCriteria(TicketQueryType.AssignedToStatus, "Open", user);

TicketList tl = DataPortal.Fetch<TicketList>(crit);

tl.hookupProxy();

return tl;

}

[NonSerialized()]

[NotUndoable()]

private WcfTicketServiceClient wcfClient;

public void hookupProxy() {

InstanceContext callback;

callback = new InstanceContext(this);

wcfClient = new WcfTicketServiceClient(callback);

wcfClient.Subscribe(this._dependencyId);

return;

}

Curelom replied on Thursday, May 31, 2007

I've figured out my problem.  I had to change the CslaDataPortalProxy over to web services before I was able to debug.  I was trying to access some resources that were not on the web server giving me null argument errors.  Once I cleaned this up, I was able to switch back to wcf and everthing seems to be working fine.

RockfordLhotka replied on Friday, June 01, 2007

Curelom:

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.

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...

Copyright (c) Marimer LLC