Maybe I'm getting confused on the terminology, but in the DataPortal e-book, I see this quote:
Because Silverlight doesn't support the netTcpBinding, you can't use this binding from a Silverlight client application.
However, I see online articles that SL 4 opened up the possibility of using net.tcp binding. Do "netTcpBinding" and "net.tcp" terms refer to different things? I would like to have an intranet Silverlight (CSLA 4) app use the net.tcp binding for communicating with the data portal. Is this possible? Do any of the examples in the e-book demonstrate this? Thanks.
I think I missed that SL4 added this...
The binding should work fine, but there's no sample specifically for SL.
The only thing I suspect might be different from using that binding in .NET, is that (at least in SL3) your server needs to listen for a specific request from SL to grant SL permission to talk to the server via TCP. This is the TCP equivalent of the cross-domain permission file required for HTTP requests from SL.
Of course that may have changed in SL4 too - but I'm sure something is required to grant permission to SL to talk to your server.
Thanks for clarifying. From what I've read, the clientaccesspolicy file is still needed, and there are examples out there of serving even that up via code in the wcf service without the need for a physical policy file, if needed.
Assuming I use the netTcpBinding capabilities provided by SL4, would I still need to use the portal compression example shown in the e-book? If data is being sent over tcp, I would guess that the size limitation wouldn't exist and therefore I wouldn't have to use compression...is that right?
The size limits are just as real with the WCF tcp bindings as the http bindings. The specific settings and configuration may be different, but the limits are still there.
Since I'm trying to use netTcpBinding available in SL4, should I switch to the Csla.Server.Hosts.IWcfPortal contract within my web.config file, or should I still use Csla.Server.Hosts.Silverlight.IWcfPortal?
Additionally, in an existing Wpf/Wcf implementation, I am subclassing Csla.DataPortalClient.WcfProxy, following the example provided in the e-book. Do I need to also use this in my SL object since in this case since I'm using netTcpBinding? In other words, do I need subclass so that I can do this?
factory.Credentials.Windows.AllowedImpersonationLevel = System.Security.Principal.
factory.Credentials.Windows.AllowedImpersonationLevel = System.Security.Principal.
You must use the IWcfPortal from the Silverlight namespace. The Silverlight data portal has a different service contract from the .NET data portal, and that contract is independent of the WCF binding you choose.
If you need to control the creation of the WCF proxy on the client, you do need to subclass the WcfProxy class, yes.
As far as the creation of the WCF proxy, since it is a SL client how do I go about subclassing the WcfProxy?
In the Authentication/Windows example, it shows the WcfWindowsProxy subclass in the .NET business object, but not the SL object. I tried copy/pasting the code into the SL object, but of course System.ServiceModel.ChannelFactory<Csla.Server.Hosts.IWcfPortal> doesn't compile, and it appears that I can't do System.ServiceModel.ChannelFactory<Csla.Server.Hosts.Silverlight.IWcfPortal>, either.
Just to recap what I'm doing: I intend to use windows impersonation in my SL 4 app, because I'm running in the intranet environment and all users will be authenticated via AD. I've already successfully done this with another SL app using the CustomIdentity/Principal objects (following the examples from the e-book), but the difference here is getting netTcpBinding to work in conjunction and I haven't (yet) wrapped my head around what needs to change to get netTcpBinding to work with this. I might be making this more difficult than it actually is.
public class MyWcfProxy<T> : Csla.DataPortalClient.WcfProxy<T>
where T : Csla.Serialization.Mobile.IMobileObject
protected override Csla.WcfPortal.WcfPortalClient GetProxy()
You are doing two things right?
Using the tcp binding - which should have no real impact on the client proxy or server host. It is just a different binding.
And configuring specific service authentication, and that does have an impact on at least the client proxy (requiring an override).
But you really need a custom proxy and host anyway, because you will implement compression. So you already need to create the subclass of WcfProxy to override the byte stream methods for compression - all you need to do is also override GetProxy to configure your proxy for your authentication model.
Yes, that is correct. I am also using compression, following the e-book examples.
So when I override GetProxy, what am I plugging in besides the call to base.GetProxy()? I assume it would be something similar to what I have in my .NET counterpart (ie setting the AllowedImpersonationLevel)?
The reason I ask is because I'm currently getting the following exception:
System.InvalidOperationException: The contract operation 'Create' requires Windows identity for automatic impersonation. A Windows identity that represents the caller is not provided by binding ('NetTcpBinding','http://tempuri.org/') for contract ('IWcfPortal','http://ws.lhotka.net/WcfDataPortal'.
And just to confirm, in the Application_Startup method in App.xaml.cs, I have the following:
Csla.DataPortal.ProxyTypeName = typeof(BLX.BusinessObject.Common.Compression.CompressedProxy<>).AssemblyQualifiedName;
Csla.ApplicationContext.AuthenticationType = "Windows";
In my web.config file I also have the following serviceAuthorization setting for the service behavior:
<serviceAuthorization impersonateCallerForAllOperations="true" />
These last two things are configured the same way I have configured my other (working) SL app using a different binding.
Oh, I see, you want the service to authenticate the user's Windows credentials?
As I note in the ebook, the Silverlight app does not have access to the user's client-side credentials. So your code has no access to those credentials.
I think the process is automatic, as long as the svc endpoint is in a virtual root that requires Windows authentication. The user will be challenged (in the browser) for their credentials when they first hit the web site (or IE may do automatic impersonation if configured properly). So the Windows client and browser are already authenticating every request to the server behind the scenes.
In other words, your SL code can't get involved because it doesn't have the necessary information. This is all handled at the client workstation or browser level.
If there's some other way to do this with the tcp binding you'll have to find docs or information via MSDN or other sources.
To your first question - I think so. To put it another way, when a user opens the SL app, I want the app to communicate with the remote data portal using his real windows (AD) credentials. I used your Authentication/Windows example to do just this with another SL app and it works great...the SL app calls to the remote data portal and the data portal is then able to make calls to the database with the user's credentials. The only thing different between that app and the current one I'm working on is the binding. That working app uses the standard basicHttp binding, whereas (as you know) I'm trying to get this to work with tcp.
So if I understand what you're saying, you believe that the tcp binding may change how this occurs...is that right? I guess it would, because I'm pretty sure that I've set up my IIS7 applications exactly the same (IIS permissions, web.config files, etc).
The problem I seem to be experiencing (the InvalidOperationException exception shown previously) I had also run into previously in my httpBinding app. However, the way I fixed that isn't working here. So just to be sure I understand - can you clarify whether my problem is, indeed, related to my attempt to use tcp binding? Thanks so much for your help.
You are out of my area of experience at this point, so I can't directly help you.
It is quite possible that the tcp binding doesn't automatically impersonate like the http binding. It is my understanding that the browser is what actually manages impersonation via http - and based on what you are seeing I suspect this isn't occuring via tcp.
fwiw, none of this has anything at all to do with the data portal. I say this, because it might help you with your research. The issue here is how (or if) you can get a SL client to call a service via the tcp binding such that the client workstation's Windows identity flows through to the server. Can the server impersonate the client via tcp binding?
I don't know the answer to those questions - but those are the questions around which you'll need to goobing to find the answer.
Thanks, Rocky. I will head to Google and see what I can find on the topic.
I do have one remaining question (for now), though, which is related to why I began down this route. We're getting ready to re-write my organization's largest, most critical app (currently in VB6). I had considered that WPF was the only way to go with this one, but after reading some of your other posts on how you default to SL and only go to WPF if necessary, I reconsidered. After looking at the app's requirements and reading this particular post of yours, I realized that technically we could do the app in SL. The only remaining concern of mine is the performance difference in http binding vs tcp binding. This LOB app has 400 concurrent users, many spread around the country (some using VPN, some Citrix). I've seen charts that show big performance differences between the two bindings, but I really don't have an idea about how that practically works itself out. If there isn't a way to get tcp binding to work with my scenario, should the performance implications of http binding cause us to consider switching back to WPF? Thanks, again.
There are a lot of variables involved that make arbitrary benchmarks hard to trust.
WCF serializes data over the wire using XML or BinaryXML. The data portal defaults to BinaryXML regardless of the WCF binding, and that eliminates one cause of the tcp perf benefit (because it defaults to BinaryXML, and http defaults to XML).
The other reason tcp is faster is that the tcp headers are smaller than the text-based http headers. Each request has protocol-level headers, and the tcp header is smaller. If you send lots of small messages the header can be a large percentage of the message size. But the data portal messages (for better or worse) are quite large, so the header is always a tiny percentage of any message.
In either case, you need to use compression of the byte stream. This is an absolute requirement for any real app using the data portal on Silverlight. This also skews any "normal" benchmarking though, because it means you are always sending compressed binary streams of data, and WCF then converts that into a wire format for transfer.
I will almost guarantee that any benchmarks you are seeing are assuming transfer of more normal data transfer objects, where WCF handles all the serialization and wire format by itself, and where the data itself isn't a binary stream.
Please note, I'm not saying tcp might not have a perf benefit. But I am saying that any such benefit is probably a lot less signficant when using the data portal - but I've never done that benchmark, so I can't say for sure.
One thing to consider, and I think you are considering this: premature optimization is an anti-pattern. Although it is very foolish to wait to the end of a project to optimize for performance, it is also somewhat foolish to try and anticipate problems before you can run simulated real tests to see if those problems exist.
That is all very helpful to know. I'm sure I probably read somewhere about the DP defaulting to binaryXML but hearing that again is reassuring. Thanks.
Copyright (c) Marimer LLC