This behavior was actually done so by design. The main
reason was that you can send multiple requests at the same time due to
asynchronous nature of SilverLight, thus there would never be any guaranty that
you global context from one call would not be overwritten from another asynchronous
call before you have a chance to check it. So, instead of resetting
global context every time it is exposed on a property (as you correctly
noticed) to allow you do any post-call manipulations with it.
Asynchronous data portal in .NET behaves the same way incidentally – it also
does not overwrite global context.
Sergey Barskiy
Principal Consultant
office: 678.405.0687 |
mobile: 404.388.1899
Microsoft Worldwide Partner of the Year | Custom
Development Solutions, Technical Innovation
From: paupdb
[mailto:cslanet@lhotka.net]
Sent: Friday, August 29, 2008 8:08 AM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] Csla Light - Couple of questions/issues to
report
Some more behavior I think may be buggy in
Csla.DataPortalClient.WcfProxy<T> (in cslalightcs sln):
As part of a Fetch on one of my business objects, I am setting a value into the
ApplicationContext.GlobalContext on the server side (i.e. in the BO
DataPortal_Fetch).
I expect that value to then be visible in the Silverlight GlobalContext when
the Fetch callback method fires. However it isn't :(
Now my understanding of the GlobalContext is that it should be the same on both
client and server side, since it is serialised both ways with every request.
I've done some debugging, and I found that the server GlobalContext is indeed
coming back from the server through the WcfProxy, however it is never set onto
the SL client side ApplicationContext.GlobalContext.
Instead the globalcontext received from the server side is deserialised and
assigned to property _globalContext on the WcfProxy<T>.
Interestingly, I can access this globalcontext property from the sender object
o.GlobalContext parameter in my callback (and hence see the server side value I
set on the GlobalContext).
But obviously, having to manually then set that into Silverlight client ApplicationContext.GlobalContext
seems a little manual to me.
Surely the ApplicationContext.GlobalContext should be set according to what is
deserialised on both the server and client side?
For reference - an example of the _globalContext being set from the FetchCompleted
method of WcfProxy (the same setting happens in all the other *Completed
methods):
private void proxy_FetchCompleted(object sender,
Csla.WcfPortal.FetchCompletedEventArgs e)
{
try
{
if (e.Error == null &&
e.Result.ErrorData == null)
{
var buffer = new
System.IO.MemoryStream(e.Result.ObjectData);
var formatter = new
MobileFormatter();
T obj =
(T)formatter.Deserialize(buffer);
_globalContext =
(ContextDictionary)MobileFormatter.Deserialize(e.Result.GlobalContext);
OnFetchCompleted(new
DataPortalResult<T>(obj, null, e.UserState));
Thanks for your feedback, Paul.
We added paremeter-less constructor to SingleCriteria. You
should be set to go.
Sergey Barskiy
Principal Consultant
office: 678.405.0687 |
mobile: 404.388.1899
Magenic ®
Microsoft Worldwide Partner of the Year | Custom
Development Solutions, Technical Innovation
From: paupdb
[mailto:cslanet@lhotka.net]
Sent: Saturday, August 30, 2008 12:04 AM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] RE: Csla Light - Couple of questions/issues to
report
Sergey,
Thanks for the feedback. I understand what you mean in terms of the
GlobalContext design - maintaining consistent client state in the midst of
asynchronous calls is tricky.
I can access the GlobalContext property, so thats no major issue :)
Glad to see the other items I reported have been resolved as well :)
Any chance of that protected parameterless constructor on the SingleCriteria
(reported in my second post above)?
You should thank Rocky – it was his decision.
Sergey Barskiy
Principal Consultant
office: 678.405.0687 |
mobile: 404.388.1899
Magenic ®
Microsoft Worldwide Partner of the Year | Custom
Development Solutions, Technical Innovation
From: paupdb
[mailto:cslanet@lhotka.net]
Sent: Sunday, August 31, 2008 7:00 PM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] RE: RE: Csla Light - Couple of questions/issues
to report
You the man Sergey :D
Thank you for your comments, first of all.
One the first issue, protected get has been added to CslaIdentity.Roles
On the second issue, this is a bug, and it has been fixed.
Sergey Barskiy
Principal Consultant
office: 678.405.0687 |
mobile: 404.388.1899
Microsoft Worldwide Partner of the Year | Custom
Development Solutions, Technical Innovation
From: paupdb
[mailto:cslanet@lhotka.net]
Sent: Thursday, August 28, 2008 8:11 AM
To: Sergey Barskiy
Subject: [CSLA .NET] Csla Light - Couple of questions/issues to report
I've got a few suggestions that I'd like to run by Rocky and
the other Magenic guys regarding CSLA Light.
I'm basing these questions on using the latest 3.6 source code straight out of
Subversion (svn://svn.lhotka.net/csla/).
First question: Csla.Security.CslaIdentity
I'm currently subclassing the above to have my own custom Identity, but one
thing that irritating is the RolesProperty.
Currently the RolesProperty PropertyInfo field is private in CslaIdentity, and
the protected property Roles has no getter.
The problem is that I want to be able to get the Roles list out of the Identity
in some special circumstances.
Any chance you can either make the RolesProperty protected in CslaIdentity, or
else provide a getter on the Roles property?
If not, I guess I'll just make a copy of CslaIdentity instead of subclass.
Second question: WcfPortalClient and ServiceReferences.ClientConfig
The application I'm building will be deployed at many client sites, and as such
the urls relating to the website will be different each time. Now having
to configure the endpoint address in the web.config is fine, but the
ServiceReferences.ClientConfig side is embedded in the Silverlight xap file.
Having to unzip the file, update the ServiceReferences.ClientConfig, and rezip
the xap is something I want to avoid.
So what I've done is programatically set the WcfProxy.DefaultUrl and
WcfProxy.DefaultBinding properties on startup of my Silverlight app:
//Csla settings - note it is assumed that
WcfPortal.svc exists in web application root
string pageUrl =
HtmlPage.Document.DocumentUri.AbsoluteUri;
string appRootUrl = pageUrl.Substring(0,
pageUrl.LastIndexOf('/') + 1);
ApplicationContext.GlobalContext["AppRootUrl"] = appRootUrl;
//Set up WcfProxy DataPortal service
Csla.DataPortalClient.WcfProxy.DefaultUrl =
appRootUrl + "WcfPortal.svc";
//Set WCF message size to support large
resultsets
System.ServiceModel.BasicHttpBinding
largeBinding = new System.ServiceModel.BasicHttpBinding();
largeBinding.MaxReceivedMessageSize = 32000000;
largeBinding.MaxBufferSize
= 32000000;
Csla.DataPortalClient.WcfProxy.DefaultBinding =
largeBinding;
Csla.DataPortal.ProxyTypeName =
"Csla.DataPortalClient.WcfProxy, Csla";
I also went so far as to comment out the endpoint configuration in my
ServiceReferences.ClientConfig - just to be sure my programmatic settings were
being applied.
This all works really well when I access the DataPortal without criteria - i.e.
the Csla code runs into WcfProxy.BeginFetch(), which in turn calls
WcfProxy.GetProxy() to setup its proxy object.
I noticed the GetProxy method checks the DefaultBinding and DefaultUrl
properties and uses these if set.
However, when trying to access the DataPortal with a Criteria object, I found
the code was crashing because the endpoint was not defined.
This is because WcfProxy.BeginFetch(object criteria, object userState) is not
calling GetProxy() to setup its proxy object. Instead it simply calls new
WcfPortal.WcfPortalClient().
So the DefaultBinding and DefaultUrl are not applied :(
I'm guessing this is a bug - a call to GetProxy() should be being made imo.
Maybe the WcfPortalClient constructor should be private to prevent such cases
occurring? Or maybe move the GetProxy onto WcfPortalClient as a factory
method?
Either way can this be fixed?
Other than that, things are rolling on nicely with CslaLight. Great job
Magenic guys.
Copyright (c) Marimer LLC