UsingCsla4 04 DataPortal
UsingCsla4 04 DataPortal
UsingCsla4 04 DataPortal
Rockford Lhotka
Using CSLA .NET 4: Data Portal Configuration
All rights reserved. No part of this work may be reproduced or transmitted in any form or by any
means, electronic or mechanical, including photocopying, recording, or by any information
storage or retrieval system, without the prior written permission of the copyright owner.
Trademarked names may appear in this book. Rather than use a trademark symbol with every
occurrence of a trademarked name, we use the names only in an editorial fashion and to the
benefit of the trademark owner, with no intention of infringement of the trademark.
The information in this book is distributed on an “as is” basis, without warranty. Although every
precaution has been taken in the preparation of this work, the author shall not have any liability
to any person or entity with respect to any loss or damage caused or alleged to be caused directly
or indirectly by the information contained in this work.
The source code for this book (CSLA 4 version 4.1.0) is available at
http://www.lhotka.net/cslanet.
Revision: 1.0
Acknowledgements
Neither this book, nor CSLA 4, would have
been possible without support from Magenic.
Magenic is the premier .NET development
company in the US, and is a Microsoft Gold
Certified Partner.
This book covers the configuration of the data portal, including how to use it for 1-, 2-, 3-, and 4-
tier physical deployment models. It also covers the authentication models that can be used with the
data portal.
The data portal is the component in the CSLA .NET framework that supports the mobile object
concept discussed in the Using CSLA 4: CSLA .NET Overview ebook. It abstracts the network, and
manages objects and messages as they flow between client and server.
By using the data portal and the five layer architecture prescribed by CSLA .NET, an application
can switch from a 1- or 2-tier to a 3- or 4-tier deployment without changes to any code.
Additionally, an application can change from using HTTP, to TCP, or other network technologies for
communication between the client and server, again with no changes to the application’s code.
By the end of this book you will understand how to use and configure the data portal.
Local
WCF (for .NET)
WCF (for Silverlight and Windows Phone 7 (WP7))
Remoting (.NET only)
Enterprise Services (.NET only)
The local channel (sometimes called the local proxy) doesn’t cross the network. It runs the
“server-side” components in the same AppDomain, and therefore on the same computer, as the
“client-side” components.
The other channels do cross the network, or at least AppDomain or Windows process
boundaries, and they are used in 3- and 4-tier deployments.
The WCF channel for .NET has access to the full set of WCF technologies on .NET, and uses the
NetDataContractSerializer provided by WCF. You can use any WCF binding that provides a
synchronous communication model. This excludes the MSMQ-based bindings, but allows the use of
HTTP, TCP, named pipes, and other similar bindings.
The WCF channel for Silverlight and Windows Phone 7 (WP7) has access to the features of WCF
available on Silverlight and the phone. This channel uses a custom serializer provided by CSLA .NET
Using CSLA 4: Data Portal Configuration Page 4
Rev 0.4 (draft)
called the MobileFormatter. The custom serializer is required, because Silverlight doesn’t
implement the .NET serializers required by CSLA .NET: the BinaryFormatter or
NetDataContactSerializer.
Deployment Options
In the Using CSLA 4: CSLA .NET Overview ebook, I discussed the architectural concerns and tradeoffs
as you deploy applications into an n-tier environment. Typically, the more tiers in your deployment,
the slower the application will perform for any one user. In many cases, adding more tiers does
provide other benefits, possibly including:
Scalabity
Security
Fault tolerance
Please refer to Chapter 2 in the Using CSLA 4: CSLA .NET Overview ebook for a detailed
discussion of the costs and benefits of n-tier deployment.
1-tier Deployment
The simplest deployment model is a 1-tier deployment. If all five layers from Figure 1 are deployed
onto one physical computer, and are running in the same .NET AppDomain, that is a 1-tier
deployment.
In a 1-tier deployment the data portal is configured in local mode. This means that the “server-
side” data portal components are running on the same machine, and in the same .NET AppDomain,
as the “client-side” data portal components.
When the data portal is configured to run in local mode, there is no cross-network or cross-
AppDomain communication. The client-side data portal makes direct method calls to the server-
side data portal, all within the same AppDomain.
Local mode is supported by the local channel provided by the data portal.
In a 1-tier deployment, the client-side application components have access to the database
credentials, and to the physical database itself.
3-tier Deployment
A 3-tier deployment is often used to enhance security or improve scalability for smart client
applications. It can also be used in environments where the client workstations are geographically
distant from the data center, because having the client communicate with an application server is
often more efficient than having the client communicate directly with the database server.
Figure 5 shows the 3-tier deployment model for a smart client application.
4-tier Deployment
Silverlight and WP7 applications can be deployed into a 4-tier model.
Because most Silverlight applications are deployed to the client workstation from a web server,
it is often natural for the application to make service calls back to that same web server. If the web
server is allowed to interact with the database server directly, then the web server is also the
application server and you are using a 3-tier smart client deployment like that shown in Figure 5.
In some cases, the web server is not allowed to interact directly with the database server. This is
usually due to security restrictions, where the web server must communicate through a second
firewall to interact with other servers in your organization’s network. To enable this scenario, the
Silverlight data portal supports a 4-tier deployment as shown in Figure 7.
Configuring an application to interact with a database server is outside the scope of this book.
That configuration is dependent on the type of database and database server technology you are
using, and can be very different for SQL Server Compact Edition, SQL Server, Oracle, XML files, text
files, or the many non-relational databases that have become popular recently.
The primary difference between 1- and 2-tier models is the configuration of the database and
database server.
The rest of this chapter will focus on how the data portal is configured to use the local channel
for 1- and 2-tier models, or the WCF channel for 3- and 4-tier models.
Client Configuration
When you use the local channel, the client-side and server-side data portal components all run on
the same machine, and in the same AppDomain. This means that there is no “server configuration”
of the data portal, because there is no real server.
All data portal configuration is client configuration in a 1- or 2-tier deployment. The techniques
and defaults for data portal configuration are different between .NET, Silverlight, and WP7. I’ll
discuss each platform.
.NET Configuration
In a .NET application (such as WPF or ASP.NET), the data portal defaults to using the local channel.
This means you can use the data portal in a 1- or 2-tier application without the need to do any
configuration.
If you do want to explicitly configure the data portal to use the local channel, you need to add a
CslaDataPortalProxy entry to the appSettings section of the app.config or web.config file:
<appSettings>
<add key="CslaDataPortalProxy" value="Local" />
</appSettings>
1. The application is a 1-tier application, and is storing its data in isolated storage
2. The application is an SOA “edge application” that is invoking services (SOAP or REST)
The data portal is typically configured through code as the Silverlight application first starts. This
means adding code to the App.xaml.cs file in the Silverlight application project:
private void Application_Startup(object sender, StartupEventArgs e)
{
Csla.DataPortal.ProxyTypeName = "Local";
this.RootVisual = new MainPage();
}
WP7 Configuration
In a WP7 application, the data portal defaults to using the local channel. Although a WP7
application is a Silverlight application, the most common scenario for a WP7 application is that it
will store data locally in isolated storage, or that it will invoke SOAP or REST services on a server.
If you do want to explicitly set the ProxyTypeName to "Local" for a WP7 application, you need to
edit the project’s App.xaml.cs file and set the property in the constructor of the App class:
public App()
{
Csla.DataPortal.ProxyTypeName = "Local";
You should only disable this feature if you have a complete understanding of the
consequences, and are willing to alter your application code to deal with the
resulting behaviors.
If you use the asynchronous data portal and you disable automatic cloning, you can encounter
cross-threading exceptions. The data access code may be running on a background thread, and if
your object graph is bound to the UI then the PropertyChanged and CollectionChanged events
may be raised on that background thread. Because .NET UI technologies are not threadsafe, they
throw a cross-threading exception when this happens, to avoid corruption of the UI.
Another issue you may encounter, is that without cloning, business objects bound to the UI
through data binding will remain bound while they are being updated by your data access code.
This can lead to UI flickering and poor performance, as the UI attempts to remain current while the
object graph is being manipulated by the data access code.
The most complex issue is that a failure during a data portal update operation can leave the
object graph in an indeterminate state. Although the database update should be transactionally
protected and will roll back, the state of your objects in memory will be left partially updated, and
therefore will be invalid.
This happens because during the update operation the object graph is changed to reflect any
database-generated primary key values, updated timestamp values, and so forth. Those changes
are made to the objects in memory as the data is updated in the database. If the database update
fails part way through the process, the database typically rolls back and all changes are undone. But
the properties of your objects in memory remain changed, and are therefore wrong.
Using CSLA 4: Data Portal Configuration Page 13
Rev 0.4 (draft)
When the data portal’s automatic cloning feature is enabled, that invalid object graph is
automatically discarded, and your application continues to use the object graph as it was before the
failed database update was attempted. This is good, because it means your application has access
to a consistent and valid object graph.
If you disable the automatic cloning feature, it is up to your application code to detect that a
database update has failed, and to discard the object graph. You must write this code, typically by
overriding the Save method of each business class, or by handling this situation in your UI code.
To disable the automatic cloning feature, you will set the CslaAutoCloneOnUpdate configuration
value to false in the app.config or web.config file:
<appSettings>
<add key="CslaAutoCloneOnUpdate" value="false" />
</appSettings>
This configuration value defaults to true. Setting it to false disables the feature.
At this point you should understand how to configure the data portal to use the local channel for
.NET, Silverlight, and WP7 applications. I will move on to discuss the use of the WCF channel.
http://msdn.com/wcf/
http://wcfsecurity.codeplex.com/
http://wcf.codeplex.com/documentation
In this chapter I will focus on the configuration of the data portal, along with some WCF
configuration details necessary for common application scenarios. However, it is necessary to
Using CSLA 4: Data Portal Configuration Page 14
Rev 0.4 (draft)
understand some of the basic WCF configuration concepts and terminology to even begin this
discussion.
1. Address
2. Binding
3. Contract
This is sometimes called the “ABC” of WCF. These three elements are what define every WCF
service. And any client that calls a WCF service must configure itself to match the service’s address,
binding, and contract. For example, here’s the configuration of a client that is calling a WCF service:
<client>
<endpoint name="BasicHttpBinding_IWcfPortal"
address="http://localhost:21647/SlPortal.svc"
binding="basicHttpBinding"
contract="WcfPortal.IWcfPortal" />
</client>
You can see the address, binding, and contract in the configuration for the service.
The WCF data portal channel consists of a WCF service, and client code to call that service.
Although the contract is defined by the channel, it is up to you to choose the binding and address
for the service.
Address
The address is the URI (universal resource identifier) or network name where the service is hosted.
In many cases this is an HTTP URL, for example:
http://myserver.mycompany.com/myapplication/WcfPortal.svc
When a WCF service is hosted in IIS, all parts of the address except the name of the svc file are
defined by the web server. If you host your WCF service in a custom Windows service, then you will
explicitly define the address.
Binding
The format of the address will be different depending on the WCF binding that is used. The binding
controls how WCF communicates between client and server. There are several bindings that use
HTTP. There are also bindings that use TCP sockets, named pipes, MSMQ queues, and other
network technologies.
The address of the service will depend on the binding that is used. In the example above, the
service must be configured to use one of the HTTP bindings. If the service is configured to use one
of the TCP bindings, the address might look more like this:
tcp://myserver.mycompany.com:12004/WcfPortal.svc
Contract
The service contract defines the service interface. A service contract consists of three parts:
1. Operation contract
2. Data contracts
3. Fault contracts
The operation contract defines the methods a service implements. These methods can be
invoked by the client that is calling the service.
The data contracts define the properties for the messages that are passed to and from each
service method. If a method accepts a message object of type RequestMessage, then the
RequestMessage data contract is part of the overall contract for the service.
The fault contracts define the messages returned from the service in case of failure. When
designing a service interface, it is important to view failure conditions as a valid part of the service.
Each failure condition is typically described using a fault, and an associated data contract that
contains the information about the fault.
When using the WCF data portal channel, the service contract is defined by CSLA .NET. The .NET
contract is IWcfPortal from the Csla.Server.Hosts namespace. The Silverlight contract is also
IWcfPortal, but from the Csla.Server.Hosts.Silverlight namespace.
If you create your own data portal channel that uses WCF, you need to define your own contract
for your service implementation. I describe how to create a custom data portal channel in Chapter
4.
Other hosting environments might have their own limits and customization techniques. You
should understand the hosting environment you are using for your application server, and how to
configure that specific environment.
WCF may have data size limits on the client as well. Here’s an example of raising the limits for
the basicHttpBinding binding on a Silverlight client:
<bindings>
<basicHttpBinding>
These settings also override the values for the send and receive timeouts, demonstrating some
other options you can set on your bindings.
As I discuss specific configurations for .NET and Silverlight I’ll use similar configuration elements.
Returning Faults
The data portal will return detail about server exceptions to the client. This is possible due to a
configuration setting applied to the service endpoint that allows the information to be returned. On
the .NET server, a custom behavior is applied to the service. For example:
<behaviors>
<serviceBehaviors>
<behavior name="returnFaults">
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
The service configuration indicates that this custom behavior should be used through the
behaviorConfiguration property on the service element. For example:
<service name="Csla.Server.Hosts.WcfPortal" behaviorConfiguration="returnFaults">
<endpoint binding="wsHttpBinding" bindingConfiguration="wsHttpBinding_IWcfPortal"
contract="Csla.Server.Hosts.IWcfPortal" />
</service>
Troubleshooting Services
It can sometimes be challenging to troubleshoot WCF connection issues. Many of the exceptions
returned by WCF or the CSLA .NET data portal are obscure or don’t provide detail about the real
issue.
Perhaps the most important troubleshooting tip for WCF services is to right-click on the svc file
in Solution Explorer, and to choose the View in Browser menu option. This will bring up a
browser window to display metadata about the service. If the browser displays error or exception
information, it is a clear indication that the service configuration in the web.config file is in error.
WCF can be configured to write detailed information to a .NET trace listener. You configure this
behavior in the server’s web.config file by adding a top level system.diagnostics element to the
configuration. This element looks like this:
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing" propagateActivity="true">
Using CSLA 4: Data Portal Configuration Page 18
Rev 0.4 (draft)
<listeners>
<add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener"
initializeData="c:\temp\WcfTrace.xml" />
</listeners>
</source>
</sources>
<trace autoflush="true" />
</system.diagnostics>
You should change the c:\temp\WcfTrace.xml path and filename to a location where the service
host process has write permissions on your computer. As client applications interact with the WCF
service on the server, detailed trace information, often including important exception detail, is
written to this file.
Client Configuration
The client may be a WPF, Silverlight, WP7, or Windows Forms smart client application. Or it may be
code running on a web server for an ASP.NET or service application. The configuration techniques
and defaults for each platform are different.
.NET Configuration
A .NET client might be a smart-client WPF or Windows Forms application, or an ASP.NET
application. In the case of an ASP.NET Web Forms, ASP.NET MVC, or service interface, the “client” is
the web server that is using the data portal to communicate with an application server.
In a .NET application the data portal is configured to use the WCF channel by setting the
CslaDataPortalProxy value in the app.config or web.config file:
<appSettings>
<add key="CslaDataPortalProxy" value="Csla.DataPortalClient.WcfProxy, Csla" />
</appSettings>
The CslaDataPortalProxy configuration value is set to the assembly qualified type name of the
data portal proxy class. In this case, it is the WcfProxy class from the Csla.DataPortalClient
namespace, in the Csla assembly.
You must also provide the client with the URL of the application server endpoint. This can be
done in three ways:
Because the most common configuration is to use wsHttpBinding with maximum message size
limits, it is very likely that you can use the CslaDataPortalUrl configuration technique in your
application.
The endpoint name expected by the data portal proxy is WcfDataPortal. Within this endpoint
element you must provide all necessary WCF configuration values for your environment. At a
minimum, you must provide the address, binding, and contract values shown in the example,
using an address and binding appropriate for your server.
The contract value will always be Csla.Server.Hosts.IWcfPortal when you are using the
standard CSLA .NET data portal WCF channel.
Subclassing WcfProxy
Sometimes, you will need even more control over the WCF client configuration than can be
provided through a configuration file. It is also possible that you will want to avoid putting the WCF
configuration into a file, but would rather have the values hardcoded in the application, or loaded
from some other source.
In these cases, you can create a subclass of the WcfProxy class from the Csla.DataPortalClient
namespace. The WcfProxy class is designed to enable customization of the WCF client without the
need to create a completely custom data portal channel. Table 1 lists the members of the WcfProxy
class you might use for customization.
Member Description
EndPoint property Set this value to control the name of the service configuration file
element used for WCF configuration on the client; default is
WcfDataPortal
GetChannelFactory method Override this method to create the ChannelFactory<IWcfPortal>
used to create the IWcfPortal proxy object by the default
GetProxy method implementation
This tells the data portal to use your custom proxy instead of the standard WcfProxy class.
Many .NET applications can simply set the CslaDataPortalProxy and CslaDataPortalUrl
configuration values on the client. If you need more control over the client configuration, you can
provide explicit WCF configuration through the application’s configuration file, or create a subclass
of the WcfProxy class.
Silverlight Configuration
A Silverlight application will use the WCF data portal channel by default, so you don’t need to
configure the client to use WCF. You do need to provide the server URL, and you might provide
custom configuration of WCF on the client.
As in a .NET application, there are three ways to configure the client to communicate with the
application server:
Even using the maximum message size limits for WCF on Silverlight, most applications will need
to use compression to reduce the size of messages sent through the data portal. This is partially
because of WCF message size limitations on Silverlight, and partially because the MobileFormatter
(discussed further in Chapter 3) often generates large data streams.
Because of this, the most common configuration technique for Silverlight applications is to
create a subclass of the WcfProxy class. I provide a detailed walkthrough in Chapter 4, showing how
to create a compressed WCF data portal channel for Silverlight and WP7.
If only the DefaultUrl property is specified, the WCF data portal proxy will default to using a
basicHttpBinding binding, with the message size limits set to their maximum values.
You can also explicitly provide a WCF Binding object by setting the DefaultBinding property:
private void Application_Startup(object sender, StartupEventArgs e)
{
var binding = new BasicHttpBinding();
binding.MaxBufferSize = int.MaxValue;
binding.MaxReceivedMessageSize = int.MaxValue;
binding.ReceiveTimeout = TimeSpan.FromMinutes(10);
binding.SendTimeout = TimeSpan.FromMinutes(10);
binding.OpenTimeout = TimeSpan.FromMinutes(10);
Csla.DataPortalClient.WcfProxy.DefaultBinding = binding;
Csla.DataPortalClient.WcfProxy.DefaultUrl = "http://localhost:21647/SlPortal.svc";
this.RootVisual = new MainPage();
}
This example creates a basicHttpBinding with the message size limits set to their maximum
values, just like the default binding used if only the DefaultUrl property is specified.
This example sets the address, binding, and contract for the application server. The endpoint
name is BasicHttpBinding_IWcfPortal, and that is the default name used by the WCF data portal
proxy. You can override that name by setting the DefaultEndPoint property on the WcfProxy class:
private void Application_Startup(object sender, StartupEventArgs e)
{
Csla.DataPortalClient.WcfProxy.DefaultEndPoint = "MyEndPointName";
The example configuration also customizes the basicHttpBinding to set the message size limits
to their maximum values.
Subclassing WcfProxy
The WcfProxy class for Silverlight is designed so you can create a subclass to customize the data
portal channel without having to write your own proxy and host from scratch.
The primary reason for creating a subclass is to implement compression to minimize the amount
of data passed between client and server. In Chapter 4, there is a section devoted to a detailed
walkthrough of adding compression to the Silverlight WCF data portal channel.
Table 2 lists the members of the WcfProxy<T> class you might use or override in a subclass.
Member Description
Binding property Set this value to create a custom WCF Binding object for use in
communications with the application server
DataPortalUrl property Set this value to the URL for the application server endpoint
EndPoint property Set this value to the name of the endpoint element in the
ServiceReferences.ClientConfig file that should be used for
WCF configuration
GetProxy method Override this method to create the IWcfPortal proxy object; this is
normally done by using the channel factory created by the
GetChannelFactory method
ConvertRequest method Override the two overloads of this method to compress the data in
the byte stream being sent from the client to the application server
on each data portal request
ConvertResponse method Override this method to decompress the data in the byte stream
being received by the client from the application server
To use your custom proxy type, provide the name of your type instead of the one shown here.
Most Silverlight applications will implement compression to minimize the data transferred
between client and server. When this is done by subclassing the WcfProxy<T> class, the static
properties on the WcfProxy class (DefaultUrl, DefaultBinding, and DefaultEndPoint) can be used
to configure the data portal. For more complete customization, your subclass of WcfProxy<T> may
completely override the creation of the WCF binding and proxy objects.
WP7 Configuration
A Windows Phone application defaults to using the local data portal channel. This is because the
data portal requires that the client and application server use the exact same business assemblies,
and it can be difficult to control exactly when (or if) a user updates your application on their phone.
If you do choose to use a remote data portal configuration for a WP7 application, you will need
to configure the client application to use the WCF data portal. This is done by setting the
ProxyTypeName property of the DataPortal class as the application starts:
public App()
{
Csla.DataPortal.ProxyTypeName = typeof(Csla.DataPortalClient.WcfProxy<>).AssemblyQualifiedName;
...
You must also specify the URL of the application server, along with any other client-side
configuration.
Configuring a WP7 application is exactly the same as configuring a Silverlight application. Please
refer to the previous section on Silverlight configuration for details.
At this point, you should understand the basic configuration options for a .NET, Silverlight, and
WP7 client. I will now discuss how to set up and configure an application server using the data
portal.
Any environment that will host a CSLA .NET web application or the data portal must provide
FullTrust security in Microsoft .NET.
When selecting a host environment or hosting provider, make sure your server-side components
will have access to FullTrust security in .NET.
Today, most organizations host application server components in IIS, but over time they will
probably move toward hosting in Windows Server AppFabric. Components hosted in Windows
Server AppFabric still run in IIS, but have additional administrative and monitoring capabilities.
It is also possible to host the data portal application server components in Windows Azure. This
means you can take advantage of the cloud-based features provided by the Windows Azure
environment in the server-side data portal, and in the code you author or invoke in your
DataPortal_XYZ methods or object factory methods.
In environments where IIS is not available on the application server, you might choose to use the
Windows Activation Service (WAS) or a custom Windows service to host the data portal. These
options allow the server-side components to be hosted without the need for IIS or Windows Server
AppFabric.
I’ll discuss each of the options in more detail, with a specific focus on Windows Server AppFabric
and Windows Azure. First though, I’ll discuss one detail that is unique to Silverlight applications.
Most of the sample application server projects used in this ebook include a copy of this
clientaccesspolicy.xml file.
Csla.dll
Your business library assemblies (compiled for .NET)
Your data access assemblies
Any other assemblies required by your server-side code
I typically reference all required projects or assemblies in my web project in Visual Studio,
because that allows Visual Studio to manage the dependencies. If you don’t want to reference the
projects or assemblies, you can use some other deployment technology to ensure that the correct
assemblies are deployed to the web site’s bin folder.
In the IISHost project, I’ve added references to Csla.dll, and to the Library.Net, DataAccess,
and DataAccess.Mock projects. This ensures that the latest versions of my server-side components
will be in the bin folder each time I run, package, or deploy the solution from Visual Studio.
This WcfPortal class is located in the Csla.Server.Hosts namespace in Csla.dll. The svc file
provides WCF with the information necessary to locate that type.
Your data portal host project should only include the WcfPortal.svc file if you want to support
.NET client applications.
You should also understand that this file can have any name you choose. The name of this file is
part of the URL the client application will use to call the application server, and you can name the
file to control that part of the URL.
The SlPortal.svc file is the endpoint for the Silverlight data portal. This is the endpoint that will
be used by any Silverlight or WP7 client applications. It contains the name of the type that
implements the Silverlight data portal service:
<% @ServiceHost Service="Csla.Server.Hosts.Silverlight.WcfPortal" %>
Notice that the type name of the Silverlight WcfPortal class is different from the .NET class.
Your data portal host project should only include the SlPortal.svc file if you want to support
Silverlight or WP7 client applications. And again, there is nothing “magic” about this file name. You
can name the svc file anything you choose, as long as the client uses the same name in its server
URL.
During development you can host the web site in one of several locations, including:
As I discussed earlier in this chapter, the endpoint is composed of an address, binding, and
contract. Because this service is hosted in IIS, the address is predefined and there’s no need for an
address property in the configuration of the endpoint. The address of this service is:
http://www.mycompany.com/mywebsite/WcfPortal.svc
The specific address will depend on the name of your organization’s Internet domain, and the
name of the virtual root into which the web site is deployed. Notice how the WcfPortal.svc file
name is the part of the URL that you can control.
The wsHttpBinding element is used to override the default configuration of the wsHttpBinding
object used by WCF. In this example I’m setting the message size limits to their maximum values.
The custom returnFaults behavior is used to tell WCF to return exception fault information to
the client, allowing the data portal to provide detailed exception data to the calling code. Notice
how the behaviorConfiguration property is set on the service element so WCF uses this behavior
for the data portal service.
As with the .NET endpoint, there is no explicit address set because the URL is derived from the
IIS host and the name of the svc file:
Using CSLA 4: Data Portal Configuration Page 31
Rev 0.4 (draft)
http://www.mycompany.com/mywebsite/SlPortal.svc
The basicHttpBinding element is used to override the default message size limits for the
binding, allowing larger messages to pass over the network. And the returnFaults custom
behavior is used to allow WCF to return exception detail from the server for use by the client-side
data portal components.
At this point you should understand how to set up an ASP.NET web project to contain the WCF
data portal host components. This involves setting up a web project, adding assembly or project
references, the svc files, and configuring the WCF endpoints in the web.config file.
I will now move on to discuss the use of the WCF data portal host in Windows Server AppFabric.
For this discussion, I am assuming that you have installed and configured Windows
Server AppFabric and IIS on your development workstation or server. Please refer to
http://msdn.com/appfabric for full product information and documentation.
To set up the WCF data portal host for Windows Server AppFabric you need to follow the same
steps as for IIS, including:
The Windows Server AppFabric features are only available in IIS itself. This means you can’t use
them in the ASP.NET Development Web Server, or in IIS Express.
The primary benefit of running the data portal in IIS with Windows Server AppFabric is that you
gain health monitoring, and the ability to use AppFabric for event logging. This information is
available through the AppFabric Dashboard in the IIS Manager, and provides valuable information
that is not otherwise available for WCF services hosted in IIS.
When the application is run, the Silverlight client application will invoke the data portal endpoint
hosted in Windows Server AppFabric, based on the DefaultUrl property value set as the
application starts:
private void Application_Startup(object sender, StartupEventArgs e)
{
Csla.DataPortalClient.WcfProxy.DefaultUrl = "http://localhost/IISHost/SlPortal.svc";
I will now discuss how to configure the web application and WCF services for AppFabric health
monitoring and custom event logging.
Troubleshooting
End-To-End Monitoring
Health Monitoring
Using CSLA 4: Data Portal Configuration Page 34
Rev 0.4 (draft)
Errors Only
Off
These are in order of verbosity and overhead. The Health Monitoring level is appropriate for
most applications.
After configuring the web application for monitoring a microsoft.applicationServer element
has been added to the web.config file:
<microsoft.applicationServer>
<monitoring>
<default enabled="true"
connectionStringName="ApplicationServerMonitoringConnectionString"
monitoringLevel="HealthMonitoring" />
</monitoring>
</microsoft.applicationServer>
This element is used to configure AppFabric monitoring for the WCF services in the web site.
The enabled property indicates whether monitoring is enabled or disabled.
The connectionStringName propery must be the name of a database connection value available
in the ASP.NET configuration. That database must be configured for use by AppFabric. During the
installation of Windows Server AppFabric, the installer will set up the database and this connection
string name.
The monitoringLevel property indicates the level of detail that should be included in the logging
performed by AppFabric. For basic health monitoring, the value should be HealthMonitoring.
Additionally, some entries have been added to the system.serviceModel element in the
web.config file. I will discuss those entries in the next section when I talk about event logging with
AppFabric.
Once the web application has been configured for health monitoring, AppFabric will
automatically collect usage statistics for your WCF services, including the data portal endpoints.
Figure 14 shows the AppFabric Dashboard for the IISHost web application after the Silverlight
client application has been used to interact with the data portal a few times.
When AppFabric monitoring is enabled for a WCF service, entries are also written into the
system.serviceModel configuration element. The diagnostics element configures logging of
events for services:
<diagnostics etwProviderId="029f8aa9-30ae-472f-aaa2-42db603a20d8">
<endToEndTracing propagateActivity="true" messageFlowTracing="true" />
</diagnostics>
Because the .NET and Silverlight data portal endpoints already use this returnFaults behavior,
they will now also support custom event logging.
The Microsoft Developer & Platform Evangelism team has created a helper class to simplify the
code required to generate custom events. This class is available as part of the AppFabric WCF
Service Template. This template is discussed in Ron Jacob’s blog:
http://blogs.msdn.com/b/rjacobs/archive/2011/03/09/appfabric-wcf-service-c.aspx
The DataAccess.Mock project in the AppFabricHost solution includes the
DalManagerEventProvider class, based directly on the helper class created by Microsoft. You can
look through the code in that class to see how they create information, event, and error events for
AppFabric.
This helper class requires that the project reference the following assemblies:
System.Configuration.dll
System.ServiceModel.dll
System.Web.dll
Each time the GetProvider method is called, it either finds an implementation of the requested
interface or it doesn’t. If an instance of the interface is found, an informational event is generated:
_eventProvider.WriteInformationEvent("DataAccess.Mock",
string.Format("DAL request for {0}", type.Name));
If an instance of the interface can’t be found, the code now handles the resulting exception, and
generates an error event for that exception:
_eventProvider.WriteErrorEvent(ex);
The exception is then re-thrown, so the failure is reported back to the client through the data
portal after it has been logged.
For demonstration purposes, I have altered the DataPortal_Update method in the PersonEdit
business class to request a type that isn’t implemented in the DataAccess.Mock project. This means
a new PersonEdit object can be inserted into the database, but an update will cause an exception.
When the application is run, the AppFabric Dashboard provides access to the custom events.
These events are available as you drill into the details about each specific service invocation. For
example, clicking on the service hyperlink in the Completed Calls list shown in Figure 17 will
bring up details about the invocations of that service.
For this discussion I assume you have installed the Windows Azure SDK on your
development workstation. This SDK is available from http://msdn.com/azure.
To deploy the application to the development test environment, you must configure
your Windows Azure SDK development environment. For this discussion I assume
you have configured your development machine for Azure development.
To deploy the application to actual Windows Azure servers, you must establish an
account with Microsoft and pay appropriate usage fees.
The AzureHost solution in the sample code download for this ebook includes an AzureHost
project. This is a Windows Azure Project created as shown in Figure 22.
References Csla.dll, your business assemblies or projects, and your data access assemblies
or projects
Contains appropriate svc files to the web project for the .NET and Silverlight data portal
endpoints
Has appropriate system.serviceModel entries to web.config for the .NET and Silverlight
data portal endpoints
The WebRole1 project also references the SilverlightUI project, so it hosts the Silverlight client
application.
In short, the WebRole1 project is identical to the IISHost project in the original IISHost solution
I used earlier in this chapter to demonstrate hosting in IIS.
The DataPortal_XYZ methods or your object factory methods, along with your data access code,
will all run in the Windows Azure environment. This means you can make use of any Windows
Azure features in that code, including the use of SQL Azure databases, Windows Azure Storage, and
Windows Azure AppFabric.
As with the other sample applications, the AzureHost solution uses the mock database
implemented by the DataAccess.Mock project.
Running the solution in Debug mode from Visual Studio will cause Visual Studio to do the
following:
3. Run the Azure deployment package to deploy the solution to the Windows Azure compute
emulator
The Silverlight client application will invoke the data portal endpoint hosted in the Windows
Azure compute simulator, based on the DefaultUrl property value set as the application starts:
private void Application_Startup(object sender, StartupEventArgs e)
{
Csla.DataPortalClient.WcfProxy.DefaultUrl = "http://127.0.0.1:81/SlPortal.svc";
this.RootVisual = new MainPage();
}
Hosting the data portal in Windows Azure is virtually identical to hosting the data portal in IIS.
This means that it is easy to consider using Windows Azure as a host for your CSLA .NET application
server.
In this discussion I assume you have installed, enabled, and configured WAS for use
on your development workstation. Because I’ll be demonstrating the use of the
netTcpBinding in WCF, I also assume you have installed IIS.
The primary value of using WAS is that a WCF service can be hosted with a protocol other than
HTTP. Specifically, WAS adds support for these protocols:
Because the data portal requires a synchronous WCF binding, only the TCP and named pipes
protocols are useful in this discussion.
WAS is designed to host a web application, just like IIS. This means that the same steps for
creating and configuring a web application to host the WCF data portal channel for IIS apply to
WAS. The WASHost solution in the sample code download for this ebook uses WAS to host the .NET
data portal, using the netTcpBinding in WCF.
Because Silverlight doesn’t support the netTcpBinding, you can’t use this binding from a
Silverlight client application. The WASHost solution contains a WpfUI project instead of the
SilverlightUI project used in the previous examples.
Notice that the binding property for the endpoint is netTcpBinding, and that the address
property specifies a net.tcp:// URL. The default port used by WAS for TCP communication is 808.
Also notice that the netTcpBinding is customized to set the message size limits to their
maximum values, and to control the security used for communication with the server.
Notice that the service name, behaviorConfiguration, and contract properties are unchanged.
Only the binding property is different.
The server configuration also customizes the netTcpBinding to set the message size limits and
security:
<bindings>
<netTcpBinding>
<binding portSharingEnabled="true"
maxReceivedMessageSize="2147483647">
<security mode="None" />
<readerQuotas maxBytesPerRead="2147483647"
maxArrayLength="2147483647"
maxStringContentLength="2147483647"
maxNameTableCharCount="2147483647"
maxDepth="2147483647"/>
</binding>
</netTcpBinding>
</bindings>
The netTcpBinding requires that the binding values on the client and server match.
It also requires that many binding properties be consistent across all uses of
netTcpBinding by different applications on the server. See the documentation from
http://msdn.com for more information.
When the solution is run, the WpfUI application launches and uses the net.tcp protocol to
communicate with the application server using TCP and port 808.
A consistent theme in all these hosting scenarios is that the application code is essentially
unchanged. In each case, I am changing the client and server configuration so WCF communicates
using the correct WCF binding and address to reach the server. At no point are the business classes
or data access classes affected by these changes. In this WAS example the client application
switched from Silverlight to WPF, only because Silverlight doesn’t support the TCP binding I wanted
to demonstrate.
HTTP
TCP
Named pipes
The protocol selection is based on how the WCF endpoints are configured.
One of the challenges with building Windows services is debugging. It is notoriously difficult to
debug code running in a Windows service. To make initial debugging simpler, I always create a Class
Using CSLA 4: Data Portal Configuration Page 46
Rev 0.4 (draft)
Library project to contain the code that does the real work of the service. Then I reference this
project from the Windows service project, as well as a Console Window project. Figure 25 illustrates
this relationship, using the project names from the WindowsHost solution in the sample code
download for this ebook.
Csla
The business library projects or assemblies
The data access projects or assemblies
System.ServiceModel
The references to Csla.dll, the business code, and the data access code are required because
this is the host for the data portal. Like the web application projects discussed earlier in this
chapter, the data portal host needs access to these assemblies.
The reference to the System.ServiceModel assembly is required to host WCF. The
DataPortalHost class contains the code necessary to host WCF. The Start method creates and
initializes instances of ServiceHost objects:
public void Start()
{
if (_netService != null)
_netService.Close();
The _netService field represents the .NET data portal endpoint, and the _slService field
represents the Silverlight endpoint.
Although most of the configuration for these endpoints is in the host application’s app.config
file, the endpoint URI values are specified as the ServiceHost objects are created. Rather than
hardcoding the URI values, this code reads them from appSettings entries in the application’s
configuration file.
I’ll discuss the configuration in the app.config file as I walk through the creation of the console
application and Windows service projects.
The Stop method in the DataPortalHost class closes the endpoints:
public void Stop()
{
if (_netService != null)
{
_netService.Close();
_netService = null;
}
if (_slService != null)
{
_slService.Close();
_slService = null;
}
}
These Start and Stop methods reflect the way a Windows service works. A Windows service can
be started and stopped, and so this code supports those two operations.
The configuration in the app.config file is identical to the configuration for the WAS hosted
service, except that the address property matches the URI specified by the WindowsHost project.
Console.WriteLine();
Console.WriteLine("Service stopped");
Console.WriteLine();
Console.WriteLine("Press <return> to exit");
Console.ReadLine();
}
All the interesting work occurs in the WindowsHost project’s code, where the WCF endpoints are
opened and then closed.
It is important to understand that .NET applications have exactly one configuration file per
AppDomain, and that configuration file comes from the application that is executed, not by any
other assemblies being used. This means that it is the app.config file from the WindowsConsole
project that provides configuration values when the service is running through the console
application.
The appSettings element contains the URI values for each endpoint:
<appSettings>
<add key="DalManagerType" value="DataAccess.Mock.DalManager,DataAccess.Mock" />
<add key="NetDataPortalUri" value="net.tcp://localhost:8001/WindowsHost/WcfPortal.svc" />
<add key="SlDataPortalUri" value="http://localhost:8000/WindowsHost/SlPortal.svc" />
</appSettings>
Notice that the full URI for each endpoint is specified. These service endpoints are not hosted in
IIS or WAS, and so the host application has complete control over the URI that is exposed to the
clients.
The system.serviceModel entries are identical to those in the WASHost example I discussed in
the previous section. The endpoints for the .NET and Silverlight data portal hosts are configured,
along with custom bindings to set the message size limits to maximum.
The WindowsConsole and WpfUI applications should both be run when F5 is pressed to debug the
solution. To make this happen, I right-clicked the WindowsHost solution in Solution Explorer and
chose the Set Startup Projects menu item, resulting in the dialog shown in Figure 26.
You should be able to run the solution to launch the service in the console window, and the
WpfUI application in its own window. As you interact with the WpfUI application, it will use the data
portal to interact with the service running in the console window.
Because all the code is running in the debugger, it is easy to troubleshoot and solve any issues
with the code.
public DataPortalService()
{
InitializeComponent();
}
Because the DataPortalHost class in the WindowsHost project already implements the service
behaviors, the OnStart and OnStop methods can simply call the Start and Stop methods, just like in
the console application.
The WindowsHostService project also contains an app.config file that contains the
configuration for the application and the WCF endpoints. The contents of this file are exactly the
same as in the WindowsConsole project.
Using CSLA 4: Data Portal Configuration Page 51
Rev 0.4 (draft)
Installing the Windows Service
A Windows service must be installed into the operating system to run. Typically a service project
will include an installer class to make this possible. The WindowsHostService project contains the
ProjectInstaller class:
[RunInstaller(true)]
public class ProjectInstaller : Installer
{
private ServiceProcessInstaller process;
private ServiceInstaller service;
public ProjectInstaller()
{
process = new ServiceProcessInstaller();
process.Account = ServiceAccount.LocalSystem;
service = new ServiceInstaller();
service.ServiceName = "DataPortalService";
service.Description = "Example data portal service";
Installers.Add(process);
Installers.Add(service);
}
}
This requires that the project add a reference to the System.Configuration.Install assembly.
This class has the RunInstaller attribute, so the installutil.exe command line utility will
identify it as the installer for this assembly. The constructor of the class is responsible for installing
the assembly as a service. Notice how the service name and description are provided.
The installutil.exe command line utility is available from the Visual Studio Command Prompt.
The following command will install the service on your system:
installutil WindowsHostService.exe
Once the service is installed, it will appear in the Services administration console as shown in
Figure 28, with the name and description values from the ProjectInstaller class.
Make sure not to run the WindowsConsole application at the same time the service
is running, because they both attempt to use the same ports, and that will cause one
or both to fail.
At this point you should understand how to host the WCF data portal channel for .NET and
Silverlight in IIS, Windows Server AppFabric, Windows Azure, WAS, and in a custom Windows
service. These are all options for deploying the server-side components of your application to an
application server.
1. Silverlight client
2. Web server
3. Application server
There is nothing special or unique about the Silverlight client and application server
configuration to support a 4-tier deployment.
The web server configuration is unique, in that the web server is configured to accept incoming
requests from the Silverlight client, and it is also configured to use the .NET data portal to
communicate with the application server. In other words, the web server configures the data portal
as both a server and a client.
Client Configuration
The Silverlight client can be configured as I discussed earlier in this chapter. You can configure the
data portal using the ServiceReferences.ClientConfig file, or through code in the App.xaml.cs
file.
The Silverlight4Tier solution in the code download for this ebook includes a SilverlightUI
project. This is the Silverlight client application, and the data portal configuration is in its
App.xaml.cs file:
private void Application_Startup(object sender, StartupEventArgs e)
{
Csla.DataPortalClient.WcfProxy.DefaultUrl = "http://localhost:4108/SlPortal.svc";
this.RootVisual = new MainPage();
}
As I discussed earlier in the chapter, when running in Silverlight, the data portal defaults to using
the WCF data portal channel. The only required configuration is the URL of the server.
This URL is the address of the web server, not the application server. Again, the typical 4-tier
scenario is one where the Silverlight client can’t directly interact with the application server due to
network security limitations, so the only server it can call is the web server.
The web.config file also overrides the basicHttpBinding to set the message size limits and
includes the custom returnFaults behavior.
It also configures the client WCF endpoint, including the URL for the application server:
<client>
<endpoint name="WcfDataPortal"
address="http://localhost:4109/WcfPortal.svc"
binding="wsHttpBinding"
contract="Csla.Server.Hosts.IWcfPortal" />
</client>
Because the data portal is configured as a client, any data portal calls made by code running on
the web server will result in calling the server-side data portal components on the application
server.
The “magic” is that when a Silverlight client calls the data portal on the web server, the default
action is for the Silverlight data portal to call the .NET data portal to service the request. When the
.NET data portal is called, it is configured to invoke the server-side components on the application
server.
The result is that the data portal request from the Silverlight client is relayed through the web
server to the application server. The web server acts as a relay router for all data portal messages,
effectively allowing the client to interact with the application server.
In a real application the web.config file would probably contain the database connection strings
as well.
The web.config file also configures the .NET data portal endpoint:
<services>
<service name="Csla.Server.Hosts.WcfPortal"
behaviorConfiguration="returnFaults">
<endpoint binding="wsHttpBinding" bindingConfiguration="wsHttpBinding_IWcfPortal"
contract="Csla.Server.Hosts.IWcfPortal"/>
</service>
</services>
This is the standard endpoint configuration like in the previous examples, and the web.config
file also includes a customized wsHttpBinding and the returnFaults behavior.
The application server accepts data portal calls from the web server “client”. The web server is
acting as a relay point for messages from the actual Silverlight client.
Configuring this basic pass-through configuration is relatively straightforward. As you can see,
only the web server configuration is different, because it is configured as both a server endpoint
and data portal client.
I will now move on to discuss the ability to create and run object inspectors on the web server.
Method Description
Create Invoked by the data portal when a client-side request for a create operation arrives
at the web server
Fetch Invoked by the data portal when a client-side request for a fetch operation arrives
at the web server
Update Invoked by the data portal when a client-side request for an update operation
arrives at the web server
Delete Invoked by the data portal when a client-side request for a delete operation arrives
at the web server
Execute Invoked by the data portal when a client-side request for an execute operation
arrives at the web server
This allows the code in the inspector class to use the protected members of the ObjectFactory
class. Those members are listed in Table 4.
Member Description
LoadProperty Loads a property value without invoking authorization or business rules
ReadProperty Reads a property value without invoking authorization rules
MarkAsChild Invokes MarkAsChild on the target object (editable object only)
MarkNew Invokes MarkNew on the target object (editable object only)
MarkOld Invokes MarkOld on the target object (editable object only)
BypassPropertyChecks Gets the BypassPropertyChecks object from the target object (editable
object only)
CheckRules Invokes the CheckRules method on the target object’s BusinessRules
object (editable object only)
FieldExists Gets a value indicating whether a managed backing value already exists for
the target property
GetDeletedList Gets the DeletedList collection from a BusinessListBase or
BusinessBindingListBase object
SetIsReadOnly Sets the IsReadOnly property on a ReadOnlyListBase,
ReadOnlyBindingListBase, or NameValueListBase object
Create Operation
For example, the PersonEdit class is implemented so the data portal create operation always
occurs on the client, not on the server. This means that any request from a Silverlight client to
create a PersonEdit object on the server is invalid.
Using CSLA 4: Data Portal Configuration Page 60
Rev 0.4 (draft)
The Create method in the PersonEditInspector rejects all create requests:
public PersonEdit Create()
{
throw new NotSupportedException("Server-side create not supported");
}
If a client request shouldn’t be allowed to flow through to the application server, the object
inspector throws an exception to stop further processing of the request. The exception should
indicate why the request was rejected, so that information is available to the client application.
Fetch Operation
The data portal fetch operation is validated by the Fetch method in the PersonEditInspector
class:
public PersonEdit Fetch(int id)
{
return DataPortal.Fetch<PersonEdit>(id);
}
In this case, all client requests are relayed to the application server. This call to the data portal
Fetch method will automatically enforce any authorization rules associated with getting
PersonEdit objects, and the object inspector isn’t applying any additional rules to the process.
The fact that the authorization rule for the fetch operation is running on the web server adds a
level of security to the application. Even if a malicious user managed to hack the Silverlight runtime
on the client and bypass the authorization rules that would normally run on the client, the
appropriate authorization rules are run on the web server before the request is relayed to the
application server.
The assumption is that it is harder for a malicious user to alter running code on the web server
than for them to hack into the Silverlight runtime on the client.
Update Operation
The data portal update operation occurs when the editable root object is saved on the client with
the BeginSave method. That results in a client-side call to the data portal’s BeginUpdate method,
causing the data portal to invoke the server-side data portal on the web server. The server-side
code on the web server will invoke the Update method of any object inspector associated with the
editable root business class.
The PersonEditInspector implements the Update method:
public PersonEdit Update(PersonEdit obj)
{
CheckRules(obj);
if (!obj.IsValid)
throw new InvalidOperationException("Can not update invalid object");
else
return DataPortal.Update<PersonEdit>(obj);
}
This implementation demonstrates the most common action for an object inspector: re-running
the business rules for the business object.
On the Silverlight client, the BeginSave method only calls the data portal if the business object’s
IsValid property is true. Only valid objects can be saved.
Using CSLA 4: Data Portal Configuration Page 61
Rev 0.4 (draft)
If you assume that the code running on the client has been compromised by a malicious user,
they may attempt to save an invalid object. They might do that by rewriting your business rules in
memory, or by bypassing the IsValid property check.
Again, I am not aware of any reported instances of the Silverlight runtime being
hacked in this manner. Everything I’m discussing in this section is to protect against
hypothetical threats.
Acting under the assumption that it is harder for a malicious user to hack into your web server,
re-running the rules on the web server adds a level of security. The business code running on the
web server is presumably not compromised by the malicious user, so the rules that are run by the
CheckRules method in the PersonEditInspector object’s Update method are authentic rules.
If the resulting IsValid property remains true, then the data portal’s Update method is invoked
to relay the client request to the application server for processing.
Delete Operation
The data portal delete operation is handled just like the fetch operation. The data portal
automatically checks authorization rules before relaying the request to the application server, and
no additional checks are added by the object inspector:
public void Delete(int id)
{
DataPortal.Delete<PersonEdit>(id);
}
Execute Operation
There is no Execute method in the PersonEditInspector class, because the data portal execute
operation only applies to command object stereotypes that subclass CommandBase. An Execute
method for a command object looks much like the Fetch or Update methods shown earlier.
For example:
public MyCommand Execute(MyCommand obj)
{
return DataPortal.Execute<MyCommand>(obj);
}
The command object can be verified before relaying the request to the application server.
MobileFactory Attribute
At this point you know how to implement an object inspector class. The MobileFactory attribute is
used to link the root business type to its associated object inspector class.
For example, the PersonEdit class in the Library.Net project includes this attribute:
[Serializable]
[Csla.Server.MobileFactory("ObjectInspectors.PersonEditInspector,ObjectInspectors")]
public class PersonEdit : BusinessBase<PersonEdit>
That class name is combined with a specific namespace and assembly name to create the
assembly qualified type name in the mobile factory loader:
public class MobileFactoryLoader : Csla.Server.Hosts.Silverlight.IMobileFactoryLoader
{
public object GetFactory(string factoryName)
{
return Activator.CreateInstance(GetFactoryType(factoryName));
}
A mobile factory loader must implement two methods as defined by the IMobileFactoryLoader
interface in the Csla.Server.Hosts.Silverlight namespace.
The GetFactoryType method is responsible for creating a .NET Type object for the object
inspector class. In this example you can see how the factoryName parameter is combined with a
Using CSLA 4: Data Portal Configuration Page 63
Rev 0.4 (draft)
hardcoded namespace and assembly name to create a full type name. That value is passed to the
GetType method of the .NET Type class to create the Type object.
The GetFactory method is usually simpler, and uses the CreateInstance method of the
Activator type to create an instance of the Type object returned by the GetFactoryType method.
The reason CSLA .NET allows the creation of a custom mobile factory loader is to enable flexibile
creation of object inspector instances. You might use direct type loading techniques like I show in
this example. Or you might choose to create the objects using the Managed Extensibility
Framework (MEF), or an IoC container, or other object creation technologies.
Most applications can use the default mobile factory loader, where the MobileFactory
parameter is the assembly qualified type name of the object inspector class.
In this chapter you have learned how to configure and use the data portal to deploy CSLA .NET
applications in 1-, 2-, 3-, and 4-tier physical scenarios. This includes the use of the local data portal
channel for 1- and 2-tier deployments. The chapter also provided an in-depth discussion of the WCF
data portal channel for 3- and 4-tier deployments.
Setting Description
CslaDataPortalProxy Specifies the assembly qualified type name of the client-side
data portal proxy to be used by the data portal; the value
Local is a special value indicating that the data portal
should run in 1- or 2-tier local mode (Local is the default);
proxy types must implement IDataPortalProxy
CslaDataPortalUrl Set this value to the URL of the remote service to be used
by the client-side proxy; the WcfProxy and RemotingProxy
objects default to using this value to locate the service on
the application server
CslaSerializationFormatter Set this value to NetDataContractSerializer to indicate
that CSLA .NET should use the WCF
NetDataContractSerializer type for all serialization
operations, including in-memory object serialization as well
as in the data portal
CslaAuthentication Set this value to Windows to indicate that the data portal
should use Windows integrated authentication, allowing the
operating system to follow its normal impersonation rules;
any other value indicates the use of custom authentication
and the data portal will automatically transfer the client
principal to the server with every data portal call
CslaAuthorizationProvider Specifies the assembly qualified type name of a server-side
type that implements IAuthorizeDataPortal; this type is
used to create an object that authorizes every data portal
call immediately after the request has been deserialized and
before any further work occurs on the server
CslaObjectFactoryLoader Specifies the assembly qualified type name of a server-side
type that implements IObjectFactoryLoader; this type is
Using CSLA 4: Data Portal Configuration Page 65
Rev 0.4 (draft)
responsible for interpreting the factory name specified in
each ObjectFactory attribute; this type implements the
code that creates the specified factory object
CslaMobileFactoryLoader Specifies the assembly qualified type name of a server-side
type that implements IMobileFactoryLoader; this type is
responsible for interpreting the factory name specified in
each MobileFactory attribute; this type implements the
code that creates the specified inspector object used to
verify calls from Silverlight and WP7 clients
CslaDataPortalExceptionInspector Specifies the assembly qualified type name of a server-side
type that can re-write server exceptions before they are
returned through the data portal to the client
CslaAutoCloneOnUpdate Set this to False to disable the automatic cloning of the
object graph before Update and Execute operations; make
sure you have implemented an alternative solution to
handle persistence failure scenarios before altering this
value
CslaDataPortalProxyFactory Specifies the assembly qualified type name of the client-side
data portal proxy factory, which is the object responsible for
creating instances of the data portal proxy type; this type
must implement IDataPortalProxyFactory; the value
Default is a special value indicating that the data portal
should use its default factory that creates an instance of the
type specified by the CslaDataPortalProxy setting
CslaAlwaysImpersonate (RemotingProxy only) Set this value to true to cause the
RemotingProxy to always pass the client-side Windows
user identity to the application server
CslaEncryptRemoting (RemotingProxy only) Set this value to true to cause the
RemotingProxy to use encryption for server
communication
Setting Description
DataPortal.ProxyTypeName Specifies the assembly qualified type name of the client-side
data portal proxy to be used by the data portal; the value
Local is a special value indicating that the data portal
should run in 1-tier local mode; proxy types must
implement IDataPortalProxy; WP7 default is Local,
Silverlight default is the CSLA .NET WcfProxy type
DataPortal.ProxyFactory Gets or sets a reference to the ProxyFactory object that is
used to create an instance of the client-side proxy object;
this value defaults to a factory that creates an instance of
the DataPortal.ProxyTypeName property
WcfProxy.DefaultUrl This URL value is used to locate the data portal service on
the application server; default is null (meaning settings in
ServiceReferences.ClientConfig are used)
WcfProxy.DefaultBinding Specifies the default WCF binding to be used by the
WcfPortal proxy; default is BasicHttpBinding with
maximum message size and timeout values
WcfProxy.DefaultEndPoint Specifies the end point name the WcfProxy should use to
load its configuration from the application’s
ServiceReferences.ClientConfig file; the config file
values are used if either the DefaultUrl or
DefaultBinding properties are null
Csla.ApplicationContext. If set to Windows, the client-side principal will not flow to
AuthenticationType the server on each data portal request, otherwise the data
portal will always impersonate the client-side user on the
application server; default is “Csla”
In a WP7 application this code will typically be in the constructor for the App class:
public App()
{
Csla.DataPortal.ProxyTypeName = "Local";
The .NET data portal channels use either the NDCS or the BinaryFormatter to serialize and
deserialize your object graphs. The WCF data portal channel uses the NDCS, because that is how
WCF serializes data for transfer over the network. Even when the WCF data portal channel is used,
CSLA .NET defaults to using the BinaryFormatter for all serialization operations outside the data
portal. You can use the CslaSerializationFormatter configuration setting to override this default
behavior.
The Silverlight and WP7 platforms have restrictions on .NET reflection that prevents reflection
from getting or setting non-public property values in an object. Because the BinaryFormatter and
NDCS rely directly on that feature of reflection, those serializers do not exist in Silverlight.
To overcome the fact that those serializers don’t exist in Silverlight, and the fact that CSLA .NET
requires the features provided by those serializers, CSLA 4 includes the MobileFormatter. The
MobileFormatter is a serializer that operates without needing reflection to access non-public
property values, and yet is able to serialize and deserialize object graphs with 100% fidelity.
When CSLA .NET is running on Silverlight and WP7 it uses the MobileFormatter in place of the
BinaryFormatter or NDCS. Additionally, a .NET application server that exposes a data portal
endpoint for a Silverlight client will use the MobileFormatter to serialize and deserialize messages
that flow between the client and server.
The MobileFormatter can only serialize primitive values, or objects that implement
the IMobileObject interface.
The Csla.Core namespace includes the set of base types listed in Table 7 that already
implement this interface.
1. The application uses multiple application servers, where some objects need to be routed to
one server, and other objects need to be routed to a different server
2. The application supports online and offline functionality, and the data portal should use the
local proxy when offline, and the WCF proxy when online
I will also discuss how to implement compression for the Silverlight data portal. This involves
customizing the client-side proxy and server-side host types.
AppServer Attribute
The AppServerAttribute class implements the AppServer attribute. This attribute is applied to root
business types in the Library.Net project to indicate the application server that should be used for
that business type. For example:
[AppServer(ServerName = "Server1")]
[Serializable]
public class OneTest : BusinessBase<OneTest>
The class inherits from the .NET Attribute type, and defines the ServerName property that
contains the name of the application server.
The AttributeUsage attribute restricts the usage of this new AppServer attribute so it can only
be used on class definitions.
WcfProxy Class
The standard CSLA .NET WcfProxy type is found in the Csla.DataPortalClient namespace. It gets
the application server URL from the application’s configuration file. The value comes from either
the CslaDataPortalUrl configuration value, or from the endpoint definition in the
system.serviceModel configuration section.
Because the new SmartProxy data portal proxy will be setting the URL dynamically at runtime, it
is necessary to customize the default behavior of the standard WcfProxy type by overriding the
GetChannelFactory method. This is done by implementing a subclass:
public class WcfProxy : Csla.DataPortalClient.WcfProxy
{
public WcfProxy(string serverUrl)
{
_serverUrl = serverUrl;
}
SmartProxy Class
The SmartProxy class contains the implementation of the custom proxy. This data portal proxy uses
the AppServer attribute to get the name of the application server, and it uses that name to retrieve
the server’s URL from the application’s configuration file. It then creates an instance of the
WcfProxy subclass to communicate with that application server at that URL.
Because the network communication is handled by the WcfProxy object, the code in the
SmartProxy class is completely focused on getting the server URL. Here’s the code:
public class SmartProxy : Csla.DataPortalClient.IDataPortalProxy
{
private WcfProxy GetProxy(Type objectType)
{
string serverName = null;
var att = objectType.GetCustomAttributes(typeof(AppServerAttribute), false);
if (att.Length > 0)
{
var asa = (AppServerAttribute)att[0];
serverName = asa.ServerName;
}
var serverUrl = ConfigurationManager.AppSettings[serverName];
return new WcfProxy(serverUrl);
}
The first thing to note is that the SmartProxy type implements the IDataPortalProxy interface
from the Csla.DataPortalClient namespace. This interface is used by the data portal to
Using CSLA 4: Data Portal Configuration Page 75
Rev 0.4 (draft)
communicate with all proxy objects. The interface requires that the class implement the members
listed in Table 8.
Member Description
IsServerRemote Gets a value indicating whether the application server is physically remote, or is
running in the same AppDomain as the client code
Create Invokes the server-side data portal to perform a create operation
Fetch Invokes the server-side data portal to perform a fetch operation
Update Invokes the server-side data portal to perform an update or execute operation
Delete Invokes the server-side data portal to perform a delete operation
This method uses reflection to get the AppServer attribute from the root business object type,
and then gets the server name from the attribute. The server name is used as the key to look up the
server’s URL from the application’s configuration file. That URL is used to create an instance of the
WcfProxy subclass.
This tells the data portal that it should use the SmartProxy type from the CustomProxy assembly
to handle all data portal requests.
Also notice that the Server1 and Server2 key values are associated with the URLs of the two
application servers.
Using CSLA 4: Data Portal Configuration Page 76
Rev 0.4 (draft)
Client applications on Silverlight or WP7 set the ProxyTypeName property of the DataPortal class
to specify the client-side proxy. This is typically done as the application starts up, in the
App.xaml.cs class. For example:
Csla.DataPortal.ProxyTypeName = typeof(CustomProxy.SmartProxy).AssemblyQualifiedName;
Because there is no System.Configuration API on Silverlight, you would need to use a different
technique to maintain the mapping from application server name to server URL on a Silverlight
client.
At this point you should understand how to create a custom client-side data portal proxy that
routes data portal requests to concrete proxy objects for server communication. You can use this
technique to support the use of multiple application servers for an application.
This also requires that your application implement two data access layers, one for
the application server and one for the client.
The client-side data portal uses a data portal proxy factory to create the proxy object that is used
by the data portal. The default data portal proxy uses the CslaDataPortalProxy configuration value
to identify this type on .NET, and the ProxyFactory property on the DataPortal type on Silverlight.
You can implement your own proxy factory, and your implementation can create the proxy
object following more complex rules. The ProxyFactorySl solution in the code download for this
ebook is an example of a custom proxy factory implementation. Figure 34 shows the projects that
make up this solution.
The implementation of the DAL interfaces in the ClientDal and ServerDal projects will almost
certainly be different, because they are running on the client and server and will use different data
access technologies and databases. The key is that their interfaces are the same, and so the code in
the business classes remains reasonably consistent for online and offline environments.
Figure 35 illustrates the relationship between the projects in the solution.
If the WcfProxy is used, the server-side components will run on the .NET application server, so
the Library assembly compiled for .NET invokes the data access components available on the
application server, so the DAL implementation is in the ServerDal project.
On the other hand, if the LocalProxy is used, the “server-side” components run on the
Silverlight client, and so use the Library assembly compiled for Silverlight. That assembly invokes
the data access components available on the Silverlight client, where the implementation is in the
ClientDal project.
The class overrides the GetProxy method overloads, making use of an Offline value from the
LocalContext dictionary in Csla.ApplicationContext to determine whether the application
should run in online or offline mode.
If the application is configured to run offline, or a local proxy is specifically requested, an
instance of LocalProxy is returned, otherwise an instance of WcfProxy is the result.
In a complete application, you would implement manual or automatic detection of the
application’s online or offline state, and would set the configuration value based on the application
state. The sample application sets the value in the TestItemViewModel class in the ProxyFactorySl
UI project. The value is data bound to a check box control in the UI, making it easy to switch
between online and offline modes.
In a Silverlight application like the ProxyFactorySl sample, the proxy factory is set through code
as the application starts up. The App.xaml.cs file contains this code:
private void Application_Startup(object sender, StartupEventArgs e)
{
Csla.ApplicationContext.LocalContext.Add("Offline", false);
Csla.DataPortal.ProxyFactory = new ProxyFactory();
Csla.DataPortalClient.WcfProxy.DefaultUrl = "http://localhost:13325/SlPortal.svc";
DataAccess.DalFactory.DalType = typeof(Dal.DalManager);
this.RootVisual = new MainPage();
}
The ProxyFactory property of the DataPortal class is set to an instance of the custom proxy
factory type:
Csla.DataPortal.ProxyFactory = new ProxyFactory();
This will cause the data portal to use the custom type to create instances of the data portal
proxy objects as necessary.
At this point you should understand how to implement a custom proxy factory by subclassing
the ProxyFactory class in the Csla.DataPortalClient namespace. A proxy factory allows you to
control the proxy object created by the data portal to service data portal requests, and you can see
how this can be used to support online and offline application models.
http://www.icsharpcode.net/OpenSource/SharpZipLib/
http://www.codeplex.com/slsharpziplib
There are two assemblies, one for .NET and one for Silverlight. The important feature is that they
use the same compression algorithms on both platforms, and so can compress and decompress
each other’s data.
Any compression library that can compress and decompress byte arrays or .NET
Stream objects can be used, as long as the library supports both .NET and Silverlight.
CompressionUtility Class
The open source SharpZipLib library used in the solution provides a low-level API that is used to
compress and decompress Stream objects. The CSLA .NET API provided to the subclasses of
WcfProxy and WcfPortal works with byte arrays. Fortunately the .NET MemoryStream type can be
used to easily convert between a byte array and a stream.
The CompressionUtility class in the CompressedHost and CompressedProxy projects
implements Compress and Decompress methods that encapsulate the use of the SharpZipLib
library.
You can look at this class to see how it works if you are interested. For the purposes of the
discussion in this ebook, it is enough to understand that the Compress method accepts a byte array
containing the original data and returns a byte array of compressed data. Similarly, the Decompress
method accepts a byte array of compressed data, and it returns a byte array of uncompressed data.
The CompressionUtility is used to implement the custom proxy and host.
This class inherits from the standard WcfProxy class provided by CSLA .NET. The CSLA .NET class
exposes three protected methods that are overridden to implement compression. The two
ConvertRequest method overloads convert a criteria-based and update request respectively.
The request parameter provided to each of these methods contains the serialized object graphs
that will be sent to the application server. You may choose to compress some or all of this serialized
data.
In many cases you’ll compress all the data as shown here. But you may choose to implement a
more sophisticated algorithm where you only compress the data if it is of a certain size. There is a
performance cost involved in compressing and decompressing data, and it can be argued that small
byte arrays shouldn’t be compressed, because the reduction in network bandwidth usage can’t
offset the performance cost of the compression.
The ConvertResponse method is invoked to decompress data coming from the server. Again, the
request parameter contains the byte arrays of compressed data, each of which corresponds to a
serialized object graph from the server. The data must be decompressed before it is returned, so
the data portal can properly deserialize the byte arrays into object graphs on the client.
Like the proxy, this class overrides the two ConvertRequest methods to process the data coming
from the client. The client has compressed this data, so on the server the data is decompressed.
The ConvertResponse method is invoked as data is flowing from the server back to the client.
The byte arrays contain serialized object graph data, and must be compressed before they are
returned to the client.
Notice how the client and server are mirrors of each other. Where one compresses data, the
other decompresses the data. The end result is that the serialized object graphs flowing to and from
the server are serialized and compressed before going across the network.
The ProxyTypeName property of the DataPortal class is set to the type name of the
CompressedProxy type. This causes the data portal to use this custom proxy instead of the default
proxy, ensuring that all data flowing to and from the server is compressed and decompressed.
The rest of the endpoint configuration is no different from the configurations you’ve seen
throughout this book.
At this point the client and server are configured to use the CompressedProxy and
CompressedPortal respectively, and the data flowing across the network is compressed.
This chapter has demonstrated how to create custom data portal proxy and host types to enable
some common scenarios, including support for multiple application servers, online and offline
mode, and data compression for Silverlight and WP7 client applications.
If you implement your own authorization rules, you can use any data or information available to
your application’s code. But in almost all cases, authorization rules rely on access to the current
user identity and related information.
Authentication is the process of confirming the identity of the user, and establishing a principal
object for that user. This chapter will focus on the options available within CSLA .NET for
authenticating the user, and for making user information available to the rest of the application.
CSLA .NET supports three authentication models:
1. Custom authentication
The implementation of these authentication models is slightly different on .NET and Silverlight,
but the basic concepts and overall coding structure are consistent.
Authentication Concepts
The .NET Framework stores the current user’s identity and information in a principal object. This
principal object can be accessed through several techniques.
The .NET Framework provides some pre-existing principal types you can use in your applications.
It also defines interfaces you can implement to create custom principal types. The primary
mechanism you’ll use to maintain additional user information for your application is to create a
custom identity class.
The IsAuthenticated property returns a Boolean value indicating whether the current user has
been authenticated. The AuthenticationType property returns a string value indicating how the
user was authenticated. There is no standardization for the AuthenticationType value, so you’ll
have to experiment to find out what values it might contain, before using the value.
The Name property returns a string value containing the username of the current user. This is
only the Windows username when Windows authentication is used. When using custom or
Membership authentication, the username value comes from the security database.
In Visual Basic you can also use My.User to access this value.
In an ASP.NET application you can access the current principal through the User property of the
current HttpContext object. For example:
var principal = HttpContext.Current.User;
The fact that the value is available from at least three different locations in the .NET Framework
is confusing. To make things more complex, only the HttpContext value is reliable when building
web applications, but HttpContext isn’t available at all when building non-web applications.
This means that if you want to write code, such as a reusable business library, that works
properly in ASP.NET and other non-web applications, you need to write code to get the principal
object correctly depending on the environment in which your code is running.
This User property automatically adapts, and retrieves the principal from the HttpContext or the
Thread when appropriate, and overcoming the auto-reset behaviors of WPF.
The way CSLA .NET adapts the User property behavior is by having different implementations for
each runtime scenario. The implementations are contained in technology-specific assemblies
included with the CSLA .NET framework. Table 9 lists the runtime scenarios and required assembly
references.
Type Description
GenericPrincipal Simple implementation of principal that contains an IIdentity object, and a
list of roles for the current user
GenericIdentity Simple implementation of identity that contains values for IsAuthenticated,
AuthenticationType, and Name
WindowsPrincipal Principal that contains a WindowsIdentity object, and provides access to the list
of Windows domain or Active Directory groups for the user
WindowsIdentity Represents the Windows identity for the current user, or an impersonated user
FormsIdentity Identity that contains the current user’s ASP.NET security token for ASP.NET
forms authentication; typically contained within a GenericPrincipal
RolePrincipal Principal that contains a user’s roles from the ASP.NET RoleProvider; used as
part of Membership Provider authentication
Type Description
ICheckRoles Interface that enables a principal to ask its identity to check roles
CslaPrincipal Principal base class that contains an IIdentity object; if the identity
object implements ICheckRoles the principal delegates all IsInRole
checks to the identity object; subclass CslaPrincipal to create your
own custom principal
Value Description
IsAuthenticated Boolean property indicating whether the current user is authenticated
AuthenticationType string property that returns the type of authentication used
Name string property that returns the username of the current user
Roles List of string values, each value representing a role to which the user
belongs
Impersonation
In a 3- or 4-tier physical deployment, it is usually desirable for the application server code to run
under the same security context as the client code. This means that the application server’s
principal object should be the same as the principal object on the client.
The process of ensuring that the application server uses the same principal as the client is called
impersonation, because the application server is impersonating the client user.
Implementation of impersonation depends on the type of authentication used by your
application, and by the types of technologies being used on client and server.
Using CSLA 4: Data Portal Configuration Page 90
Rev 0.4 (draft)
Although I’ll demonstrate several common impersonation scenarios as I walk through the
authentication sample applications throughout this chapter, this section will provide an overview of
the concepts and techniques involved for each type of authentication and client/server technology.
If you decide to recreate the principal on each request, the client should pass the username to
the server using the ClientContext dictionary in the Csla.ApplicationContext class. On the
application server, you should implement an IAuthorizeDataPortal provider (as shown later in this
chapter) that uses the username value to retrieve the principal and identity objects from the
security database. The resulting principal object should be set as the User property of the
Csla.ApplicationContext class, effectively providing the server with the same principal as the one
on the client.
Windows Authentication
Windows authentication relies on the Windows operating system to manage the user’s identity,
and to implement impersonation.
You should be aware that Windows impersonation can only take one “network
hop”. This means the application server can impersonate the client user, but then
the database server can’t impersonate the same user because that would be two
hops. This is a limitation of Windows security, and can be overcome by configuring
your Windows security domain to use Kerberos security. The use of Kerberos
security is outside the scope of this book.
When using Windows authentication, the user provides their credentials to the Windows
operation system, and Windows authenticates the user. The current principal is then a
WindowsPrincipal, containing a WindowsIdentity object.
You must configure IIS and ASP.NET on the application server to perform impersonation, at
which point Windows will automatically impersonate the client user on the application server.
The CSLA .NET authentication type should be set to Windows on the client and server. This causes
the data portal to not attempt to pass the client-side principal to the server. The WindowsPrincipal
and WindowsIdentity types are not serializable, so if the data portal does attempt to serialize them
to the server the result will be an exception.
At this point you should have a basic understanding of the .NET principal and identity object
concepts, and how they are accessed in .NET and Silverlight applications. You should also realize
that the .NET Framework and the CSLA .NET framework supply pre-existing principal and identity
types you can use in your applications.
I will now move on to discuss specific implementations of the custom, ASP.NET membership, and
Windows authentication models.
Custom Authentication
The Authentication folder in the code download for this ebook contains three solutions: Custom,
Membership, and Windows. I will be walking through the key parts of each solution through the rest
of this chapter. You should understand that ASP.NET membership authentication builds on the
concepts of custom authentication. In Silverlight and WP7, the Windows authentication solution
also builds on the concepts of custom authentication.
Custom authentication is demonstrated in the Custom solution in the Authentication folder of
the code download for this ebook. The solution contains several projects, including WPF, ASP.NET
MVC, Silverlight, and WP7 applications that share common business library code. Because there are
differences in how authentication is implemented in different application types, I will discuss each
Implementing CustomPrincipal
The CustomPrincipal class can be found in the Library.Net project. It is also linked into the
Library.Sl and Library.Wp projects to support Silverlight and WP7 applications with the same
code.
As I mentioned earlier, this is a subclass of the CslaPrincipal base class, and most of the code
implements static methods for the login and logout operations:
[Serializable]
public class CustomPrincipal : CslaPrincipal
{
private CustomPrincipal(CustomIdentity identity)
: base(identity)
{ }
#if !SILVERLIGHT
public static void Login(string username, string password)
{
There are four static methods: BeginLogin, Login, Load, and Logout. I’ll discuss the two login
methods, then the Load method, and finally the Logout method.
Login Methods
The login methods are called by the application to login the user, using the credentials supplied by
the user to prove their identity.
Although the example BeginLogin and Login methods require a username and password, your
methods could require other types of credentials. For example, some applications might also
require a PIN number, or a byte array containing fingerprint or smartcard data. Your methods must
require whatever credential values are required to authenticate the user against your custom
security database or service.
Notice how the BeginLogin and Login methods invoke the static factory methods on the
CustomIdentity class. Those static factory methods are normal read-only stereotype factory
methods that invoke the data portal to retrieve an instance of the CustomIdentity type.
The resulting CustomIdentity object is then used to create a new instance of the
CustomPrincipal type. Remember that all principal objects contain one identity object. To create
an instance of a principal object, you must pass its identity object into the constructor.
The resulting CustomPrincipal object is used to set the User property of the
Csla.ApplicationContext type. Setting the User property automatically makes this new value the
principal the current principal for the .NET thread, current HttpContext, or Silverlight application.
It is important to recognize that this process doesn’t throw an exception if the user’s credentials
are invalid. In other words, if the user provides an incorrect username or password, the result is not
an exception. Instead, the result is that the current principal is set to a valid principal object that
contains an identity object with an IsAuthenticated property value of false. Additionally, the
principal contains no roles, so the user is unauthenticated and isn’t in any roles.
On the other hand, if the user provides valid credentials, the result is that the current principal
will be set to an authenticated value that contains the user’s roles.
Load Method
The Load method is similar to the login methods, except that it only requires the username, not the
full set of credentials. This method is used by the ASP.NET MVC application to load the user’s
Using CSLA 4: Data Portal Configuration Page 95
Rev 0.4 (draft)
principal and identity on each HTTP request. The same technique would be used in a Web Forms or
WCF service application that follows a stateless web server architecture.
In a stateless web server architecture, the web server remembers nothing between page
requests or server calls. This means the server doesn’t have an instance of the user’s principal when
a request comes in from the browser or consumer.
ASP.NET does keep track of the user’s username and whether the user’s security cookie or token
is still valid. As you’ll see when I walk through the ASP.NET MVC implementation, code in
Global.asax.cs runs on each request and uses that username value to call the Load method of the
CustomPrincpal class to load the principal and identity objects.
The Load method requires that the CustomIdentity class have a factory method that only
requires the username.
Logout Method
The Logout method sets the User property of the Csla.ApplicationContext type to a new instance
of the UnauthenticatedPrincipal type. When an UnauthenticatedPrincipal object is created, it
automatically sets its identity to a new instance of the UnauthenticatedIdentity class. The result is
that the current principal and identity is set to represent an unauthenticated user with no roles.
Implementing CustomIdentity
The CustomIdentity class is also found in the library projects. This class inherits from the
CslaIdentityBase class, and follows the read-only object stereotype described in the Using CSLA 4:
Creating Business Objects ebook:
[Serializable]
public class CustomIdentity : CslaIdentityBase<CustomIdentity>
The CslaIdentityBase class already implements the properties required by the IIdentity
interface from the System.Security.Principal namespace. These properties were listed earlier in
the chapter, in Table 12.
When adding custom properties, it is important to remember that these properties add to the
object’s state. In most cases, this means they increase the size of the data flowing between the
client and server on each data portal call. By default, a custom principal (and its identity object) flow
from the client to the server on each data portal call.
#if !SILVERLIGHT
public static CustomIdentity GetCustomIdentity(string username, string password)
{
return DataPortal.Fetch<CustomIdentity>(new UsernameCriteria(username, password));
}
There are asynchronous and synchronous methods to validate the user’s identity and retrieve a
CustomIdentity object based on the username and password values provided by the static login
methods in the CustomPrincipal class.
These methods make use of the UsernameCriteria class from the Csla.Security namespace.
This is a standard criteria class that contains Username and Password property values.
2. Retrieve the user’s list of roles (if using a role-based authorization model)
3. Retrieve any user profile data required by your custom identity (if any)
The example CustomIdentity class is implemented using the encapsulated invoke data access
model as discussed in the Using CSLA 4: Data Access ebook. You may choose to use the factory
implementation, or any of the other data access models in your application. Remember that this is
just a read-only business object, so any data access model will work.
Here’s the business class code from the Custom solution:
private void DataPortal_Fetch(UsernameCriteria criteria)
{
AuthenticationType = "Custom";
var dal = new DataAccess.IdentityDal();
if (dal.VerifyUser(criteria.Username, criteria.Password))
LoadUserData(criteria.Username, dal);
}
The two DataPortal_Fetch overloads are required because the factory methods pass either a
UsernameCriteria or the single username value.
The overload that accepts the UsernameCriteria parameter calls a VerifyUser method exposed
by the data access provider. This method returns a value indicating whether the credentials
supplied by the user match those in the security database or service.
If the credentials don’t match, no exception is thrown. Instead, the CustomIdentity is returned
with its default values. Most importantly, the IsAuthenticated property is false, indicating that
the identity represents an unauthenticated user.
You should not throw an exception when the credentials can’t be verified. The .NET
Framework’s authentication model is not designed to support an exception-based
model, and expects a valid (if unauthenticated) identity to be returned when
authentication fails.
If the credentials are verified, the LoadUserData method is invoked to load the user’s profile and
role information. The DataPortal_Fetch overload that accepts only the username value always
invokes the LoadUserData method.
The LoadUserData method calls the data access provider to get the user’s profile information.
That’s the FullName value in the example code. It also retrieves the list of roles or groups to which
the user belongs.
The CslaPrincipal base class provides an IsInRole method implementation that delegates to
the identity object if that object implements the ICheckRoles interface from the Csla.Security
namespace. The CslaIdentityBase class implements ICheckRoles by checking the list of roles in
the object’s Roles property. This simplifies retrieval of the user information, because the user’s
authentication status, profile data, and roles are all maintained by one object: the custom identity
object.
You can look at the IdentityDal class in the DataAccess project to see the implementation of
the data access code. The code uses LINQ queries against an in-memory mock database as
described in the Using CSLA 4: Data Access ebook.
At this point you should understand how to implement custom principal and identity classes to
support custom authentication for any CSLA .NET application. The one area you’ll need to focus on
is the data access implementation, where the user’s credentials are verified, and the user profile
and role information is retrieved.
I will now cover how to configure the application server, and then briefly discuss how the static
login methods implemented in the CustomPrincipal class are used by the various types of
applications supported by CSLA .NET.
Custom Impersonation
You can configure the client application to not pass the client-side principal to the server on each
data portal request. I’ll discuss how this is done as I talk about each type of client application.
The value of preventing the principal from being serialized to the server on each request is that
your application will consume less bandwidth on the network. The downside to this choice, is that
the server will need to retrieve the user’s identity object from the security database or service on
every data portal request.
Setting CslaAuthorization
The first step is to configure the data portal to use the Windows authentication type in the server’s
web.config file:
Using CSLA 4: Data Portal Configuration Page 100
Rev 0.4 (draft)
<appSettings>
<add key="CslaAuthentication" value="Windows"/>
</appSettings>
This may be a little confusing, because the application is not using Windows authentication, it is
using custom authentication.
When the server-side data portal is configured with the authentication type of Windows, it
requires that the client not pass a principal to the server through the data portal. And this setting
will cause the data portal to not explicitly set the server-side principal value.
Normally the assumption is that the Windows operating system will perform the impersonation,
but in this case ASP.NET is not configured to impersonate the client user. The result is that the
server principal isn’t set to any explicit value.
That works well, because the application will be setting the value in a custom authorization
provider.
Implementing IAuthorizeDataPortal
Retrieving the principal on each server request is done with a custom authorization provider.
Immediately after deserializing the client request, the data portal can invoke an authorization
provider. This is a class that implements the IAuthorizeDataPortal interface from the
Csla.Server namespace.
This provider will have access to the ClientContext and GlobalContext dictionaries from the
client, as well as other information about the data portal request. This provider can set the current
principal of the server thread based on that information.
If the client doesn’t pass the client-side principal to the server, it does need to pass the
username value. I typically pass the username value to the server by using the ClientContext
dictionary.
The Custom solution contains a custom authorization provider in the AuthorizeDataPortal class
in the Library.Net project. The application server’s web.config must tell the data portal to use this
type by setting the CslaAuthorizationProvider value:
<appSettings>
<add key="CslaAuthentication" value="Windows"/>
<add key="CslaAuthorizationProvider" value="Library.AuthorizeDataPortal, Library"/>
</appSettings>
The Authorize method is invoked by the data portal for each data portal request. It is important
to remember that server-side code can invoke the data portal too, so one client-side data portal
request might result in numerous calls to the Authorize method. Only the first call on the thread is
the one that came from the client.
The implementation in the AuthorizeDataPortal class is designed to automatically enable if the
CslaAuthentication configuration value is Windows. Otherwise it does no work.
Also, the implementation only runs on the first data portal request on the thread. That is the
request that came from the client, and all subsequent requests are known to be completely server-
side data portal calls. The LocalContext dictionary is used to maintain a FirstRun flag for this
purpose.
Although you might be tempted to use a static field for this value, it is important to remember
that static fields are shared across the AppDomain, and so are not per-thread. A static field
would be shared across multiple concurrent data portal requests from different users, and so would
not work. The CSLA .NET LocalContext dictionary is per-thread.
The username value is retrieved from the ClientContext dictionary. This dictionary flows from
the client to the server with each data portal request, and is designed to be used for this type of
scenario.
Once the code has the username value from the client, it can call the Load method on the
CustomPrincipal class. That method uses the synchronous factory method on the CustomIdentity
class to retrieve the user’s identity object. It then sets the current principal to an instance of the
CustomPrincipal type.
The result is that, on each data portal request from the client, the thread servicing that request
has the correct principal object, loaded fresh from the security database or service.
You can use the default data portal impersonation, or custom impersonation, as appropriate for
your application. The important thing to keep in mind is that the client and server must be
configured to use the same type of impersonation.
I’ll now move on to briefly discuss the configuration of each type of client application.
The viewmodel also exposes the identity object so the view can bind to its properties. For
example:
<TextBox Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="3"
Name="authenticationTypeTextBox"
Text="{Binding Path=Identity.AuthenticationType, Mode=OneWay}"
VerticalAlignment="Center" Width="120" IsReadOnly="True" />
The application can be configured to use the default data portal impersonation, or custom
impersonation.
If you wanted to perform the login operation synchronously, the code would look like this:
public MainWindowViewModel()
{
CustomPrincipal.Login("rocky", "test");
OnPropertyChanged("Identity");
OnPropertyChanged("IsAdmin");
OnPropertyChanged("IsGuest");
ApplicationReady = true;
}
Either way, the static login method on the CustomPrincipal class is invoked to authenticate
the user’s credentials. When that process is complete, the current principal will be set to an
authenticated or unauthenticated principal object, depending on whether the credentials were
verified.
In a more complete application, this code would run once the user has entered their credentials
into some sort of login dialog or UI control. I’ll show a more complete example of the login process
in the Using CSLA 4: Silverlight 4 and WPF ebook.
The OnPropertyChanged method calls in MainWindowViewModel raise the ProperyChanged event
so WPF data binding refreshes the display. The results are shown in Figure 37.
This is expected, based on the data loaded into the mock database in the Database project:
static MockDb()
{
Users = new List<User>
{
new User { Username = "rocky", Password="test", FullName = "Rocky Lhotka" }
};
UserRoles = new List<UserRole>
{
new UserRole { Role = "Admin", Username = "rocky" }
};
}
This principal object will flow from the client to the application server with each subsequent data
portal call, ensuring that any authorization code running on the application server will run against
the same user principal and identity as the code on the client workstation.
Setting the CslaAuthentication value to Windows causes the client-side data portal to not pass
the client-side principal to the server with each data portal request.
Second, the client must pass the username value to the application server. You may remember
that the IAuthorizeDataPortal implementation shown earlier in this chapter expected the
username to be in the ClientContext dictionary. The client application must set that value as part
of the login process.
The MainWindowViewModel is where the login process occurs in the example code, and that’s
where the username value is added to the dictionary:
public MainWindowViewModel()
{
CustomPrincipal.BeginLogin("rocky", "test", (ex) =>
{
if (ex != null)
MessageBox.Show(ex.ToString());
OnPropertyChanged("Identity");
OnPropertyChanged("IsAdmin");
OnPropertyChanged("IsGuest");
ApplicationReady = true;
Using CSLA 4: Data Portal Configuration Page 105
Rev 0.4 (draft)
// if we are not using auto-impersonation, then
// set a ClientContext value so the username flows
// to the server, so the server can create its own
// principal object on each data portal request
if (Csla.ApplicationContext.AuthenticationType == "Windows")
Csla.ApplicationContext.ClientContext["Username"] =
Csla.ApplicationContext.User.Identity.Name;
});
}
In this case the code only adds the username to the dictionary if the authentication type is
Windows.
The result is that the client will not pass the client-side principal to the server, but it does pass
the username. This allows the application server to retrieve the principal directly from the security
database or service based on the username. Less data is passed over the network from the client to
the server, but the load on the security database will be higher.
At this point you should understand how to configure a .NET smart client to use custom
authentication. Next, I’ll discuss the configuration of a Silverlight or WP7 client application.
This code should be familiar, because it is the same as the asynchronous code used in the WpfUI
project.
No special configuration is required. When the application is run the results are the same as in
WPF. Figure 38 shows the Silverlight UI:
if (System.Diagnostics.Debugger.IsAttached)
{
Application.Current.Host.Settings.EnableFrameRateCounter = true;
}
InitializeComponent();
Csla.DataPortal.ProxyTypeName = typeof(Csla.DataPortalClient.WcfProxy<>).AssemblyQualifiedName;
Csla.DataPortalClient.WcfProxy.DefaultUrl = "http://localhost:38257/SlPortal.svc";
InitializePhoneApplication();
}
This authentication type prevents the data portal from passing the client-side principal to the
application server with each data portal call.
At this point you should understand how to configure .NET, Silverlight, and WP7 applications to
use custom authentication. I will now discuss web application configuration.
ASP.NET Applications
ASP.NET applications include ASP.NET Web Forms, ASP.NET MVC, web services, and WCF services
applications. All of these applications run on a server in ASP.NET, and have access to ASP.NET core
features.
Perhaps the most important decision for any web application is whether the server will be
stateless or stateful. A stateless server doesn’t maintain any information in memory between client
requests. A stateful server typically uses the ASP.NET Session object to maintain information in
memory between client requests.
ASP.NET provides support for authentication, including managing an encrypted user token in a
cookie or on the URL. This encrypted user token, at a minimum, contains the username and an
expiration time, after which the token becomes invalid.
When a user is authenticated, ASP.NET generates this user token, and the token is provided to
the server on each client request so ASP.NET is able to maintain the user’s identity and
authentication status.
Optionally, the token can contain the list of user roles. Normally this is not the case, because
there are limits on cookie sizes, and sending the data over the network on each request is
considered wasteful. For the purposes of this discussion, I’ll assume the default behavior, where
only the username and authentication status is available from ASP.NET on each client request.
When the server is stateless, the user’s principal and identity objects must be retrieved on each
client request. This is done by passing the username from the ASP.NET security token to the Load
method of the CustomPrincipal class.
If the server is stateful you can choose to put the principal object into the ASP.NET Session
object so it is available on each client request without retrieving the data from the security
database or service.
This approach does increase the size of the state maintained between page requests. The web
site can be configured to use an out-of-proc or SQL Server location to maintain Session. In such a
scenario the Session object (and therefore the principal and identity objects) is deserialized from
state storage into memory at the start of each page request, and it is serialized from memory into
state storage at the end of each page request.
You should evaluate whether storing the principal in Session provides better performance for
your application than retrieving it from the security database on each client request.
The data portal defaults to the correct configuration for custom authentication, so no special
configuration is required.
ASP.NET does create principal and identity objects based on its security token. Unfortunately
those objects don’t contain the user’s roles or any profile information. Only the username and
authentication status is available.
You can see how this code uses the authentication status and username from the ASP.NET
identity object to invoke the synchronous Load method on the CustomPrincipal class. The result is
that the real CustomPrincipal and CustomIdentity objects are set as the current principal for the
duration of this client request.
This code runs before any MVC controller code, Web Forms page code, or service
implementation code. By the time your regular application code is executed, this code will have run
and so the current principal will be set to the correct value.
The first time the user hits the MvcUI web site this code runs to verify the user. If the user is
authenticated the code sets up the ASP.NET security token. All subsequent client requests will
retrieve the principal based on the username in the security token.
Figure 40 shows the results displayed in the browser when the MvcUI application is executed:
This prevents the data portal from sending the principal from the web server to the application
server on each data portal request.
Second, the username must be placed into the ClientContext dictionary. This must occur on
each client request to the web site, and so it is implemented in the Global.asax.cs file:
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
var identity = HttpContext.Current.User.Identity;
if (identity.IsAuthenticated)
{
CustomPrincipal.Load(identity.Name);
Csla.ApplicationContext.ClientContext["Username"] = Csla.ApplicationContext.User.Identity.Name;
}
}
In this configuration, each client request will cause the web application to retrieve the principal
through the data portal. Then, each subsequent data portal request will cause the application
server to retrieve the principal based on the username in the ClientContext dictionary. This will
increase the load on your security database or service, but will reduce the network load between
the web and application servers.
At this point you should understand how to configure and implement custom authentication on
an application server, and in .NET, Silverlight, WP7, and ASP.NET applications. Custom
authentication is the basis for all membership authentication, as well as the basis for Windows
authentication for Silverlight and WP7 applications.
I’ll now move on to discuss membership authentication.
Implementing CustomPrincipal
The CustomPrincipal class is the same as in the Custom solution. It implements static methods for
login and logout operations, including BeginLogin, Login, Load, and Logout methods. These
methods invoke static factory methods on the CustomIdentity class, and use the resulting
identity object to establish the current principal for the application.
Implementing CustomIdentity
The CustomIdentity class is similar to the one in the Custom solution.
Instead of a FullName property, this class adds an Email property to the pre-existing properties
required by the IIdentity interface:
public static readonly PropertyInfo<string> EmailProperty = RegisterProperty<string>(c => c.Email);
public string Email
{
get { return GetProperty(EmailProperty); }
private set { LoadProperty(EmailProperty, value); }
}
This is because the membership provider exposes the user’s email address, but doesn’t provide a
full name value.
The class implements the same static factory methods as the version in the Custom solution,
allowing for synchronous and asynchronous verificaition of the user’s credentials. The membership
provider uses username and password credentials, so those are the values that flow through the
data portal to the server-side data portal code.
This is the exact model discussed in detail in the Using CSLA 4: Data Access ebook, so this code
structure should be familiar to you.
Using CSLA 4: Data Portal Configuration Page 114
Rev 0.4 (draft)
Notice that the LoadUserData method is virtually identical to the one in the Custom solution. If
the user’s credentials are verified, this method is called to load the user’s profile and role data from
the DAL provider.
The DAL provider implementation is in the DataAccess.Net project in the IdentityDal class:
public class IdentityDal : IIdentityDal
{
public bool VerifyUser(string username, string password)
{
var result = Membership.ValidateUser(username, password);
return result;
}
This project targets the .NET Framework 4 profile, and references the System.Web.dll assembly.
The VerifyUser method calls the ValidateUser method of the Membership class from the
System.Web.Security namespace. The ValidateUser method verifies the user’s credentials,
returning true if the credentials are valid.
The GetUser method gets the user profile data from the membership provider. In this case, the
username and user’s email address are retrieved. These values are returned in a data transfer
object (DTO). The UserDto type is defined in the DataAccess project, and so is available to the code
in the DataAccess.Net and Library.Net projects.
Finally, the GetRoles method gets the user role data from the ASP.NET role provider. The
GetRolesForUser method of the roles provider from the System.Web.Security namespace is used
to retrieve the role data.
Notice that the Provider property of the Roles type is used to make this call. There is a
GetRolesForUser method on the Roles type itself, but that method throws an unexpected
NullReferenceException when invoked from a WCF service such as the data portal. This didn’t
occur prior to .NET 4, and is presumably a bug in the .NET Framework. Calling the method through
the Provider property avoids the unexpected exception and is a viable workaround.
The data access code runs on the application server. Before this code will work, the application
server must be configured to use the membership and role providers.
Figure 42. Security tab of the ASP.NET Web Site Administration Tool
The Security tab is selected in Figure 42, showing that this application has been configured to
enable membership and roles.
When the membership and role providers have been configured, they’ll have entries in the
system.web element of the web.config file, usually along with a database connection string for the
ASP.NET security database:
<connectionStrings>
<add name="ApplicationServices"
connectionString="Data Source=.\SQL2008;AttachDbFilename=
|DataDirectory|aspnetdb.mdf;Integrated Security=True;User Instance=True"/>
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<membership userIsOnlineTimeWindow="15">
<providers>
<clear/>
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider"
connectionStringName="ApplicationServices"
enablePasswordRetrieval="false" enablePasswordReset="false"
requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6"
In this case the ASP.NET security database is a SQL Server Express database named
aspnetdb.mdf. The file is located in the web site’s App_Data folder.
The ASP.NET membership and role providers are flexible. Details on configuring all aspects of
these providers are outside the scope of this book. The authentication techniques shown in this
chapter will work against the membership and role providers as long as their configuration is valid
within your environment.
The data access code in the DataAccess.Net project uses the Membership and Roles types from
the System.Web.Security namespace. Those types use the providers configured in the web.config
file to interact with the security database to verify the user’s credentials, and to retrieve profile and
role data.
Implementing CustomIdentity
The CustomIdentity class is declared like this:
[Serializable]
[Csla.Server.MobileFactory("Library.CustomIdentityFactory, Library")]
public class CustomIdentity : CslaIdentityBase<CustomIdentity>
The MobileFactory attribute causes the data portal on the web server to create an instance of
the CustomIdentityFactory class, and invoke a Fetch method on that object. That Fetch method is
responsible for managing the data access process. In this case that means calling a data access
component to authentication the user.
The CustomIdentity class would no longer contain any DataPortal_Fetch methods, because all
data access is managed by the mobile factory object.
As you can see, the code in this class is very similar to the code in the DataPortal_Fetch
methods used in the 3-tier implementation. I have chosen to use the same DataAccess and
DataAccess.Net DAL implementations.
It is important to note that the DAL assemblies must be installed on the web server
for this code to work. Additionally, the membership and role providers must be
configured on the web server.
The result is that the Silverlight or WP7 client applications will invoke the data portal normally.
When the data portal request arrives at the web server, the data portal will route the call to an
instance of the CustomIdentityFactory type. The CustomIdentityFactory object uses the DAL to
authenticate the user, and to create a CustomIdentity object. That CustomIdentity object is then
returned to the client.
At no point is the application server involved in the authentication process, because the security
database and providers are all on the web server. Other business classes will flow through to the
application server as normal, only the CustomIdentity class is different due to its MobileFactory
attribute.
When using this 4-tier approach, you will typically want to allow the data portal to perform its
default impersonation by including the client-side principal object as part of each data portal
request. The reason is that your application server probably won’t have access to the web server,
and so won’t be able to directly create a principal object for each request. Therefore you should
expect to pass the principal from the client through the data portal to the application server to
provide a consistent security environment for your business objects.
At this point I’ve covered custom and membership authentication. The final type of
authentication I’ll discuss is Windows domain or Active Directory authentication.
Windows Authentication
Many organizations rely on Windows authentication to secure their applications, and to provide
some level of single sign-on functionality across the organization. In these cases the servers and
workstations in the organization are typically part of a Windows Active Directory domain, and all
user credentials and roles are managed as part of that domain.
This is particularly nice for .NET smart client and internal ASP.NET web applications, because all
the authentication and role management is provided automatically by the Windows operating
system. From a CSLA .NET application perspective, the application must simply be configured to not
Using CSLA 4: Data Portal Configuration Page 119
Rev 0.4 (draft)
perform any explicit user authentication or impersonation, so the application relies entirely on the
operating system to do the work.
Silverlight applications are a different story. These technologies assume the application will be
running outside the organization’s security domain, and so there’s no provision on these platforms
to automatically integrate with a Windows domain. However, CSLA .NET does support Windows
authentication for Silverlight applications. This is implemented as a form of custom authentication,
where the user is authenticated against the Windows domain.
The Windows solution in the Authentication folder of the code download for this ebook
provides an example of using Windows authentication with CSLA .NET. At a high level the structure
of this solution is similar to the Custom and Membership solutions I discussed earlier in this chapter,
but there are differences throughout the solution.
WP7 applications can not currently use Windows authentication through WCF, so there is no
WpUI project in the Windows solution.
You should be aware that executing and testing applications that use Windows security can be
complex. Certain scenarios require a Windows domain, others require being in a network
configured as a workgroup. Some features are only available with a real IIS server, while others can
be used with IIS Express.
The business library projects (such as the Library.Net project) in the Windows solution include a
UserInfo class that is used by the sample applications. This is a read-only business object that
retrieves user information from the application server. Each application displays the user
information on the client and the information from the server to establish that the client identity
has been impersonated on the server.
As I discuss each scenario I’ll discuss the configuration requirements. In most cases you will need
to change or apply those requirements to the projects in the Windows solution before it can
successfully execute.
.NET Applications
Windows client workstations are often members of the Windows domain, and when a user logs into
the workstation, they log in using a Windows domain account. Such domain accounts are available
to all machines in the domain, including the workstation and the application server, and the user
identity can flow from client to server automatically.
If the workstation and server are part of a workgroup instead of a domain, Windows will still
attempt to flow the client Windows identity to the server. To do this, Windows looks for a user
account on the server with the same username and password as on the client. If it can find one, it
assumes the accounts represent the same user.
The real magic comes from the use of the wsHttpBinding in WCF, because that binding carries
the client’s Windows identity to the server when the server is configured to use Windows
authentication. The application server and client must be configured properly for this to occur.
Configuring WCF to use the client’s Windows identity is done by adding a serviceAuthorization
element to the custom behavior used by the service endpoint. The Custom.Web project in the
Windows solution is the application server, and it contains this endpoint configuration:
<service name="Csla.Server.Hosts.WcfPortal" behaviorConfiguration="windowsAuthReturnFaults">
<endpoint binding="wsHttpBinding" bindingConfiguration="wsHttpBinding_IWcfPortal"
contract="Csla.Server.Hosts.IWcfPortal" />
</service>
The behaviorConfiguration value has been changed from previous examples to point to a new
custom behavior. That custom behavior is declared like this:
<behavior name="windowsAuthReturnFaults">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceAuthorization impersonateCallerForAllOperations="true" />
</behavior>
The result of this setting is that the server-side data portal won’t change the server-side principal
value, allowing the Windows operating system to perform impersonation.
Setting this value to Windows ensures that the data portal won’t attempt to pass the client-side
principal to the server as part of the data portal request. The WindowsPrincipal isn’t serializable, so
if this value isn’t set you will get a serialization exception on any attempt to use the data portal.
Finally, the client application must use a custom data portal proxy instead of the standard
WcfProxy class from the Csla.DataPortalClient namespace. This custom proxy configures WCF to
enable impersonation. The WcfWindowsProxy class in the Library.Net project provides this
implementation:
public class WcfWindowsProxy : Csla.DataPortalClient.WcfProxy
{
protected override System.ServiceModel.ChannelFactory<Csla.Server.Hosts.IWcfPortal>
GetChannelFactory()
{
var factory = base.GetChannelFactory();
factory.Credentials.Windows.AllowedImpersonationLevel =
System.Security.Principal.TokenImpersonationLevel.Impersonation;
return factory;
}
}
The default WcfProxy implementation is used to create the channel factory object. Then the
AllowedImpersonationLevel property of the Windows credential object associated with the
channel factory is set to allow impersonation.
If you look back at the appSettings block from the app.config file shown earlier, you should
notice that the CslaDataPortalProxy setting indicates that the data portal should use the
WcfWindowsProxy type from the Library assembly.
You can see the results of running the WpfUI project in Figure 43.
Silverlight Applications
Silverlight applications interact with Windows authentication and impersonation quite differently
from .NET smart clients. The Silverlight runtime itself has no concept of Windows principal or
identity objects. It relies on the browser hosting the Silverlight runtime to manage any identity
negotiation with the server.
Your Silverlight application can use Windows authentication against the server. When the
application attempts to interact with the server, the browser will prompt the user for their
Windows credentials, or the browser will perform an automatic credential negotiation process. The
specific behavior depends on the browser and the browser’s configuration for the web site.
Assuming the user, the browser, and the server are able to authenticate the user’s credentials,
the WCF data portal service on the server will run under the user’s Windows domain account.
As I mentioned, the Silverlight runtime has no concept of Windows identities. To make the
Windows username and domain groups available to the Silverlight application, custom principal and
identity objects are used. The custom identity object is created on the server, and it is loaded with
the username and roles for the user account under which the service is running on the application
server.
Implementing CustomPrincipal
The Library.Net project contains a CustomPrincipal class, and that class is linked into the
Library.Sl project so it is also available to Silverlight applications.
This CustomPrincipal class is the same as the class used in the Custom and Membership
solutions, except that it has no Load method. The Load method is not required for Silverlight clients,
and so is not necessary in this solution.
The custom principal object contains a CustomIdentity object, and it is the CustomIdentity
class that contains the code to retrieve a copy of the user’s Windows username and domain roles.
Implementing CustomIdentity
The Library.Net project contains the CustomIdentity class, and that class is linked into the
Library.Sl project so it is also available to Silverlight applications.
The CustomIdentity class inherits from the WindowsIdentity class in the
Csla.Silverlight.Security namespace. The WindowsIdentity base class is an implementation of
the read-only object stereotype, as well as of the IIdentity interface from the
System.Security.Principal namespace. You can think of it as a specialized version of the
CslaIdentityBase class discussed earlier in this chapter.
#if !SILVERLIGHT
public static CustomIdentity GetCustomIdentity()
{
return DataPortal.Fetch<CustomIdentity>();
}
This article contains useful information about server configuration for Silverlight
clients: http://msdn.microsoft.com/en-us/library/dd744835(VS.95).aspx.
The Custom.Web project in the Windows solution has this entry in the system.web element of the
web.config file:
<authentication mode="Windows" />
And the custom basicHttpBinding used by the Silverlight data portal endpoint includes a
security element:
<basicHttpBinding>
<binding name="basicHttpBinding_IWcfPortal" maxReceivedMessageSize="2147483647">
<readerQuotas maxBytesPerRead="2147483647"
maxArrayLength="2147483647"
maxStringContentLength="2147483647"
maxNameTableCharCount="2147483647"
maxDepth="2147483647" />
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
Once the CustomIdentity object has been retrieved, the User property of the
Csla.ApplicationContext type will be set to the CustomPrincipal object containing the
CustomIdentity object that has the user’s Windows account information. From that point forward,
the client application has access to a principal that is essentially the same as the user’s Windows
principal.
It is important to use something like the ApplicationReady property to prevent the user from
interacting with the application until the client-side principal has been set. Remember that the
Silverlight client has no knowledge of the user’s identity until the login process is complete.
If you look at the actual code in the MainPageViewModel class it is a bit more complex. After the
login process is complete, the code calls the GetUserInfo factory method of the UserInfo class to
retrieve information about the principal being used by the server.
When the application is run, the browser will appear, and will immediately prompt the user for
their Windows credentials as shown in Figure 44.
There is no explicit data portal configuration. The default data portal configuration is to use the
LocalProxy, and to rely on the existing principal object provided by the operating system or
runtime.
The web site must be configured to disable anonymous authentication in IIS, thereby requiring
that the user provide Windows credentials to access the site.
Figure 46 shows the display in the IIS Manager console where the security settings are
controlled.