I'm currently using Castle-Windsor with the WCF Facility to inject all my WCF services. I've just started adding permission requirements using a custom IAuthorizationPolicy, which seems to work when done on a per-method basis on the service, but when the service class itself is marked up with the requirements, I get an exception thrown.
I've set things up based on the example at How To – Use Username Authentication with Transport Security in WCF from Windows Forms. I didn't set up the custom HTTP Module class as I'm using an existing Membership implementation. My IAuthorizationPolicy implementation (HttpContextPrincipalPolicy) is essentially identical.
The essential part of my Web.config is:
<serviceBehaviors\>
<behavior name="MyBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
<serviceAuthorization principalPermissionMode="UseAspNetRoles"
roleProviderName="UserProvider">
<authorizationPolicies>
<clear/>
<add policyType="Website.FormsAuth.HttpContextPrincipalPolicy,Website"/>
</authorizationPolicies>
</serviceAuthorization>
</behavior>
</serviceBehaviors>
Everything seems to work fine when I put the requirements on the method. This is being done like so:
[PrincipalPermission(SecurityAction.Demand, Role = RoleNames.USER_ADMINISTRATION)]
If this is on an OperationContract method, things work as expected. However, if it is moved to the class itself (which implements the ServiceContract) I get the following exception (with most of the extra stuff pruned out):
Castle.MicroKernel.ComponentActivator.ComponentActivatorException {
Message = "ComponentActivator: could not instantiate Services.UserService"
InnerException = System.Reflection.TargetInvocationException {
Message = "Exception has been thrown by the target of an invocation."
InnerException = System.Security.SecurityException {
Message = "Request for principal permission failed."
}
}
}
I've debugged and found that the constructor on HttpContextPrincipalPolicy is being called but Evaluate() is not when the demand is attached to the class. When it is attached to the method Evaluate() is being called. So at this point I've gone as far as my newbie .NET/WCF/Castle-Windsor skills will take me.
Is there a way to tell Castle-Windsor to invoke the service constructor while honoring the IAuthorizationPolicy? Or tell WCF that Evaluate() needs to be called for the creation of the class? Or is there some other way around WCF that does the same thing? I don't want to have to mark up every single method with the exact same bit of attribute declaration.
When you mark the class itself up with a PrincipalPermissionAttribute it's effectively saying to the runtime that at the point when the class is used the permission demand must be met. So now when Castle-Windsor is trying to instantiate the class, the permission demand is being made and of course it can't be fulfilled because the security context isn't established correctly at that point.
AFAIK, PrincipalPermissionAttribute is not supported on the class level for WCF due to the nature of its runtime even though it is allowed from a pure .NET perspective. Castle-Windsor is therefore unable to create your service instance for the same reason.
Related
I am new to WCF, I am facing concurrency related issue in my hosted wcf service (.net framework 4.0) on IIS 7 / Windows 2008 server. I did all the possibilities after googling but still not able to fix my problem. I have created and inventory service which uses Entity Framework to fetch data from SQL Server tables like ItemHeadMaster, ItemMaster etc.
I referenced this WCF in my custom user search control for searching purposes. All is running well when 2 concurrent user hit search control placed on ASP.Net page.
My code looks like this:
namespace HIS.STORESERVICES
{
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)]
public class StoreMasterData : IStoreMasterData
{
public string GetAllItemHead(string strHospitalId)
{
using (DAL.ItemHeadMaster objItemHeadMasterDAL = new DAL.ItemHeadMaster())
{
List<STORE.MODEL.ItemHeadMaster> objItemHeamMasterList = new List<STORE.MODEL.ItemHeadMaster>();
objItemHeamMasterList = objItemHeadMasterDAL.GetAllItemHead(strHospitalId);
XmlSerializer Xml_Serializer = new XmlSerializer(objItemHeamMasterList.GetType());
StringWriter Writer = new StringWriter();
Xml_Serializer.Serialize(Writer, objItemHeamMasterList);
return Writer.ToString();
}
}
}
I did following after googling:
added in config but NO EFFECT
<system.net>
<connectionManagement>
<add address="*" maxconnection="100" />
</connectionManagement>
</system.net>`
Added in config but NO EFFECT instead it gets more slow..
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" />
<serviceThrottling maxConcurrentCalls="32"
maxConcurrentInstances="2147483647"
maxConcurrentSessions="20"/>
Please help
Before WCF, to construct a service for cross process communications between processes in the same host, or in the same LAN, or in the Internet, you have to hand-craft transportation layers and data serializations for target environments and specific protocols.
With WCF, you just need to focus on creating data models (DataContracts after being decorated by attributes) and operation models (OperationContracts), and .NET CLR will "create" most if not all needed transportation layers and data serializations at run time, according to the configuration defined by you or the system administration in the target environment.
The defects in your codes:
WCF typically uses DataContractSerializer, NOT Xmlserializer to serialize things, and you don't need to call it explicitly, since the runtime will do it.
For most applications, you don't need ServiceBehaviorAttribute explicitly. You must know WCF in depth before using those advantage config which is not for beginner. And I rarely used them.
Your service interface function should comfortably return complex type rather the serialized text. In 99.9% of cases, if you have explicit serialization codes in WCF programs, the whole design is very dirty if not entirely wrong.
There are plenty of tutorials of creating Hello World WCF projects, and VS has one for you when creating a new WCF application. After you got familiar with Hello World, you may have a look at http://www.codeproject.com/Articles/627240/WCF-for-the-Real-World-Not-Hello-World
BTW, WCF serialization is very fast, check http://webandlife.blogspot.com.au/2014/05/performances-of-deep-cloning-and.html
My service methods are marked with PrincipalPermissionAttribute and i have a custom IErrorHandler implementation attached to the service. When an incoming request has no permissions to execute the method System.Security.SecurityException is thrown. IErrorHandler.ProvideFault() is then triggered and i want to provide a special fault. But error parameter is not original exception, it's untyped FaultException. Moreover, error.InnerException is null despite i have the following setting in the config:
<serviceDebug includeExceptionDetailInFaults="true"/>
Why? How can i achieve the desired behavior?
According to this SecurityException is kind of "special" for WCF:
SecurityException is related to CAS
(Code Access Security), and it is a
fatal exception. Since this exception
is not related to any service model
exceptions, it cannot be handled by
IErrorHandler.
So i ended up by creating additional class which methods (called from the methods of the class implementing the service interface) are marked with PrincipalPermissionAttribute and a handler function with try/catch.
Let say I have a WCF
Foo(int param);
The client is passing in a JSON string. Instead of passing in an integer, they pass in a string.
The system now returns a 500 error back to the client. The event log says that I need to add includeExceptionDetailInFaults="true" to my config file if I want a friendly message to be returned. I go and do that but then I still get the 500 error and an event log error stating that I cannot add the 'serviceDebug' extension to my endpoint behavior because the underlying behavior type does not implement the IEndpointBehavior.
What does that suppose to mean?
First of all: where did you add the <serviceDebug> behavior, and how? Can you show us? The <serviceDebug> needs to be added to the <serviceBehavior> section on your server - not the endpoint behavior section. It's a service behavior, after all (it affects the whole service) - not an endpoint behavior (which affects only a single endpoint but not others).
So you should have:
<serviceBehaviors>
<behavior name="debug">
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
in your server-side config (web.config or app.config), and then apply that service behavior to your service tag:
<services>
<service name="...."
behaviorConfiguration="debug">
....
Secondly: error 500 is an internal server error, so this means, the server couldn't interpret and handle your input. The best bet would be to do some client-side validation before actually sending this input to the service, to avoid these kind of errors.
If you cannot do this, then maybe you need to add some more logic to your service so you can capture and figure out these kind of errors before they blow up your service code.
And thirdly, the ultimate solution: you could write a client-side parameter inspector to catch these wrong parameters even before they're being sent to the server, and react accordingly. WCF is very extensible that way. See the MSDN How To Inspect Or Modify Parameters or this blog post if you're interested in learning more about parameter inspectors.
I have put the attribute [FaultContract(typeof(ExceptionDetail))] for my operation contract. When I am trying to add the service to a client application, I get this error - "Custom tool error: Failed to generate code for the service reference 'ServiceReference1'. Please check other error and warning messages for details."
But when I comment out the FaultContract Attribute, I am able to add the wcf service reference th' my client app.
The point of having FaultContracts is to make it possible to first of all pass back SOAP faults from the service which will not break the communication channel between the server and the client (handling error conditions like .NET exceptions gracefully and interoperably), and secondly, using FaultContracts, your server than throw typed faults (FaultException<T>) and your client can catch those.
If you want or need to be really interoperable, you need to:
define all your FaultContract types as classes decorated with the [DataContract] attribute
catch all .NET exceptions on the server (using e.g. IErrorHandler interface) and turn them into interoperable SOAP faults
If you control both ends of the wire and both ends are .NET, then you can simplify this by one step: on the server, handle all .NET exceptions and turn them into e.g. FaultException<ArgumentOutOfRangeException>, that is, create a "fault of (whatever .NET exception)" and then on the client, catch those typed FaultException and handle them:
[FaultContract(typeof(ArgumentOutOfRangeException)]
[OperationContract]
public void CallService(.......)
and then in your implementation, use this:
try
{
clientProxy.CallService();
}
catch(FaultException<ArgumentOutOfRangeException> ex)
{
// handle the most specific exception first
}
catch(FaultException ex)
{
// handle all other, unspecific server faults
}
catch(CommunicationException ex)
{
// handle all other, client-proxy related WCF errors
}
catch(Exception ex)
{
// handle anything else....
}
Remove that FaultContract, and instead configure includeExceptionDetailInFaults:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="Behavior">
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Use Service Trace Viewer tool from http://msdn.microsoft.com/en-us/library/ms732023.aspx, to view the activity trace .
I had the same problem few minutes ago.
It was due to the absence of a default constructor. Also remember that all properties must have public get/set accessors.
I am working on a project that is using NetTcp bindings for talking to some WCF services. When first starting out we took a bad practice example from another application that made WCF calls by using the following:
EntityObject sample = new ServiceProxy().GetEntity();
That worked great until we realized WCF was holding onto the connections even though the aspx page had been sent to the client (which I naively assumed would clean up any connections). While the connections were held on causing things to eventually slow down, ELMAH logged any errors and sent us full stack traces. To resolve the performance issues we changed to this:
using (ServiceProxy proxy = new ServiceProxy())
{
sample = proxy.GetEntity();
}
This made performance rock comparatively. The downside to this method is whenever an error is received on the proxy the only thing ELMAH can catch is that the channel is now faulted. We then have to dig through logs (the WCF ones setup with sharedListeners in ) to figure out what happened and if it's a serialization error the odds of actually find it become much lower, despite the listeners being setup on both client and server. I've explored the IErrorHandler interface and am going to add support for it to our services, but I was wondering if there are other ways to get detailed errors out of WCF instead of it just saying it faulted with no real information as to why it faulted. This would be especially beneficial if it dies on serializing the object that it could tell us WHY it couldn't serialize.
I think if you call Close() explicitly on the proxy, and put that in a try-catch, you'll get what you want.
See especially this sample:
http://msdn.microsoft.com/en-us/library/aa355056.aspx
Well, you can tell the WCF servive to send back more information than just "something bad happened" by using the serviceDebug behavior.
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ExceptionDetails">
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
This is OK as long as it's a dev/test environment, or an in-house app. But really, service error should be caught (and logged) on the server side - you're on the right path with the IErrorHandler interface.
The client needs to handle client-side exceptions, like TimeoutException and CommunicationException to deal with security exceptions or networks going down and such. Just standard .NET exception handling, really.
Also, the using() is a good idea in general - but not necessarily here, since you could encounter an exception when the ServiceProxy is being disposed of (at the end of the using() {} block), and that won't be caught in this case. You might just need to use a try {...} catch {...} finally {...} block for your service proxies instead.
Marc