WCF Security
-------------
http://msdn.microsoft.com/en-us/magazine/cc163382.aspx
http://msdn.microsoft.com/en-us/library/bb386582.aspx#CodeExamples
WCF Authorization
-----------------
http://msdn.microsoft.com/en-us/magazine/cc948343.aspx
WCF Instance Management
-----------------------
http://msdn.microsoft.com/en-us/magazine/cc163590.aspx
Azure Cloud Solution Architect, Full-Stack Development in .Net Eco system, Senior Manager at Capgemini
Showing posts with label WCF. Show all posts
Showing posts with label WCF. Show all posts
Wednesday, May 26, 2010
Tuesday, May 18, 2010
Certificates
http://developers.de/blogs/damir_dobric/archive/2006/08/01/897.aspx
http://msdn.microsoft.com/en-us/library/ff647503.aspx#ClentAuthentication
http://msdn.microsoft.com/en-us/library/ff647503.aspx#ClentAuthentication
Monday, May 17, 2010
WCF Security
Fundamentals of WCF Security (Cont.) Role Based WCF Security
http://www.code-magazine.com/article.aspx?quickid=0611051&page=4
wcf authentication with Custom credentials
http://msdn.microsoft.com/en-us/library/aa702565.aspx
http://www.devatwork.nl/2007/05/wcf-username-authentication/
http://msdn.microsoft.com/en-us/library/ff648806.aspx
Using Certificate-based Authentication and Protection with Windows Communication Foundation (WCF)
--------------------------------------------------------------------------------------------------
http://notgartner.wordpress.com/2007/09/06/using-certificate-based-authentication-and-protection-with-windows-communication-foundation-wcf/
How To – Perform Input Validation in WCF
------------------------------------------
http://wcfsecurity.codeplex.com/wikipage?title=How%20To%20-%20Perform%20Input%20Validation%20in%20WCF&referringTitle=How%20Tos&ProjectName=wcfsecurity
WCF Security Guidance videos
-----------------------------
http://wcfsecurity.codeplex.com/wikipage?title=Video%20Index&referringTitle=Home
Extending WCF with Custom Behaviors
-----------------------------------
http://msdn.microsoft.com/en-us/magazine/cc163302.aspx
ActiveDirectoryMembershipProvider Class
---------------------------------------
http://msdn.microsoft.com/en-us/library/system.web.security.activedirectorymembershipprovider.aspx
How To: Use Forms Authentication with Active Directory in ASP.NET 2.0
-----------------------------------------------------------------------
http://msdn.microsoft.com/en-us/library/ff650308.aspx
C#tools
_______
http://www.csharptools.com/
http://msdn.microsoft.com/en-us/magazine/cc163358.aspx
http://www.code-magazine.com/article.aspx?quickid=0611051&page=4
wcf authentication with Custom credentials
http://msdn.microsoft.com/en-us/library/aa702565.aspx
http://www.devatwork.nl/2007/05/wcf-username-authentication/
http://msdn.microsoft.com/en-us/library/ff648806.aspx
Using Certificate-based Authentication and Protection with Windows Communication Foundation (WCF)
--------------------------------------------------------------------------------------------------
http://notgartner.wordpress.com/2007/09/06/using-certificate-based-authentication-and-protection-with-windows-communication-foundation-wcf/
How To – Perform Input Validation in WCF
------------------------------------------
http://wcfsecurity.codeplex.com/wikipage?title=How%20To%20-%20Perform%20Input%20Validation%20in%20WCF&referringTitle=How%20Tos&ProjectName=wcfsecurity
WCF Security Guidance videos
-----------------------------
http://wcfsecurity.codeplex.com/wikipage?title=Video%20Index&referringTitle=Home
Extending WCF with Custom Behaviors
-----------------------------------
http://msdn.microsoft.com/en-us/magazine/cc163302.aspx
ActiveDirectoryMembershipProvider Class
---------------------------------------
http://msdn.microsoft.com/en-us/library/system.web.security.activedirectorymembershipprovider.aspx
How To: Use Forms Authentication with Active Directory in ASP.NET 2.0
-----------------------------------------------------------------------
http://msdn.microsoft.com/en-us/library/ff650308.aspx
C#tools
_______
http://www.csharptools.com/
http://msdn.microsoft.com/en-us/magazine/cc163358.aspx
Thursday, May 6, 2010
WCF Security
http://wcfsecurity.codeplex.com/
http://wcfsecurityguide.codeplex.com/
Create and Install Temporary Certificates in WCF for Message Security During Development
-----------------------------------------------------------------------------------------
http://wcfsecurity.codeplex.com/wikipage?title=How%20To%20-%20Create%20and%20Install%20Temporary%20Certificates%20in%20WCF%20for%20Message%20Security%20During%20Development&referringTitle=How%20To%20-%20Use%20Username%20Authentication%20with%20the%20SQL%20Membership%20Provider%20and%20Message%20Security%20in%20WCF%20from%20Windows%20Forms
Certificate Creation Tool
--------------------------
http://msdn.microsoft.com/en-us/library/bfsktky3(VS.80).aspx
How To: Use Forms Authentication with SQL Server in ASP.NET 2.0
----------------------------------------------------------------
http://msdn.microsoft.com/en-us/library/ff649314.aspx
How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI
-----------------------------------------------------------------
http://msdn.microsoft.com/en-us/library/ms998280.aspx
How To: Use Regular Expressions to Constrain Input in ASP.NET
--------------------------------------------------------------
http://msdn.microsoft.com/en-us/library/ms998267.aspx
http://wcfsecurityguide.codeplex.com/
Create and Install Temporary Certificates in WCF for Message Security During Development
-----------------------------------------------------------------------------------------
http://wcfsecurity.codeplex.com/wikipage?title=How%20To%20-%20Create%20and%20Install%20Temporary%20Certificates%20in%20WCF%20for%20Message%20Security%20During%20Development&referringTitle=How%20To%20-%20Use%20Username%20Authentication%20with%20the%20SQL%20Membership%20Provider%20and%20Message%20Security%20in%20WCF%20from%20Windows%20Forms
Certificate Creation Tool
--------------------------
http://msdn.microsoft.com/en-us/library/bfsktky3(VS.80).aspx
How To: Use Forms Authentication with SQL Server in ASP.NET 2.0
----------------------------------------------------------------
http://msdn.microsoft.com/en-us/library/ff649314.aspx
How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI
-----------------------------------------------------------------
http://msdn.microsoft.com/en-us/library/ms998280.aspx
How To: Use Regular Expressions to Constrain Input in ASP.NET
--------------------------------------------------------------
http://msdn.microsoft.com/en-us/library/ms998267.aspx
Wednesday, May 5, 2010
WCF Security
Extending WCF with Custom Behaviors
------------------------------------------------------
http://msdn.microsoft.com/en-us/magazine/cc163302.aspx
Use the SQL Server Role Provider with Windows Authentication in WCF Calling from Windows Forms
------------------------------------------------------
http://msdn.microsoft.com/en-us/library/ff648806.aspx
Improving Web Services Security Guide
------------------------------------------------------
http://wcfsecurityguide.codeplex.com/wikipage?title=How%20To%20-%20Use%20SQL%20Role%20Provider%20with%20Username%20Authentication%20in%20WCF%20calling%20from%20Windows%20Forms&referringTitle=Home
Use Username Authentication with the SQL Server Membership Provider and Message Security in WCF from Windows Forms
------------------------------------------------------
http://wcfsecurity.codeplex.com/wikipage?title=How%20To%20-%20Use%20Username%20Authentication%20with%20the%20SQL%20Membership%20Provider%20and%20Message%20Security%20in%20WCF%20from%20Windows%20Forms&referringTitle=How%20To%20-%20Use%20SQL%20Role%20Provider%20with%20Username%20Authentication%20in%20WCF%20calling%20from%20Windows%20Forms
Create and Install Temporary Certificates in WCF for Message Security During Development
------------------------------------------------------
http://wcfsecurity.codeplex.com/wikipage?title=How%20To%20-%20Create%20and%20Install%20Temporary%20Certificates%20in%20WCF%20for%20Message%20Security%20During%20Development&referringTitle=How%20To%20-%20Use%20Username%20Authentication%20with%20the%20SQL%20Membership%20Provider%20and%20Message%20Security%20in%20WCF%20from%20Windows%20Forms
------------------------------------------------------
http://msdn.microsoft.com/en-us/magazine/cc163302.aspx
Use the SQL Server Role Provider with Windows Authentication in WCF Calling from Windows Forms
------------------------------------------------------
http://msdn.microsoft.com/en-us/library/ff648806.aspx
Improving Web Services Security Guide
------------------------------------------------------
http://wcfsecurityguide.codeplex.com/wikipage?title=How%20To%20-%20Use%20SQL%20Role%20Provider%20with%20Username%20Authentication%20in%20WCF%20calling%20from%20Windows%20Forms&referringTitle=Home
Use Username Authentication with the SQL Server Membership Provider and Message Security in WCF from Windows Forms
------------------------------------------------------
http://wcfsecurity.codeplex.com/wikipage?title=How%20To%20-%20Use%20Username%20Authentication%20with%20the%20SQL%20Membership%20Provider%20and%20Message%20Security%20in%20WCF%20from%20Windows%20Forms&referringTitle=How%20To%20-%20Use%20SQL%20Role%20Provider%20with%20Username%20Authentication%20in%20WCF%20calling%20from%20Windows%20Forms
Create and Install Temporary Certificates in WCF for Message Security During Development
------------------------------------------------------
http://wcfsecurity.codeplex.com/wikipage?title=How%20To%20-%20Create%20and%20Install%20Temporary%20Certificates%20in%20WCF%20for%20Message%20Security%20During%20Development&referringTitle=How%20To%20-%20Use%20Username%20Authentication%20with%20the%20SQL%20Membership%20Provider%20and%20Message%20Security%20in%20WCF%20from%20Windows%20Forms
Tuesday, February 16, 2010
Generic WCF Converter function
public TDestination Convert(TSource objSource, TDestination objDestination)
{
if (objSource == null)
{
return default(TDestination);
}
if (objDestination == null)
{
return default(TDestination);
}
// Read Destination Properties
foreach (PropertyInfo propInfo in objDestination.GetType().GetProperties())
{
if (!propInfo.PropertyType.IsGenericType)
{
// Read Source Properties
object val = null;
foreach (PropertyInfo info in objSource.GetType().GetProperties())
{
// Match Source & Destination Properties
if (propInfo.Name == info.Name)
{
if (info.CanRead)
{
val = info.GetValue(objSource, null);
}
if (propInfo.CanWrite)
{
// If Source is Enum Type and Destination is byte type
if (info.PropertyType.IsEnum == true && propInfo.PropertyType.IsEnum == false)
{
byte tmpVal = System.Convert.ToByte(info.PropertyType.GetField(info.GetValue(objSource, null).ToString()).GetRawConstantValue());
propInfo.SetValue(objDestination, tmpVal, null);
}
else
{
propInfo.SetValue(objDestination, val, null);
}
}
break;
}
}
}
}
return objDestination;
}
{
if (objSource == null)
{
return default(TDestination);
}
if (objDestination == null)
{
return default(TDestination);
}
// Read Destination Properties
foreach (PropertyInfo propInfo in objDestination.GetType().GetProperties())
{
if (!propInfo.PropertyType.IsGenericType)
{
// Read Source Properties
object val = null;
foreach (PropertyInfo info in objSource.GetType().GetProperties())
{
// Match Source & Destination Properties
if (propInfo.Name == info.Name)
{
if (info.CanRead)
{
val = info.GetValue(objSource, null);
}
if (propInfo.CanWrite)
{
// If Source is Enum Type and Destination is byte type
if (info.PropertyType.IsEnum == true && propInfo.PropertyType.IsEnum == false)
{
byte tmpVal = System.Convert.ToByte(info.PropertyType.GetField(info.GetValue(objSource, null).ToString()).GetRawConstantValue());
propInfo.SetValue(objDestination, tmpVal, null);
}
else
{
propInfo.SetValue(objDestination, val, null);
}
}
break;
}
}
}
}
return objDestination;
}
Wednesday, February 10, 2010
Sunday, February 7, 2010
WCF Client Proxy IDisposable - Generic WCF Service Proxy
I have run into this issue on several clients now. The basic issue is when using WCF on the client, using ClientBase<>, and you do not close the channel, you can tie up the server until the channel times out. So, once the max instances, sessions, or concurrent calls is reached and the clients are not closing their channels, the server will block and queue up subsequent calls. The un-closed client channels will eventually timeout, which causes a fault on the client, and the next set of calls will then make it through.
When I first hit this issue, my thought was to wrap my client base code in a using () statement so Dispose() would then be called. But, ClientBase<> does not implement IDisposable. Here is some info on the issue...
So, after lots of testing to understand all the WCF knobs to tweak, I came up with a generic class I called ServiceProxy for clients to use when creating/using client channels. This has been through several revisions and here is what I have ended up with. The idea to add support for the delegate came from this blog entry
Here is the code for my generic service proxy wrapper...
public class ServiceProxy : ClientBase, IDisposable where TInterface : class
{
public delegate void ServiceProxyDelegate(TInterface proxy);
public ServiceProxy(): base(typeof(TInterface).ToString())
{
}
public ServiceProxy(string endpointConfigurationName): base(endpointConfigurationName)
{
}
protected override TInterface CreateChannel()
{
return base.CreateChannel();
}
public TInterface Proxy
{
get{return this.Channel;}
}
public static void Call(ServiceProxyDelegate proxyDelegate)
{
Call(proxyDelegate, typeof(TInterface).ToString());
}
public static void Call(ServiceProxyDelegate proxyDelegate, string endpointConfigurationName)
{
ChannelFactory channel = new ChannelFactory(endpointConfigurationName);
try
{
proxyDelegate(channel.CreateChannel());
}
finally
{
if (channel.State == CommunicationState.Faulted)
{
channel.Abort();
}else{
try
{
channel.Close();
}
catch
{
channel.Abort();
}
}
}
}
public void Dispose()
{
if (this.State == CommunicationState.Faulted)
{
base.Abort();
}
else{
try
{
base.Close();
}
catch
{
base.Abort();
}
}
}
}
And, here are some usages samples...
//delegate example1
string response = null;
ServiceModel.ServiceProxy.Call(p =>
{
response = p.DoStuff("ServiceProxyUsingTest");
}
);
//delegate example2
string response = null;
ServiceProxy.Call(p => response = p.DoStuff("ServiceProxyUsingTest"));
//using example
string response = null;
using (ServiceProxy service = new ServiceProxy())
{
response = service.Proxy.DoStuff("ServiceProxyUsingTest");
}
I have run into this issue on several clients now. The basic issue is when using WCF on the client, using ClientBase<>, and you do not close the channel, you can tie up the server until the channel times out. So, once the max instances, sessions, or concurrent calls is reached and the clients are not closing their channels, the server will block and queue up subsequent calls. The un-closed client channels will eventually timeout, which causes a fault on the client, and the next set of calls will then make it through.
When I first hit this issue, my thought was to wrap my client base code in a using () statement so Dispose() would then be called. But, ClientBase<> does not implement IDisposable. Here is some info on the issue...
So, after lots of testing to understand all the WCF knobs to tweak, I came up with a generic class I called ServiceProxy for clients to use when creating/using client channels. This has been through several revisions and here is what I have ended up with. The idea to add support for the delegate came from this blog entry
Here is the code for my generic service proxy wrapper...
public class ServiceProxy
{
public delegate void ServiceProxyDelegate
public ServiceProxy(): base(typeof(TInterface).ToString())
{
}
public ServiceProxy(string endpointConfigurationName): base(endpointConfigurationName)
{
}
protected override TInterface CreateChannel()
{
return base.CreateChannel();
}
public TInterface Proxy
{
get{return this.Channel;}
}
public static void Call(ServiceProxyDelegate
{
Call(proxyDelegate, typeof(TInterface).ToString());
}
public static void Call(ServiceProxyDelegate
{
ChannelFactory
try
{
proxyDelegate(channel.CreateChannel());
}
finally
{
if (channel.State == CommunicationState.Faulted)
{
channel.Abort();
}else{
try
{
channel.Close();
}
catch
{
channel.Abort();
}
}
}
}
public void Dispose()
{
if (this.State == CommunicationState.Faulted)
{
base.Abort();
}
else{
try
{
base.Close();
}
catch
{
base.Abort();
}
}
}
}
And, here are some usages samples...
//delegate example1
string response = null;
ServiceModel.ServiceProxy
{
response = p.DoStuff("ServiceProxyUsingTest");
}
);
//delegate example2
string response = null;
ServiceProxy
//using example
string response = null;
using (ServiceProxy
{
response = service.Proxy.DoStuff("ServiceProxyUsingTest");
}
Friday, February 5, 2010
WCF Design Pattern: Generic Service
WCF provides great opportunities to architects for building robust applications. One thing many architects may not realize is that it is also a great technology for building reusable patterns as well; and to do so without incurring limits on the types of entities and fields operated on by the service.
A common task is to create an SOA that provides business rules in a WCF Facade that also calls into an abstracted data storage mechanism. This data storage can vary from service to service depending on the originating source for the data that the Facade is exposing as a service. Although it is very easy to create this pattern, it's not usually intuitive to do so in a generic manner; but since you're reading this you know I have a pattern in hand that fits the bill!
The WCF Generic Service Pattern has three parts: the service facade, business entity (or entities) and business entity persistence. To create a reusable pattern, we start with our entity as an abstract base class:
public abstract class EntityBase
{
Key m_keyID;
[DataMember]
public Key ID
{
get { return m_keyID; }
set { m_keyID = value; }
}
}
This looks like Generics 101, right? Just a simple entity with a definable key. What could be easier? Well, when we create our concrete entity all we need to do is supply a type for the key!
[DataContract]
public class Entity : EntityBase
{
// Nothing needed!
}
OK, nothing is needed to support using a GUID for the value of the ID property. But this is a WCF article, so you should note a couple of things. First, DataContract and DataMember are not married to each other. I've defined a DataMember in the abstract EntityBase, but it is not a DataContract; which it couldn't be because you cannot instantiate EntityBase. The Entity class is what's marked as a DataContract and the base class members marked as DataMember will be serialized by WCF.
So, we've created our Entity, so how are we going to save it to the database? Well, not only are we abstracting details about the entity, we are also abstracting details about persistence. What if one entity required saving to XML while another required saving to Oracle? It's as easy as spelling interface!
public interface IEntityPersistence
{
TEntity GetByKey(Key key);
}
Hmm, see the generics on the Interface? This is the meat-and-potatoes of this design pattern which allows any number of implementations to be created to work with the entities of your choice. To handle our previously defined entity, the persistence class looks like this:
public class Persistence : IEntityPersistence
{
#region IEntityPersistence Members
public Entity GetByKey(Guid key)
{
// TODO: Implement your data access code here!
throw new Exception(
"The method or operation is not implemented.");
}
#endregion
}
Note that the class declaration sets the persistence provider to use our Entity class with a Guid for the key. You'll need to handle the actual persistence here.
OK, we have our entity and our persistence, now let's expose them as a service! Best practices for WCF say to use an interface for our service's ServiceContract:
[ServiceContract()]
public interface IService
{
[OperationContract]
TEntity GetByKey(Key key);
}
Here we define both the WCF ServiceContract and the OperationContract for GetByKey. Notice the use of generics; we are once again making our service pattern completely reusable. Next, we create an abstract service base class that has our reusable functionality:
public abstract class ServiceBase : IService
{
protected IEntityPersistence m_objPersistence = null;
#region IService Members
public TEntity GetByKey(Key key)
{
return m_objPersistence.GetByKey(key);
}
#endregion
}
This easy! We've declare an instance variable to hold our persistence instance and actually used it to return our entity from our data store. What's missing? Oh, yeah, the instantiation of the persistence class! Now we need to provide an actual public class that WCF can instantiate:
public class Service : ServiceBase
{
// This constructor sets the appropriate
// persistence instance for the entity
// being exposed by this service.
public Service()
{
m_objPersistence = new Persistence();
}
// All the business rules for the entity
// is handled in the ServiceBase class!
}
And that's it! We now have a complete WCF service build from our WCF Generic Service pattern. We could create any number of sub-classes of EntityBase and matching facade and persistence classes. This is a very powerful tool for creating a consistent API with WCF.
WCF provides great opportunities to architects for building robust applications. One thing many architects may not realize is that it is also a great technology for building reusable patterns as well; and to do so without incurring limits on the types of entities and fields operated on by the service.
A common task is to create an SOA that provides business rules in a WCF Facade that also calls into an abstracted data storage mechanism. This data storage can vary from service to service depending on the originating source for the data that the Facade is exposing as a service. Although it is very easy to create this pattern, it's not usually intuitive to do so in a generic manner; but since you're reading this you know I have a pattern in hand that fits the bill!
The WCF Generic Service Pattern has three parts: the service facade, business entity (or entities) and business entity persistence. To create a reusable pattern, we start with our entity as an abstract base class:
public abstract class EntityBase
{
Key m_keyID;
[DataMember]
public Key ID
{
get { return m_keyID; }
set { m_keyID = value; }
}
}
This looks like Generics 101, right? Just a simple entity with a definable key. What could be easier? Well, when we create our concrete entity all we need to do is supply a type for the key!
[DataContract]
public class Entity : EntityBase
{
// Nothing needed!
}
OK, nothing is needed to support using a GUID for the value of the ID property. But this is a WCF article, so you should note a couple of things. First, DataContract and DataMember are not married to each other. I've defined a DataMember in the abstract EntityBase, but it is not a DataContract; which it couldn't be because you cannot instantiate EntityBase. The Entity class is what's marked as a DataContract and the base class members marked as DataMember will be serialized by WCF.
So, we've created our Entity, so how are we going to save it to the database? Well, not only are we abstracting details about the entity, we are also abstracting details about persistence. What if one entity required saving to XML while another required saving to Oracle? It's as easy as spelling interface!
public interface IEntityPersistence
{
TEntity GetByKey(Key key);
}
Hmm, see the generics on the Interface? This is the meat-and-potatoes of this design pattern which allows any number of implementations to be created to work with the entities of your choice. To handle our previously defined entity, the persistence class looks like this:
public class Persistence : IEntityPersistence
{
#region IEntityPersistence
public Entity GetByKey(Guid key)
{
// TODO: Implement your data access code here!
throw new Exception(
"The method or operation is not implemented.");
}
#endregion
}
Note that the class declaration sets the persistence provider to use our Entity class with a Guid for the key. You'll need to handle the actual persistence here.
OK, we have our entity and our persistence, now let's expose them as a service! Best practices for WCF say to use an interface for our service's ServiceContract:
[ServiceContract()]
public interface IService
{
[OperationContract]
TEntity GetByKey(Key key);
}
Here we define both the WCF ServiceContract and the OperationContract for GetByKey. Notice the use of generics; we are once again making our service pattern completely reusable. Next, we create an abstract service base class that has our reusable functionality:
public abstract class ServiceBase
{
protected IEntityPersistence
#region IService
public TEntity GetByKey(Key key)
{
return m_objPersistence.GetByKey(key);
}
#endregion
}
This easy! We've declare an instance variable to hold our persistence instance and actually used it to return our entity from our data store. What's missing? Oh, yeah, the instantiation of the persistence class! Now we need to provide an actual public class that WCF can instantiate:
public class Service : ServiceBase
{
// This constructor sets the appropriate
// persistence instance for the entity
// being exposed by this service.
public Service()
{
m_objPersistence = new Persistence();
}
// All the business rules for the entity
// is handled in the ServiceBase class!
}
And that's it! We now have a complete WCF service build from our WCF Generic Service pattern. We could create any number of sub-classes of EntityBase and matching facade and persistence classes. This is a very powerful tool for creating a consistent API with WCF.
WCF does not support the use of generic methods for service operation. In other words, only concrete types can be used for service operations. Open generic types cannot be used. Now, it is important to clarify this is not a limitation of WCF. Rather, it is a limitation of WSDL, which is used to expose service metadata to consumers. There is no construct within WSDL to define a generic type. Generally speaking, I agree with this behavior since it decreases the coupling between a client and service.
Although generic methods are not supported, it is possible to expose generic objects for the purpose of exchanging data. However, there are some limitations. Let's take a closer look:
Bounded Generics
In his book Programming WCF Services , Juval Lowy points out that it is possible to use "bounded generics." This is sometimes referred to as closed generics. Basically, it refers to defining a generic class for your data contract, but it is restricted to a specific type in the service operation. This may sound somewhat vague. So, here is an example to provide a better illustration:
[DataContract]
public class MyGenericObject
{
private T _id;
private string _description;
public MyGenericObject()
{
}
[DataMember]
public T ID
{
get { return _id; }
set { _id = value; }
}
[DataMember]
public string Description
{
get { return _description; }
set { _description = value; }
}
}
[ServiceContract(Namespace = "http://jeffbarnes.net/2007/05/boundedgenerics/")]
public interface IBoundedGenerics
{
[OperationContract]
MyGenericObject GetGenericObject(int id);
}
As you can see, a generic object (MyGenericObject) is exposed to the client. However, the service operation restricts the usage to being of type integer. This is what Juval Lowy means by "bounded generics." However, it should be noted the client will not see the object as a generic. When the metadata is generated to describe the service operation, the data contract and service operation will appear as a normal non-generic class.
[DataContract]
public class MyGenericObjectOfint
{
private int _id;
private string _description;
public MyGenericObjectOfint()
{
}
[DataMember]
public int ID
{
get { return _id; }
set { _id = value; }
}
[DataMember]
public string Description
{
get { return _description; }
set { _description = value; }
}
}
The resulting name is due to an applied naming pattern that consists of:
Generic Class Name + "Of" + Type Parameter Name + Hash
The hash is added under certain conditions to reduce the risk of a name collision. However, you should be aware the hash can create a really ugly class name. It could be something like: MyGenericObjectOfSomeTypegDh87uV. Obviously, this isn't an ideal name for the client to use. Fortunately, you can override the use of the hash by specifying the Name property of the DataContract. It supports parameters that correspond to the generic type parameters.
For example:
[DataContract(Name = "MyGenericObjectUsing{0}"]
public class MyGenericObject
Using this approach, it is still possible to leverage generics from within the service implementation, but there is nothing special going on from the client's perspective.
You can download the sample code from here.
http://jeffbarnes.net/download/blog/200705/genericserialization.rar
Although generic methods are not supported, it is possible to expose generic objects for the purpose of exchanging data. However, there are some limitations. Let's take a closer look:
Bounded Generics
In his book Programming WCF Services , Juval Lowy points out that it is possible to use "bounded generics." This is sometimes referred to as closed generics. Basically, it refers to defining a generic class for your data contract, but it is restricted to a specific type in the service operation. This may sound somewhat vague. So, here is an example to provide a better illustration:
[DataContract]
public class MyGenericObject
{
private T _id;
private string _description;
public MyGenericObject()
{
}
[DataMember]
public T ID
{
get { return _id; }
set { _id = value; }
}
[DataMember]
public string Description
{
get { return _description; }
set { _description = value; }
}
}
[ServiceContract(Namespace = "http://jeffbarnes.net/2007/05/boundedgenerics/")]
public interface IBoundedGenerics
{
[OperationContract]
MyGenericObject
}
As you can see, a generic object (MyGenericObject
[DataContract]
public class MyGenericObjectOfint
{
private int _id;
private string _description;
public MyGenericObjectOfint()
{
}
[DataMember]
public int ID
{
get { return _id; }
set { _id = value; }
}
[DataMember]
public string Description
{
get { return _description; }
set { _description = value; }
}
}
The resulting name is due to an applied naming pattern that consists of:
Generic Class Name + "Of" + Type Parameter Name + Hash
The hash is added under certain conditions to reduce the risk of a name collision. However, you should be aware the hash can create a really ugly class name. It could be something like: MyGenericObjectOfSomeTypegDh87uV. Obviously, this isn't an ideal name for the client to use. Fortunately, you can override the use of the hash by specifying the Name property of the DataContract. It supports parameters that correspond to the generic type parameters.
For example:
[DataContract(Name = "MyGenericObjectUsing{0}"]
public class MyGenericObject
Using this approach, it is still possible to leverage generics from within the service implementation, but there is nothing special going on from the client's perspective.
You can download the sample code from here.
http://jeffbarnes.net/download/blog/200705/genericserialization.rar
Subscribe to:
Posts (Atom)