In my services all the methods except certain mandatory parameters and all the input parameters are encapsulated inside message contract.
Right now, we are validating the input in each and every service method, Its like duplicating validation logic in all the service methods. Is there any way I can move all these validation to common place and more over I don't want my service method to be executed as the input is not valid.
Appreciate your suggestions.
Yes, you can use FluentValidator for each MessageContract request.
You can write the commom validator for the request which have common validation rules.
Ex: If you want the validate employee profile in both CreateEmployeeRequest, UpdateEmployeeRequest then you can write the commom validator for Employee Profile (EmployeeProfileValidator) and make use of this validator in Create & Update Employee request validators..
Enterprise Library Validation Application Block has a module for Integration with WCF.
It implements input validation as a WCF parameter inspector. Your method will never be called if it the parameters fail validation.
Related
I'd like some help with this one.
I want to return some kind of validation exception from my WCF service if the given entity data doesn't pass the business logic, but I'm not sure the best way to return muliple things from a WCF Service (for example a validation error and a list of entities).
This one might be really simple, but even so, I'd appreciate a little help.
I would suggest you take a look at the Enterprise Library Validation Block:
http://msdn.microsoft.com/en-us/library/ff648951.aspx
http://msdn.microsoft.com/en-us/library/ff648939.aspx (note this is for EntLib 3.1, which is a bit dated, but even in EntLib 5, WCF integration works similarly)
I've used this approach a number of times for WCF validation and it works out quite well. You'll end up decorating your data contracts with validation attributes that are part of EntLib. This defines what your validation rules are. Then you configure your service to use Enterprise Library's WCF extensibility. This is an endpoint behavior, so essentially this intercepts any incoming messages for your serivce, checks that all the defined validation attributes pass and then sends the message on to your service option. If the rules specified by your validation attributes don't pass then the endpoint behavior returns a fault message that contains the details about all validation failures. So, if one attribute didn't pass, there would be one message. If three attributes didn't pass, you'd have three messages and so on. Each validation failure message references what property didn't pass validation. The nice thing about the EntLib validation WCF integration is that the fault messages used for validation failures are strongly types and available in your service's WSDL. This means that your clients can easily consume these faults and act upon them appropriately.
If you feel like Enterprise Library is a little too heavy for your needs then you could certainly roll your own validation. You'd probably want the data contracts returned by your service operations to include something like a List that cotains validation messages.
I implement a ASP.NET MVC3 application, where data is accessed through WCF services.
The WCF service uses EF4.1 for data access with DBContext and POCO classes for entities.
I can annotate the properties with data validations attributes on the server side, and also I can implement custom validation by defining either custom validation attributes (derived from ValidationAttribute), or by implementing IValidatableObject ).
But I have a problem: if validation fails, what is the best approaoch to pass validation error info from WCF to client, and then use it in MCV3 client?
As I understand with WCF, every data exchanged between client and WC service should be part of the data contract, and should not use exceptions as ways of passing meaningful information between server and client (like throwing a ValidationException with extra properties set for Validation failure info).
Also in WCF who uses EF I call dbContext.SaveData(), but if data is not valid, it throws exception, which I don't want.
So:
how can I call validation explicitly in EF and make sure either the object is valid and I can call SaveData(), or the object is invalid and I can collect somehow validation failure information to pass to client.
Haw can I pass this validation failure information back to client, as part of data contract, and not an an exception.
Thanks
You can use two approaches:
Use standard response data contract for success and fault contract with FaultException<YourFaultContract> for validation failure. Typed fault exceptions are way to define "expected" exceptions - it is just another data contract passed in SOAP Fault describing some failure.
Create response data contract which contains something like result code, response data, failure message etc. and use this data contract for both success and failure. I don't like this approach but it is easier to use in some ESB where faults are processed in special way.
What's the use of action/reply action for service operation in WCF. So far, what I've understood is; action is used by WSDL to identify the service operation to which the message from the client belongs and in return reply action is used by service operation to identify the caller to which reply message belong --> Please correct me if I am wrong with this!
Now, I want to understand; what's the real use (apart from handling anonymous messages by using aster ix [*]), I mean this could well be handled internally by WCF instead of exposing it to the developer.
Also, why is action and replyaction required at all? I mean, we already have a name property for the service operation to identify the method and when I call Proxy.SomeMethod() then somemethod is already mapped to the Name property and it should be enough to identify the destination method for the message and similarly the replyaction. Please clarify.
Can I please get a simple real world scenario/or link to that to understand Action/ReplyAction in real life.
Many Thanks.
Actions are part of the various SOAP and WS-* specifcations.
So the first point is that this is not something unique to WCF it is a standard part of the specification you need to support if you want to have interoperable web services. They are used for message routing and other message handling functions.
Second, WCF DOES manage these by default. You only need to specify them yourself if you wish to customise or manage them in some other way. E.g. WCF will automatically generate them into the WSDL for you. WCF will also use them by default when it is selecting which operation to invoke for an incoming message. Again, WCF provides extension points to customise this behavior if you require.
I am looking to extend existing services and add Authorization to every call being made. The problem I have is that I don't know how to do this in the best possible manner. What I need to do is to send the name of the module calling the WCF service. I already send the username and password for the service and now I need to extend that with the name of the module calling the service. This is because we might allow a user to open a module and display data from another module but not from a third.
If we would have used message contracts I would just add a MessageHeader for this and set that header when I create the request. That is unfortunately not an option with DataContracts so I was considering the following two alternatives.
Adding a DataMember in a base class with Order=1000 or something like that. I don't know what will happen if we add another DataMember before that though?
Create the property for the module name and set a header in the transport instead. Not really fond of this one though. It's pretty abstract and hard to follow.
Which one is the least evil or do you have a better suggestion?
EDIT 1: The problem is not how to send a header to the service the problem is how to send a header with a specific value to the server. In the message inspector I can only create generic instances with message.GetBody<DataContract>(); this means I have to know the type which I don't know how to.
EDIT 2: The issue here is that in our application we want to restrict access to a call based on from where the call is made so I need to pass this information. Let's say I make the call to MyService from FindUserModule then I need to add the id of that module in a header so that the AuthorizationManager can check if that user really should be authorized. This is due to service calls being used from many modules.
Handle this as SOAP header in custom message inspector.
Long post - sorry....
I'm doing input validation for a WCF service and using StructureMap IoC to instantiate the appropriate validation objects.
I have 2 different validation groups:
Per object validation: means that one input parameter, will be resolve by the Ioc (e.g. Ioc.ResolveAll<IValidatorObject<InputParameter1>, .... <InputParameter2>... etc). If any rules are found, the validate method is invoked.
Per context validation: mean that validation rules are invoked, based on the current context (explicit roles). A context could be 'deposit money' or 'open bank account'. Context validation are usually dependent on 2 or more of the input parameters and is the key difference between object and context validation.
The input validation is performed in the BeforeCall event call in the IParameterInspector (provider/server side!). With this event I get a string containing the operation name (aka. the context) and an object[] with the input parameters.
The problem is that there's multiple validation rules for a single context and the only way I have figured out to register the context in the Ioc, is by using named intances. However I can only register 1 named instance pr. interface. And the interface is not uniquely identifiable by its signature. E.g.
Context rule for 'create account': IValidatorContext<User, Account>
Context rule for 'deposit money': IValidatorContext<User, Account>
So my question is, whether it is possible to register the context in StructureMap in any other way than named instances - or maybe a way to group named instances.
An alternative route, is to implement explicit interfaces for each context, so that the DepositMoney service method might look like this:
public Response Deposit(IDepositMoney inputArguements)
where IDepositMoney contains the input parameters.
So am I way off here, or can I somehow register a context in StructureMap? Or should I just go ahead and use explicit interface instead (3rd option?)
Thanks in advance
Ended up wrapping each set of input parameters in a context and used the context to register in StructureMap. Works like a charm!
The whole idea of named instances is that the name points to a single instance, so you won't be able to use that feature to do what you are trying to achieve. I would use explicit interfaces, since this will allow you to auto wire more things and have less calls to your container.