Is it possible to define a validation method (for businbess rules validation) that will be used by NHibernate.Validator?
I mean something that exists in EntLib:
[HasSelfValidation()]
public class SomeClass
{
//...
[SelfValidation()]
public virtual void DoValidate(ValidationResults results)
{
//...
}
}
Yes, it can be done - but you will be missing a way to communicate more information on which rules were violated in the case of validation errors.
NHibernate Validator, to my knowledge, only provides the ability to specify a text message, the name of the class, and - in the case of property level validation attributes - the name of the violated property.
If your attribute HasSelfValidationAttribute implement IRuleArgs pointing to an IValidator (or IInitializableValidator), it has no way to communicate back anything else but a simple string Message and the name of the class, which would probably be too little information if your demand is to validate "real business rules".
NHibernate Validator is great for simple validation scoped to the properties of a class, but it comes short when you need to do more complex validation.
Have a look at The RulesEngine Project. Your business object won't have to be decorated with any attributes or have to implement any interfaces...
Related
I'm writing an app with DDD in mind and trying to avoid having an anemic domain model by delegating doman logic and behaviour to entities. There's an issue I'm running into with constructing entities that are aggregate roots and need to create sub-entities that require handling by a factory class. Here's an example:
I have the following entities: Page, Url and Layout. What makes a Page in my model is a Page with a Url and a Layout - without those two, a Page object would not be valid. In a simple model, the Page constructor method would simply create those two objects as private attributes. However, the Url has a specific requirement; it has to be created from the Page's title - or a slug - and it has to be unique (ensured by appending "-1", "-2", or something similar). This requires communication with a repository.
My initial idea was to pass/inject a UrlFactory object to the Page constructor and have the Page create the Url it needs, but I keep reading about how injecting services into entities is a bad idea.
So, my question is; is there a way - or an established pattern - to allow entities to construct their complex sub-entities without having an anemic domain model, or is injecting a factory in case such as this a valid solution?
If you consider URL construction as a technical concern, you could have an UrlFactory in the Infrastructure layer
in C# :
public class UrlFactory
{
public string CreateUrl(string title)
{
var url = // ... construct URL from the title here
return _pageRepository.NextAvailableUrlLike(url);
}
}
and then call it from your Application layer service.
If you see it as a Domain concern, Url construction logic could be in a Domain Service instead. The line calling the repository would be moved to the Application layer Service :
public void CreatePage(string title)
{
var potentialUrl = _urlService.CreateUrl(title);
var realUrl = _pageRepository.NextAvailableUrlLike(url)
new Page(title, realUrl, ...); // do whatever you want with the new Page instance
}
Do not inject factory class into aggregrate, use factory method instead. Then create method "validate(Validator)" in aggregate (Aggregate will only know it can be valided, but it will not implement logic how to do it).
Validator class which will be passed as parameter to your validate method, will need to have one method ->validateObject(this).
You pass instance of aggregate into validateObject so it will have access to your properties.
Validator class can have injected repository. When you run validateObject method it will search database for uniquness.
Following advices from people on the internet about service references, I got rid of them now and split the service/data contracts into a common assembly accesible by both the server and the client. Overall this seems to work really well.
However I’m running into problems when trying to use custom objects, or rather custom subtypes, in the service. Initially I wanted to define only interfaces in the common assembly as the contract for the data. I quickly learned that this won’t work though because the client needs a concrete class to instantiate objects when receiving objects from the service. So instead I used a simple class instead, basically like this:
// (defined in the common assembly)
public class TestObject
{
public string Value { get; set; }
}
Then in the service contract (interface), I have a method that returns such an object.
Now if I simply create such an object in the service implementation and return it, it works just fine. However I want to define a subtype of it in the service (or the underlying business logic), that defines a few more things (for example methods for database access, or just some methods that work on the objects).
So for simplicity, the subtype looks like this:
// (defined on the server)
public class DbTestObject : TestObject
{
public string Value { get; set; }
public DbTestObject(string val)
{
Value = val;
}
}
And in the service, instead of creating a TestObject, I create the subtype and return it:
public TestObject GetTestObject()
{
return new DbTestObject("foobar");
}
If I run this now, and make the client call GetTestObject, then I immediately get a CommunicationException with the following error text: “The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:09:59.9380000'.”
I already found out, that the reason for this is that the client does not know how to deserialize the DbTestObject. One solution would be to declare the base type with the KnownTypeAttribute to make it know about the subtype. But that would require the subtype to be moved into the common assembly, which is of course something I want to avoid, as I want the logic separated from the client.
Is there a way to tell the client to only use the TestObject type for deserialization; or would the solution for this be to use data transfer objects anyway?
As #Sixto Saez has pointed out, inheritance and WCF don't tend to go together very well. The reason is that inheritance belongs very much to the OO world and not the messaging passing world.
Having said that, if you are in control of both ends of the service, KnownType permits you to escape the constraints of message passing and leverage the benefits of inheritance. To avoid taking the dependency you can utilise the ability of the KnownTypeAttribute to take a method name, rather than a type parameter. This allows you to dynamically specify the known types at run time.
E.g.
[KnownType("GetKnownTestObjects")]
[DataContract]
public class TestObject
{
[DataMember]
public string Value { get; set; }
public static IEnumerable<Type> GetKnownTestObjects()
{
return Registry.GetKnown<TestObject>();
}
}
Using this technique, you can effectively invert the dependency.
Registry is a simple class that allows other assemblies to register types at run-time as being subtypes of the specified base class. This task can be performed when the application bootstraps itself and if you wish can be done, for instance, by reflecting across the types in the assembly(ies) containing your subtypes.
This achieves your goal of allowing subtypes to be handled correctly without the TestObject assembly needing to take a reference on the subtype assembly(ies).
I have used this technique successfully in 'closed loop' applications where both the client and server are controlled. You should note that this technique is a little slower because calls to your GetKnownTestObjects method have to be made repeatedly at both ends while serialising/deserialising. However, if you're prepared to live with this slight downside it is a fairly clean way of providing generic web services using WCF. It also eliminates the need for all those 'KnownTypeAttributes' specifying actual types.
I am looking for some best practices on how to handle the following scenario - flowing permissions from WCF service layer through to UI:
I have WCF services with methods that have been decorated with the PrincipalPermission attribute. I would like a means to allow a client to check if they have the required permissions before invoking the method.
A basic example of this could be checking whether a user can perform a specific function (say submitting an order), which can then be used to enable/disable a button within the UI.
Possible options are to add "chatty" operations like bool CanSubmitOrder() to the service, or instead have a single method OrderServicePermissions GetPermissions() which returns a message with a property CanSubmitOrder? I can then set the enabled state of a "Submit Order" button to the result.
So does anybody know of a better approach, or even a best practice?
Thanks in advance!
The whole point of having PrincipalPermission attributes on your service calls is that you don't have to check ahead of time whether or not the caller has the rights to call - if he doesn't, the WCF runtime will throw an exception.
Why not just rely on this built-in mechanism? Why not just put your service calls in a try..catch block and handle the exceptions if they do actually occur? It should be the "exceptional" case anyway, right?
I don't see any other "magic" way besides what you described. But the generally accepted practice would be to call and handle any exceptions if they occur.
Marc
Well, if you are able to evolve your applications to use Windows Identity Foundation (WIF) to secure your services you could achieve this using the DisplayToken property of the RequestSecurityTokenResponse.
http://msdn.microsoft.com/en-us/library/microsoft.identitymodel.protocols.wstrust.requestsecuritytokenresponse.requesteddisplaytoken.aspx
Assuming your security token service supported it, the display token could contain a claim set that would allow you to flow your permissions into the UI, say to disable controls that are bound to services the user cannot call. The display token is an extension to WS-Trust that was implemented for CardSpace so it it not likely to be very widely supported outside of the Windows world.
Be aware though, that some people think the display token is bad news and violates the 1st law of identity:
http://www.francisshanahan.com
While other people think it is a reasonable and pragmatic solution to a common problem:
http://blogs.msdn.com/b/vbertocci/archive/2007/10/31/on-displaytoken.aspx
There are two general type to implement checking logic:
Share library. Example is "RIA Services + Silverlight".
Pluses: simple to implement.
Minuses: no interoperability (only .NET); required client update for every library changing.
Implement common method validation in service part.
Pluses: interoperability, no need for client update if checking logic changed
Minuses: may be to complex because it is only on you
If we use SOA it is better to use second choice, if only you are not using applications only in your company where .NET is everywhere.
Example
Let us consider common example. We have a windows/wpf form. And there are two fields: "surname" of type string, "age" of type int; and a button "Save". We need to implement some check on client side
1) for some users button "Save" is disabled;
2) surname cannot be empty and max length is 256;
3) age cannot be less than 0;
Invoking method to save is
void Save(string surname, int age);
Create second method in the service, which return object type of PermissonAnswerDTO with validation information;
PermissonAnswerDTO SaveValidate(string surname, int age);
and main validation method
// If arguments are wrong
[FaultContract(typeof(NotSupportedException))]
// If the user have permisson to invoke this method
[FaultContract(typeof(CustomNotEnoughPermission))]
PermissonAnswerDTO Validate(string methodName, object[] methodParams);
Validation.
Invoke Validate("SaveValidate", null) on window loading. If exception of type CustomNotEnoughPermission is throwed then we block "Save" button.
If user can save then invoke user's data Validate("SaveValidate", object[2]{"Surname", "-60"};. -60 is not valid so we get answer object of type PermissonAnswerDTO with information:
ParameterName: "age",
ExceptionMessage: "age cannot be less then null".
And we can gracefully show this information to user.
My thought on this is that some day Microsoft will implement this and call as new technology as it always does. Mostly Microsoft's technologies really are not so revolutionary as it is advertised. Examples are Windows Identity Foundation and Reactive Extensions.
Full example
[DataContract]
public class ParameterExceptionExplanaitonDTO
{
[DataMember]
public string ParameterName;
[DataMember]
public string ExceptionMessage;
}
[DataContract]
public class PermissonAnswerDTO
{
[DataMember]
public bool IsValid;
[DataMember]
public ParameterExceptionExplanaitonDTO[] ParameterExceptions;
}
public class Service1 : WcfContracts.IService1
{
// If arguments are wrong
[FaultContract(typeof(NotSupportedException))]
// If the user have permisson to invoke this method
[FaultContract(typeof(CustomNotEnoughPermission))]
public PermissonAnswerDTO Validate(string methodName, object[] methodParams)
{
//1) Using Reflection find the method with name = <methodName + Validate>
//2) Using Reflection cast each object in "object[] methodParams" to the required type
//3) Invoke method
}
private PermissonAnswerDTO GetUserNameValidate(int id)
{
//logic to check param
}
public string GetUserName(int id)
{
// if the user calls method we need validate parameter
GetUserNameValidate(id);
//some logic to retreive name
}
}
NHibernate requires not only settable properties of your domain to be virtual but also get-only properties and methods. Does anyone know what the reason for this is?
I cannot imagine a possible use.
The reason is lazy loading. In order to make lazy loading possible, a proxy class is created. It must intercept every call from "outside" in order to load your entity before actual method/property is executed. If some methods/properties were not virtual it would be impossible to intercept these calls and entity wouldn't be loaded.
I'm not an NHibernate expert, but from reading Oren's blogs, and from what I've learned of NH, the basic pattern of use is to proxy the objects for the ORM. This means, among other things, that the only things you'll be able to map are going to be things that are made virtual, otherwise NH would have to use a different strategy to redefine the implementations under the hood.
Because you may want to access your settable properties from there, and maybe in some fancy indirect or reflection way. So it's to be 100% sure that when your entity is used, it's initialized.
Example:
public string GetSmth
{
get
{
// NHibernate will not know that you access this field.
return _name;
}
}
private string _name;
public virtual string Name { get { return _name; } set { _name = value; } }
Here's Ayende explaing this in relation to Entity Framework:
http://ayende.com/Blog/archive/2009/05/29/why-defer-loading-in-entity-framework-isnrsquot-going-to-work.aspx
AddProduct is a non virtual method
call, so it cannot be intercepted.
Accessing the _products field also
cannot be intercepted.
The only reason I see why one would want method execution without messing with NH proxy (i.e. loading data) is when you have method that do not access your class' data. But in this case, if this method does not use your class' data, what does it belong to that class at all?
Adding a service reference to a web service (this is all WCF) in Visual Studio produces some generated code including a client-side restatement of the interface being exposed.
I understand why this interface is generated: you might be consuming a 3rd party service and not have access to the actual interface.
But I do, and the two are not assignment compatible even though the transparent proxy does indeed exactly implement the interface to which I want to cast.
I can use reflection, but that's ugly. Is there some way to defeat this faux type safety and inject metadata to so I can use an interface with a class?
My specific problem departs from the norm in complicated ways that have to do with a single client that uses some derivatives of a base class directly and uses others remotely via service references. The base class for each server needs to keep references to subscribing clients in a collection for enumeration to notify events, and the problem was type varied due to the use of proxies.
None of these answers solves my specific problem, yet every single answer was instructive and helpful. I found my own solution (use a dual binding) but I would never have figured it out if you hadn't radically improved my understanding of the whole business.
Three excellent answers. How to choose just one? I choose the first, because it directly solves the problem I first thought I had.
If you already have the contract dll at the client, you don't even need a service reference (unless you are using it to write the setup code for you) - you can simply subclass ClientBase and expose the Channel, and use that directly - something like (no IDE handy...):
public class WcfClient<T> : ClientBase<T> where T : class
{
public new T Channel {get {return base.Channel;}}
}
Then you can just do things like:
using(var client = new WcfClient<IFoo>())
{
client.Channel.Bar(); // defined by IFoo
}
You still need the configuration settings in the config to determine the address, binding, etc - but less messy than proxy generation. Also, you might choose to re-implement IDipsoable to deal with the fact that WCF proxies can throw in Dispose() (which is bad):
public class WcfClient<T> : ClientBase<T>, IDisposable where T : class
{
public new T Channel {get {return base.Channel;}}
void IDisposable.Dispose() {
try {
switch(State) {
case CommunicationState.Open: Close(); break;
// etc
}
} catch {} // swallow it down (perhaps log it first)
}
}
When you add the service reference, go to "Advanced" and make sure "Reuse types in referenced assemblies" is selected and that the assembly containing your interface definition is selected. You can also do this with an existing service reference by right clicking on it and going to "Configure".
In order to return an interface from a service you need to use the KnownType attribute:
http://weblogs.asp.net/avnerk/archive/2006/07/31/WCF-Serialization-part-1_3A00_-Interfaces_2C00_-Base-classes-and-the-NetDataContractFormatSerializer.aspx
If you want to return a custom type from the service:
http://msdn.microsoft.com/en-us/library/bb628653.aspx
Does any of that help?