Hi, I've just started playing around with the WinRT-build of CSLA. I've been working somewhat with CSLA.NET previously, so I'm familiar with the basic concepts.
Now what happens is that when I call DataPortal.FetchAsync<MyObject>("someParameter"), I get the following exception:
There was no endpoint listening at http://localhost:2114/WcfPortal.svc that could accept the message.
InnerException: No connection could be made because the target machine actively refused it 127.0.0.1:2114
I'm making the assumtion that the dataportal is attempting to set up a WCF client-server for the dataportal. First of all, can I avoid that? It seems like an unneccessary overhead when I'm running both the client and server locally. I thought maybe I could add the [RunLocal] attribute, but it seems not to exist in CSLA.WinRt?
If I have to go with the WCF-method, then I'd like to know why I'm getting the exception. I thought at first it had something to do with permissions, but I have enabled "Internet (Client & Server)" in the appxmanifest-file.
Help appreciated
Hi Frode,
What type of server accees do you need? You may run local only but you can only interact with web/rest/json services.
The Exception indicates that your serverside DataPortal is not started or the client is miscononfigured..
"My server" a one of Google's services. The application I'm developing is a pure front-end against Google. JSON requests will fire from the client. I don't see why I would need a client-server architecture locally.
Try this instead:
DataPortal.FetchAsync<MyObject>("someParameter", DataPortal.ProxyModes.LocalOnly)
Tells the dataportal to use local mode (just as in Silverlight). .
I'm afraid that did not help. Same result. I could post some test code tomorrow.
DataPortal.FetchChild works though... It always runs locally, right? But I would really like to use the Factory-pattern.
Ok, if you can post some test code then I will look into it.
The exception indicates that you either don't have a server-side data portal endpoint set up, or that it isn't reachable.
First, the endpoint must be a Silverlight data portal endpoint, not a .NET endpoint. When you set up and configure the data portal server, you should follow the instructions for setting up a Silverlight server endpoint.
Second, for testing the server is localhost (based on your post). Callbacks to localhost from a WinRT app are normally blocked, but Visual Studio does unblock them on your dev workstation (in the RC). So it shouldn't be a problem to do this unless VS12 was unable to unblock localhost for your app.
I should also point out that the local data portal isn't tested yet. Therefore it is possible that the async methods are ignoring the LocalOnly parameter. I thought I got that right, but maybe not.
The reason the local data portal is untested, is that I'm probably going to change the way the local data portal methods are implemented for Silverlight (and therefore also WinRT) so the DataPortal_XYZ methods don't get a callback parameter.
The callback parameter is required for the event-based model used by Silverlight and WP7, but it is not ideal. With the new async support used in CSLA 4.5 I should be able to get rid of that parameter in the DataPortal_XYZ methods. If you want your method to be async, you should make it async and use the await keyword to make your async call in your code.
This won't break any WinRT apps (because there aren't any), and I don't think all that many people use the local data portal in Silverlight - at least not extensively. So for Silverlight users this will be a breaking change, but hopefully a worthy one, and one that doesn't have major impact for most apps.
I'm not exactly sure I understand what the LocalOnly-parameter is supposed to do. Do I still need to configure a localhost WCF server as described in the CSLA for Silverlight documentation? I was under the impression I bypassed the entire WCF-stuff With LocalOnly. At leas that's what I'd like to achieve.
I have created a sample solution for Win8 RP using CSLA 4.5 here which highlights the exception I'm getting : download link
I'm also confused that you say that you're going to implement DataPortal_XYZ Methods not to get a callback parameter. Haven't you already done that in CSLA 4.5? :) The FetchAsync-method does indeed return an awaitable Object, and does not take a callback parameter.
Hi Frode,
Fix checked in to repository - get latest version and try again.
For some reason the Compiler selected overloads that used ProxyMode as UserState and not as ProxyMode. Added explicit null as UserState to make Compiler select correct version.
Rockford: Ok I understand. Thanks for the explanation. I understand that the WinRT-build of CSLA still is in an early phase.
Jonny: Your fix seemd to work! ...but a new problem arose: Now the task freezes upon the "await". Deadlock of some sort? The Fetch()-method of my factory executes successfully, but code execution never returns to the awaiting method.
Frode,
Your data access is async and does not use Task (not supported yet). So Your DataPortal_Fetch should look like this:
public void DataPortal_Fetch(object criteria, LocalProxy<BusinessObject>.CompletedHandler callback)
{
try
{
Text = "Hello world";
callback.Invoke(this, null);
}
catch (Exception ex)
{
callback.Invoke(this, ex);
}
}
Since Your data Access code is going to call asyncronous webservices you must Accept a callback and is responsible to Call this to notify calling code that async operation is Complete.
This is probably going to change, see 3) in Rockys previous post but for the time beeing the callback parameter is required.
By the way, you can absolutely use async/await in the current implementation.
public async void DataPortal_Fetch(..., callback)
{
try
{
await MyAsyncMethodOrOperation();
callback(this, null);
}
catch (Exception ex)
{
callback(null, ex);
}
}
The reason this works is that the data portal won't proceed until the callback is invoked (as you noticed). And the await keyword will block execution at that point in the method until the async operation is complete, so the callback won't be invoked until either an exception occurs, or the async operation completes.
Your solution works with the DataPortal_XYZ-pattern, Jonny, but when I went back to a ObjectFactory a new problem came up, I'm afraid. The signature of the Fetch-method in the factory class is as follows:
public BusinessObject Fetch(object criteria, LocalProxy<BusinessObject>.CompletedHandler callback)
At runtime I then get this weird ClassCastException:
(A)CompletedHandler[Csla45.WinRt.AsyncAwait.BusinessObject] cannot be cast to ( (B)CompletedHandler[Csla45.WinRt.AsyncAwait.BusinessObject] Type A originates from 'Csla, Version=4.5.1.0, Culture=neutral, PublicKeyToken=93be5fdc093e4c30' in the context 'LoadNeither' at location 'D:\\coding\\source\\samples\\Csla45.WinRt.AsyncAwait\\Csla45.WinRt.AsyncAwait\\bin\\Debug\\AppX\\Csla.DLL'. Type B originates from 'Csla, Version=4.5.1.0, Culture=neutral, PublicKeyToken=93be5fdc093e4c30' in the context 'LoadNeither' at location 'D:\\coding\\source\\samples\\Csla45.WinRt.AsyncAwait\\Csla45.WinRt.AsyncAwait\\bin\\Debug\\AppX\\Csla.DLL'."}
As you can see, the exception basically says class A and B are identical, but still casting fails. This stack overflow-thread had some kind of explanation for this phenomenon, but the case in the question was a bit different. Can you make anything out of this?
The callback handler is specified in each Proxy type so for ObjectFactory the method should be like this:
public class BusinessObjectFactory : ObjectFactory
{
public void Fetch(object criteria, FactoryProxy<BusinessObject>.CompletedHandler callback)
{
try
{
var bo = new BusinessObject();
LoadProperty(bo, BusinessObject.TextProperty, "Hello world");
callback.Invoke(bo, null);
}
catch (Exception ex)
{
callback.Invoke(null, ex);
}
}
}
Brilliant, that did it! I think we can officially close this thread now :-) Thank you both for the help.
Right now the local proxy in Silverlight, WP7, and WinRT all use a callback parameter passed to the DataPortal_XYZ method to know that the DataPortal_XYZ method is complete.
Remember that the client-side data portal components and logical server-side data portal components are different things.
Copyright (c) Marimer LLC