SecurityError when calling a HTTPS-WCF Service from Silverlight 4 - silverlight

I have created a simple WCF-Service which I want to be accessible via https. The WCF-Service uses a UserNamePasswordValidator, customBinding and UserNameOverTransport as authentication mode. I run it in the IIS7.5 where I have created a self-signed server certificate.
I try to connect to that service with an Silverlight 4 application. I create a Service Reference in my Silverlight 4 app, and VS 2010 automatically creates the needed code (so obviously it is able to connect to the service and get the information).
When I call the WCF, I get a SecurityException with no infos about the reason.
I have fiddler running to see what is happening.
GET https://my.server:8099/clientaccesspolicy.xml 404 Not Found (text/html)
GET https://my.server:8099/crossdomain.xml 200 OK (text/xml)
So the GET for the crossdomain.xml seems to be the last call to the server.
The crossdomain.xml looks as follows:
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*" />
<allow-http-request-headers-from domain="*" headers="*" />
</cross-domain-policy>
The exception happens, when base.EndInvoke(...) is called on the client and the ExceptionMessage is the following:
{System.Security.SecurityException ---> System.Security.SecurityException: Sicherheitsfehler
bei System.Net.Browser.BrowserHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)
bei System.Net.Browser.BrowserHttpWebRequest.<>c_DisplayClass5.b_4(Object sendState)
bei System.Net.Browser.AsyncHelper.<>c_DisplayClass2.b_0(Object sendState)
--- Ende der internen Ausnahmestapelüberwachung ---
bei System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object state)
bei System.Net.Browser.BrowserHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
bei System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)}
Here is my UserNamePasswordValidator. Note, that included a logger for debugging reasons. Strange thing is, that the logger never writes anything, so it seems, that the Validate function isn't even called.
namespace ServiceConfiguratorDataSource
{
public class UserCredentialsValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (userName != "xyz" || password != "xyz")
{
logging.Logger.instance.StatusRoutine("LogOn Error: " + userName);
throw new FaultException("Credentials are invalid");
}
else
{
logging.Logger.instance.StatusRoutine("LogOn Success: " + userName);
}
}
}
}
Here is the Web.config of my WCF-Service:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="ServiceConfiguratorDataSource.Service" behaviorConfiguration="ServiceConfiguratorDataSourceBehaviour">
<endpoint address="" binding="customBinding" bindingConfiguration="ServiceConfiguratorCustomBinding" contract="ServiceConfiguratorDataSource.IService" />
</service>
</services>
<bindings>
<customBinding>
<binding name="ServiceConfiguratorCustomBinding">
<security authenticationMode="UserNameOverTransport"></security>
<binaryMessageEncoding></binaryMessageEncoding>
<httpsTransport/>
</binding>
</customBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceConfiguratorDataSourceBehaviour">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="ServiceConfiguratorDataSource.UserCredentialsValidator,ServiceConfiguratorDataSource" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
and here the ServiceReferences.ClientConfig
<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding name="CustomBinding_IService">
<security authenticationMode="UserNameOverTransport" includeTimestamp="true">
<secureConversationBootstrap />
</security>
<binaryMessageEncoding />
<httpsTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="https://my.server:8099/ServiceConfiguratorDataSource/Service.svc" binding="customBinding" bindingConfiguration="CustomBinding_IService" contract="WCFDataProvider.IService" name="CustomBinding_IService" />
</client>
</system.serviceModel>
</configuration>
I'm out of ideas what might be the cause of the problem.
Thanks in advance,
Frank

Does you clientaccesspolicy.xml allow https?
Here is example.

The working clientaccesspolicy.xml -> Tipp from Samvel Siradeghyan
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="*">
<domain uri="https://*"/>
<domain uri="http://*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>

Related

WCF Silverlight service returns custom fault but as HTTP 500 response not 200

It seems like I've been banging my head with custom faults in my Silverlight WCF service forever so I will happily DO MY BEST TO BUY A BEER for anyone who can help me solve this!!!
After much pain I finally have my WCF service throwing custom errors (ParameterValidationFault) and using Fiddler I know that the service's response contains my serialized fault object, but the HTTP response code is 500, not 200, so the client starts throwing exceptions rather than reading the response.
I know my SilverlightFaultBehavior class is supposed to take care of changing the response status code, but the breakpoints I set there are never being hit, so I'm hoping this is a simple web.config issue (web.config at end of post).
If this is relevant my web.config shows "the element 'behavior' has invalid child element 'silverlightFaults'...", in the section
<endpointBehaviors>
<behavior name="SilverlightFaultBehavior">
<silverlightFaults/>
</behavior>
</endpointBehaviors>
but I thought this wasn't a problem as I can view the service's metadata without error. However now I'm thinking this is the missing link that's preventing my status code from being changed on the way out. I have read that this error indicates a problem with the type attribute within my behaviorExtension element not exactly matching what .NET thinks it should be, but I have checked this a million times and the namespace and assembly name are definitely correct. I haven't messed with the version, culture, or public key stuff.
Is there a simple way for .NET to tell me exactly what this type string should be (spaces, commas, and all)? I have viewed the dll's properties in explorer but I'm still no closer.
Any other suggestions on where this might be coming from would be hugely appreciated.
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="silverlightFaults" type="my.namespace.SilverlightFaultBehavior, AssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
<behaviors>
<endpointBehaviors>
<behavior name="SilverlightFaultBehavior">
<silverlightFaults/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding name="my.namespace.IService.customBinding0">
<binaryMessageEncoding />
<httpTransport />
</binding>
</customBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="my.namespace.IService">
<endpoint address="" binding="customBinding" bindingConfiguration="my.namespace.IService.customBinding0" contract="my.namespace.IService" behaviorConfiguration="SilverlightFaultBehavior" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
</configuration>
My SilverlightFaultBehavior class starts like this and is a copy-paste of this MSDN post with a namespace change
namespace my.namespace
{
public class SilverlightFaultBehavior : BehaviorExtensionElement, IEndpointBehavior
{
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
OK so this problem has not been resolved but worked-around. I finally saw in this very useful post that I can have anonymous endpointBehaviors. The behaviour is now applied and custom faults are correctly (in a non-standard kind of way) returned as HTTP 200s. Making the behavior anonymous means it is applied to all endpoints, but as my service currently only needs a single endpoint this works for me.
It truly sucks that I had all this grief after reading the friggin manual and implementing it word for word. In the end my config parse error "the element 'behavior' has invalid child element 'silverlightFaults'..." was irrelevant, but a very smelly red-herring along the way as it very well could have been the cause (and still may be).
In case anyone is wondering, I just drank the beer.

PrincipalPermission.Demand() failing once WCF Service was moved to SSL

My Silverlight/WCF application uses PrincipalPermission in each service method to ensure the user is Authenticated. This works just fine when I have everything configured to HTTP, but once I configured my service endpoints/bindings to support HTTPS (SSL), I get an exception thrown when I call the Demand() method of my PrincipalPermission object.
EDIT: I should mention I am using IIS 7.5 Express to host and debug this project.
Here is the method that checks to make sure the user is authendicated. It's called from each of my service methods:
protected void SecurityCheck(string roleName, bool authenticated)
{
System.ServiceModel.Web.WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.OK;
PrincipalPermission p = new PrincipalPermission(null, roleName, authenticated);
try
{
p.Demand();
}
catch (Exception ex)
{
/* wrap the exception so that Silverlight can consume it */
ServiceException fault = new ServiceException()
{
/* Code = 1 will mean "unauthenticated!" */
Code = 1, Message = ex.Message
};
throw new FaultException<ServiceException>(fault); }
}
}
The execption thown is "Request for principal failed."
Here are the important bits of my web.config file:
<behavior name="BinarySSL">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="6553600"/>
<serviceTimeouts transactionTimeout="00:10:00"/>
</behavior>
<binding name="MyApp.Web.Services.ProjectService.customBinding0"
receiveTimeout="00:10:00" sendTimeout="00:10:00">
<binaryMessageEncoding />
<httpsTransport authenticationScheme="Basic"/>
</binding>
<service name="MyApp.Web.Services.ProjectService" behaviorConfiguration="BinarySSL">
<endpoint address="" binding="customBinding" bindingConfiguration="MyApp.Web.Services.ProjectService.customBinding0"
contract="MyApp.Web.Services.ProjectService" />
</service>
Here is the ClientConfig:
<binding name="CustomBinding_ProjectService">
<binaryMessageEncoding />
<httpsTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
<endpoint address="https://localhost:44300/Services/ProjectService.svc"
binding="customBinding" bindingConfiguration="CustomBinding_ProjectService"
contract="ProjectProxy.ProjectService" name="CustomBinding_ProjectService" />
I'm hoping someone can point in in the right direction here. Again, this configuration works just fine until I configure my services for SSL. Any thoughts?
Thanks,
-Scott
I thought I found the problem, and answered my own question - but I was wrong. Still have the same issue.

Silverlight 4 & WCF Cannot insert data record with a long sting as a method param

I'm working on a project using Silverlight 4 and WCF. All of the web methods, exept one are working fine. In Silverlight I use a custom xaml writer to write a string and I want to save the string in a database. Using the Insert method on the web service, I can insert data as long as the string parameter is not too large. When trying to insert the string created by the xaml writer, I get an error. I used Fiddler to trace the error and I"m getting and HTTP 400 error. I have read in numerous post that I need to change the config settings on the servce hosting in the web app and in the client config in the Silverlight app. I have made all the changes that I could find on the web. I don't know what else to try and I have ran out of resources. When I paste the xaml string into Notepad and save it, the file is only 425 KB. Here are the changes I've made to each config file. Hopefully someone can pointout anyting I'm missing. Thank you for looking over my issue.
web.config file in web app:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<!-- Enable the serializer to serialize greater number of records -->
<behavior name="CustomServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="CustomBinding">
<readerQuotas maxDepth="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
ServiceReferences.ClientConfig:
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_DBService" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost.:49436/BuilderWebService/DBService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_DBService"
contract="ServiceReference1.DBService" name="BasicHttpBinding_DBService" />
</client>
</system.serviceModel>
In your web.config in the binding tag you shoiuld add attributes: maxBufferPoolSize, maxReceivedMessageSize, maxBufferSize:
<basicHttpBinding>
<binding name="CustomBinding"
maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647">
<readerQuotas maxDepth="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647"
maxStringContentLength="2147483647" />
</binding>
</basicHttpBinding>
In my example, I've provided the maximal values for the sizes, but you can define the sizes you actually need. Hope it will help you.

The remote server returned an error: NotFound

I have a Silverlight app that consumes a WCF service in my asp.net application.The silverlight app saves "drawings" in the form of ink strokes. These strokes are in the form of xaml (which can be kind of large) of which I am converting to a string and sending to the service to save the string to sql server. (Basically does the same type of thing as this app http://msdn.microsoft.com/en-us/magazine/cc721604.aspx).
This works and I can see my service method is being hit when the drawing is relatively small, but if the drawing gets to big I get this great error and the services method break point never gets hit. It seems that I am passing a size threshold, but I can't figure out if I'm right or what to change to resolve the issue.
I have seached google and SO with no success, so any help would be appreciated. Thanks in advance.
My Service:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class DrawingService: IDrawingService
{
#region IDrawingService Members
public bool SaveEvalAreaDrawing(int EvalAreaId, string xmlToSave)
{
return true;
}
public bool SaveEvalItemDrawing(int EvalItemId, string xmlToSave)
{
return true;
}
public string GetEvalAreaDrawing(int EvalAreaId, string xmlToSave)
{
return "you got the eval drawing!";
}
public string GetEvalItemDrawing(int EvalItemId, string xmlToSave)
{
return "you got the eval item drawing!";
}
#endregion
}
My asp.net app with service web.config
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyNameSpace.Services.DrawingServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding name="customBinding0">
<binaryMessageEncoding />
<httpTransport>
<extendedProtectionPolicy policyEnforcement="Never" />
</httpTransport>
</binding>
</customBinding>
<wsHttpBinding>
<binding name="wsPlainBinding" maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="None">
<transport clientCredentialType="None">
<extendedProtectionPolicy policyEnforcement="Never" />
</transport>
<message clientCredentialType="None" negotiateServiceCredential="false"
establishSecurityContext="false" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<services>
<service behaviorConfiguration="HSD.ECERS.Services.DrawingServiceBehavior"
name="HSD.ECERS.Services.DrawingService">
<endpoint address="Services" binding="wsHttpBinding" bindingConfiguration="wsPlainBinding"
name="wsPlainHttp" contract="HSD.ECERS.Services.IDrawingService" />
<endpoint address="mex" binding="mexHttpBinding" name="wsdl"
contract="IMetadataExchange" />
</service>
</services>
ServiceReferences.ClientConfig
<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding name="wsPlainHttp">
<textMessageEncoding messageVersion="Default" writeEncoding="utf-8" />
<httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647">
<extendedProtectionPolicy policyEnforcement="Never" />
</httpTransport>
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://localhost:41594/Services/DrawingService.svc/Services"
binding="customBinding" bindingConfiguration="wsPlainHttp"
contract="EvalDrawingService.IDrawingService" name="wsPlainHttp" />
</client>
</system.serviceModel>
</configuration>
Where VS is showing the error
public bool EndSaveEvalAreaDrawing(System.IAsyncResult result) {
object[] _args = new object[0];
bool _result = ((bool)(base.EndInvoke("SaveEvalAreaDrawing", _args, result))); // Here is where is popping up
return _result;
}
Exception
{System.ServiceModel.CommunicationException: The remote server returned an error: NotFound. ---> System.Net.WebException: The remote server returned an error: NotFound. ---> System.Net.WebException: The remote server returned an error: NotFound.
at System.Net.Browser.BrowserHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)
at System.Net.Browser.BrowserHttpWebRequest.<>c__DisplayClass5.<EndGetResponse>b__4(Object sendState)
at System.Net.Browser.AsyncHelper.<>c__DisplayClass4.<BeginOnUI>b__1(Object sendState)
--- End of inner exception stack trace ---
at System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object state)
at System.Net.Browser.BrowserHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)
--- End of inner exception stack trace ---
at System.ServiceModel.AsyncResult.End[TAsyncResult](IAsyncResult result)
at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
at System.ServiceModel.ClientBase`1.ChannelBase`1.EndInvoke(String methodName, Object[] args, IAsyncResult result)
at EvaluaionAncillaryControl.EvalDrawingService.DrawingServiceClient.DrawingServiceClientChannel.EndSaveEvalAreaDrawing(IAsyncResult result)
at EvaluaionAncillaryControl.EvalDrawingService.DrawingServiceClient.EvaluaionAncillaryControl.EvalDrawingService.IDrawingService.EndSaveEvalAreaDrawing(IAsyncResult result)
at EvaluaionAncillaryControl.EvalDrawingService.DrawingServiceClient.OnEndSaveEvalAreaDrawing(IAsyncResult result)
at System.ServiceModel.ClientBase`1.OnAsyncCallCompleted(IAsyncResult result)}
Try increasing the readerQuotas -- add this element inside the binding element
<readerQuotas maxStringContentLength="2147483647" />
http://msdn.microsoft.com/en-us/library/ms731325.aspx
Have you tried turning on WCF Tracing? I'm not sure if that works with Silverlight (given that Silverlight has lots of security limitations in terms of the local harddrive), so you might need to set up a simple no silverlight client and reproduce the call with diagnostics turned on.
EDIT: Or, could be the maxArrayLength member of readerQuotas...

silverlightFaultBehavior for WCF - but still getting code 500

I want to get a meaningful error message from my WCF service for my Silverlight 4 application. After some investigation, I found that I need to change the reply code from 500 to 200 if I want silverlight enable to read the meaningful error message. Here is the article: http://msdn.microsoft.com/de-de/library/ee844556(VS.95).aspx
I have implemented it as it is written there, the application compiles and I can use the service - but I still get the 500 return code. The main difference I see is that I call the service via HTTPS not HTTP. Maybe this is the reason, why it doesn't work? Any idea, how to get the return code 200?
Here is my Web.Config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="ServiceConfiguratorDataSource.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="silverlightFaults" type="ServiceConfiguratorDataSource.SilverlightFaultBehavior, ServiceConfiguratorDataSource, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
<services>
<service name="ServiceConfiguratorDataSource.Service" behaviorConfiguration="ServiceConfiguratorDataSourceBehaviour">
<endpoint address="" binding="customBinding" behaviorConfiguration="SLFaultBehavior" bindingConfiguration="ServiceConfiguratorCustomBinding" contract="ServiceConfiguratorDataSource.IService" />
</service>
</services>
<bindings>
<customBinding>
<binding name="ServiceConfiguratorCustomBinding">
<security authenticationMode="UserNameOverTransport"></security>
<binaryMessageEncoding></binaryMessageEncoding>
<httpsTransport/>
</binding>
</customBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceConfiguratorDataSourceBehaviour">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="True"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="ServiceConfiguratorDataSource.UserCredentialsValidator,ServiceConfiguratorDataSource" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="SLFaultBehavior">
<silverlightFaults/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
... and here the silverlightFaultBehavior.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel;
namespace ServiceConfiguratorDataSource
{
public class SilverlightFaultBehavior : BehaviorExtensionElement, IEndpointBehavior
{
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
SilverlightFaultMessageInspector inspector = new SilverlightFaultMessageInspector();
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
}
public class SilverlightFaultMessageInspector : IDispatchMessageInspector
{
public void BeforeSendReply(ref Message reply, object correlationState)
{
if (reply.IsFault)
{
HttpResponseMessageProperty property = new HttpResponseMessageProperty();
// Here the response code is changed to 200.
property.StatusCode = System.Net.HttpStatusCode.OK;
reply.Properties[HttpResponseMessageProperty.Name] = property;
}
}
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
// Do nothing to the incoming message.
return null;
}
}
// The following methods are stubs and not relevant.
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
public override System.Type BehaviorType
{
get { return typeof(SilverlightFaultBehavior); }
}
protected override object CreateBehavior()
{
return new SilverlightFaultBehavior();
}
}
}
Someone knows if this is because of https ... and if so, how to get it to work?
Thanks in advance,
Frank
EDITH says: I just have added some logging: the ApplyDispatchBehavior - method is called, but the BeforeSendReply - method not ... any ideas why?
If I remember correctly, the UserNamePasswordValidator gets called very early in the pipeline, before the dispatcher ever gets called, which is why your custom dispatch behavior isn't affecting anything. (The reason is security: WCF wants to "throw out" unauthorized requests as early as possible, while running as little code as possible for them).
As you yourself suggested in the comments, one solution would be to just validate the credentials later in the pipeline - e.g. in every operation (or maybe even in a message inspector's AfterReceiveRequest?)

Resources