WCF Authentication on the Internet - wcf-security

I have a WCF service using the basicHTTP binding. The service will be targeted to be deployed
in production in a DMZ environment on a Windows Server 2008 64 bit running IIS 7.0 and is not
in an Active Directory domain.
The service will be accessed by a business partner over the Internet with SSL protection. Originally,
I had built the service to use x.509 Message authentication with wsHTTPBinding and after a lot of
problems I punted and decided to back up and use basicHTTP with UserName authentication.
Result: same exact, obscure error message as I received with certificate mode.
The service works perfectly inside our domain with the exact same authentication but as soon as
I move it to the DMZ I get an error reading: "An unsecured or incorrectly secured fault was received
from the other party. See the inner FaultException for the fault code and detail".
The inner exception message is: "An error occurred when verifying security for the message."
The services' web config with binding configuration is as follows:
<services>
<service behaviorConfiguration="HSSanoviaFacade.Service1Behavior" name="HSSanoviaFacade.HSSanoviaFacade">
<endpoint address="" binding="basicHttpBinding" contract="HSSanoviaFacade.IHSSanoviaFacade" bindingConfiguration="basicHttp">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="https://FULLY QUALIFIED HOST NAME CHANGED TO PROTECT/>
</baseAddresses>
</host>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="basicHttp">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="HSSanoviaFacade.Service1Behavior">
<serviceMetadata httpsGetEnabled="True" />
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
The test client's configuration that gets the error:
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IHSSanoviaFacade" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://HOST NAME CHANGED TO PROTECT"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IHSSanoviaFacade"
contract="MembersService.IHSSanoviaFacade" name="BasicHttpBinding_IHSSanoviaFacade" />
</client>
As mentioned earlier, the service works perfectly on the domain and the production IIS box is not on a domain.
I have been tweaking and pulling my hair out for 2 weeks now and nothing seems to work. If anyone can help I
would appreciate it. Even a recommendation for a work around for authentication. I'd rather not use a custom
authentication scheme but use built-in SOAP capabilities.
The credentials pass in thru the proxy i.e. proxy.ClientCredentials.UserName.UserName and
proxy.ClientCredentials.UserName.Password are valid accounts on both the internal domain in the test
environment and as a machine account on the DMZ IIS box.

Well, maybe not exactly what I wanted but I got it to work. Must be a difference in IIS in a domain versus not.
Here are my changes to the service web config:
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
As I understand it, this doesn't pass the credentials in the SOAP header but in the HTTP header which means message level security doesn't work in this scenario. Its all protected by an SSL certificate.

Related

WCF - Production server only - An error occurred while receiving the HTTP response

I am facing an strange issue on our production server that is
An error occurred while receiving the HTTP response to http://end-http://xxxxx/Main.svc. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.
Website and WCF service are deployed on same server and its perfectly working fine on our QA environment but same code & binding settings are not working on production server.
We have below binding settings on WCF service
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding closeTimeout="00:05:00" openTimeout="00:05:00" sendTimeout="00:05:00" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false before deployment -->
<serviceMetadata httpGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
WCF Client
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IMain" maxBufferSize="2147483647" maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://abc/DataService/Main.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IMain" contract="DALService.IMain"
name="BasicHttpBinding_IMain" />
</client>
</system.serviceModel>
Could someone help one me on this to sort out this issue?
Many Thanks
Micky
Finally , I have managed to fix it & fix is to add below setting in WCF server config.
<serviceBehaviors>
<behavior>
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
</serviceBehaviors>

Namespaces for WCF Web.config, client and server side, maxReceivedMessageSize

I'm not a VB developer and I'm having some issues with Namespace for a Web service. I own both the client and server side of this so I have no issues changing settings.
I'm trying to connect to a webservice and while doing so I get a MaxReceivedMessageSize exception.
They way I go about this is that I have a solution with a "web project" and more "class projects", in one of my "class projects" I have a Service reference and a app.config file where I do my settings.
I have read that I need to have app.config settings in my application and add settings on server web.config for the web service. I'm confused about the namespaces I need to set in the web.config for the web.service on server side. Can anybody help me out a bit? I use this settings
(server)
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="Erp_QueryServiceSoap" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="16348" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="WebService.Erp_QueryService.Erp_QueryServiceSoap">
<endpoint address="Erp_QueryService.Erp_QueryServiceSoap"
binding="wsHttpBinding" bindingConfiguration="Erp_QueryServiceSoap"
contract="Erp_QueryService.Erp_QueryServiceSoap" name="Erp_QueryServiceSoap" />
</service>
</services>
</system.serviceModel>
(client)
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="Erp_QueryServiceSoap" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="16348" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="CONNECTION TO SERVICE"
binding="wsHttpBinding" bindingConfiguration="Erp_QueryServiceSoap"
contract="ServiceQuery.Erp_QueryServiceSoap" name="Erp_QueryServiceSoap" />
</client>
</system.serviceModel>
i think may be problem is not with namespaces.
try to set maxItemsInObjectGraph to the following.
in behaviour section
<behavior name="YourServiceNameBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
**<dataContractSerializer maxItemsInObjectGraph="2147483647" />**
</behavior>
i think you already have added those codes except
**<dataContractSerializer maxItemsInObjectGraph="2147483647" />**
try adding this code line.

WCF Error - unexpected response: (400) Bad Request

I'm having trouble finding an answer for this problem. Most similar posts lean seem to be fixed by adjusting some of the maximum size settings in the web.config file. However, none of those suggestions have fixed my issue.
To give a little more background, I'm porting a asmx web service, to a WCF web service hosted in Windows Azure. This problem came up during testing. If I pass a small number of transactions to my webservice in a single call, it tends to work just fine. This error come up though when my transaction size gets around 50-60 (transactions). Serialized to xml, the file size is around 300K, so it's nothing insanely large. But it does tend to lean towards a size issue.
Also, turning on WCF tracing, I found the following exception occuring:
System.ServiceModel.ProtocolException: The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.
at System.ServiceModel.Channels.HttpInput.ThrowHttpProtocolException(String message, HttpStatusCode statusCode, String statusDescription)
at System.ServiceModel.Channels.HttpInput.ThrowMaxReceivedMessageSizeExceeded()
at System.ServiceModel.Channels.HttpInput.ReadBufferedMessage(Stream inputStream)
at System.ServiceModel.Channels.HttpInput.ParseIncomingMessage(Exception&amp; requestException)
at System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, Action callback)
So from the exception, it looks as though one of the settings if off in my web.config, but here is what that looks like:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
<behavior name="MetadataEnabled">
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceMetadata httpGetEnabled="true"/>
<useRequestHeadersForMetadataAddress>
<defaultPorts>
<add scheme="http" port="8081"/>
<add scheme="https" port="444"/>
</defaultPorts>
</useRequestHeadersForMetadataAddress>
<dataContractSerializer maxItemsInObjectGraph="111024000"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Bandicoot.Core" behaviorConfiguration="MetadataEnabled">
<endpoint name="HttpEndpoint"
address=""
binding="wsHttpBinding"
bindingConfiguration="wsHttp"
contract="Bandicoot.CORE.IRepricer" />
<endpoint name="HttpMetadata"
address="contract"
binding="mexHttpBinding"
bindingConfiguration="mexBinding"
contract="Bandicoot.CORE.Stack" />
<host>
<baseAddresses>
<add baseAddress="http://localhost/Core"/>
</baseAddresses>
</host>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="wsHttp" maxReceivedMessageSize="111024000"
messageEncoding="Text" maxBufferPoolSize="111024000"
textEncoding="UTF-8">
<readerQuotas maxBytesPerRead="111024000"
maxArrayLength="111024000"
maxStringContentLength="111024000"/>
<security mode="None"/>
</binding>
</wsHttpBinding>
<mexHttpBinding>
<binding name="mexBinding"/>
</mexHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
Does anyone have any other suggestions, or is there something mis-configured in my web.config that I'm just not seeing?
Thanks for any advice!
Edit: Here is the settings from my client's app.config
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_CORE" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="14194304" maxBufferPoolSize="14194304" maxReceivedMessageSize="14194304"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="1000" maxStringContentLength="111024000"
maxArrayLength="111024000" maxBytesPerRead="1024000" maxNameTableCharCount="111024000" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
Edit: adding addition client information:
<client>
<endpoint address="http://localhost:92/CORE.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_CORE" contract="Core.CORE"
name="BasicHttpBinding_CORE" />
</client>
Edit: Attempted changing the service bindings to basicHttpBinding - config changes:
<basicHttpBinding>
<binding name="basicHttp" maxReceivedMessageSize="111024000"
messageEncoding="Text" maxBufferPoolSize="111024000"
textEncoding="UTF-8">
<readerQuotas maxArrayLength="111024000" maxBytesPerRead="111024000" maxStringContentLength="111024000"/>
<security mode="None" />
</binding>
</basicHttpBinding>
<service name="Bandicoot.Core" behaviorConfiguration="MetadataEnabled">
<endpoint binding="basicHttpBinding"
bindingConfiguration="basicHttp"
contract="Bandicoot.CORE.IRepricer" />
<endpoint address="mex"
binding="mexHttpBinding"
bindingConfiguration="mexBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost/Core"/>
</baseAddresses>
</host>
</service>
And the client's app.config as well for reference:
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_CORE" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="100000000"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:92/CORE.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_CORE" contract="Core.CORE"
name="BasicHttpBinding_CORE" />
</client>
You need to be setting the maxReceivedMessageSize on the client (where the message you're returning from your service is incoming) - in its app.config or web.config:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsHttp" maxReceivedMessageSize="111024000"
messageEncoding="Text" maxBufferPoolSize="111024000"
textEncoding="UTF-8">
<readerQuotas maxBytesPerRead="111024000"
maxArrayLength="111024000"
maxStringContentLength="111024000"/>
<security mode="None"/>
</binding>
</wsHttpBinding>
<mexHttpBinding>
<binding name="mexBinding"/>
</mexHttpBinding>
</bindings>
<client name="whatever">
<endpoint name="HttpEndpoint"
address=""
binding="wsHttpBinding"
bindingConfiguration="wsHttp"
contract="Bandicoot.CORE.IRepricer" />
</client>
</system.serviceModel>
The default value for maxReceivedMessageSize is 64K, unless you change it.
I finally figured this one out this morning. The problem was that my service was not using the configuration settings that I thought it was. The reason? The service name in the configuration needs to be a fully qualified path to the service being implemented.
I found this link helpful figuring it out.
I found it a little odd that my service worked without pointing it to an actual endpoint, I guess it just uses a series of default values and if you want something different you can configure them in the web.config? I think this explains why I was getting a basicHttpBinding when I consumed the webservice in my client, instead of wsHttpBinding.
Took a few days to figure it out, but was educational. Thanks for the suggestions!
I had the same error and the cause was revealed to be a configuration error, too.
But in my case this was, like marc_s already posted, the maxReceivedMessageSize setting on the server side. The server was still using its default configuration, which was as low as 64 kb.
As obvious as this now sounds, that long it took me to find out that the error was not on my (client) side.
I hope that this may help someone else.
Hi Question Poster "Brosto"!
This supplements your Nov 17 '10 at 15:29 answer.
We had a “fun”, or should I say “educational” Production Deployment Testing issue today that took most of the day to resolve, and it was literally caused by one keystroke. We only confirmed the source of the problem, after we found out the problem disappeared after the Web Farm was fully deployed.
Here was the cause. When we test our Production Deployment, and do so against a “Single Server” by changing our hosts file, we are bypassing the Load Balancer, and the call to the Single Server ends up going over the default http port 80! When we test against the “Load Balancer”, the call to the Single Server from the Load Balancer, ends up going over the Load Balancer defined port 81!
Since the Service Endpoint Address must be “fully qualified”, to enable the service to find its Custom Bindings, the Services.config file on the Single Server must be changed to reflect the difference between “Single Server” vs “Load Balanced Server” endpoint connections, as follows:
Single Server connection:
endpoint address="http://www.myserver.com:80/Services/MyService.svc"
Load Balanced Server connection:
endpoint address="http://www.myserver.com:81/Services/MyService.svc"
My boss correctly diagnosed the core problem early, saying that the server was acting like the custom bindings were being ignored and the defaults were being used instead. After showing him your comment above where you mention the requirement of “fully qualified” service endpoint address, he realized that the host file redirection was causing our browser request to go to the Single Server over default port 80, instead of the Load Balanced port 81, which in effect altered the fully qualified service endpoint address, which caused the server to ignore the custom bindings and revert to default settings. Please note that it did NOT fail to call the service, it only failed to bind the custom bindings!
Hopefully someone will remember this posting the next time we Production Test a Service with custom bindings :)

WCF service authentication using System.Web.ApplicationServices.AuthenticationService, I can't authenticate to the membership provider

I'm trying to get authenticated using the the Authentication Service and my Membership Provider. Ideally I want to call my membership provider, but I bomb out before hitting my provider. Says a token cannot be validated. Checking my error log, it appears I'm trying to Authenticate using Windows auth. That's not what I'm intending to do. This is a web with an svc file. I use svcUtil and generate a client from the WSDL. I have a test page in the app that I'm using the client from. Its just a test page and will not be deployed. I see Integrated Windows Auth is checked in IIS which doesnt seem correct, but if I uncheck it, Visual Studio won't debug. Anyways I look in the event log and get two errors
Logon Failure:
Reason: Unknown user name or bad password
User Name: sandagtestuser
Domain:
Logon Type: 8
Logon Process: Advapi
Authentication Package: MICROSOFT_AUTHENTICATION_PACKAGE_V1_0
Workstation Name: SDD-CK
Logon attempt by: MICROSOFT_AUTHENTICATION_PACKAGE_V1_0
Logon account: sandagtestuser
Source Workstation: SDD-CK
Error Code: 0xC0000064
Here are the bindings in the web.config. Please note I'm trying to use SSL and HTTPS. This is my first stab at WCF security
<system.serviceModel>
<client>
<endpoint address="https://SDD-CK/ATISServices/Services/AuthService.svc/AuthService"
binding="basicHttpBinding" bindingConfiguration="userHttps_AuthenticationService"
contract="AuthenticationService" name="userHttps_AuthenticationService" >
</endpoint>
</client>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<behaviors>
<serviceBehaviors>
<behavior name="ATISServices.AuthServiceBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="userHttps_AuthenticationService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="true" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="TransportWithMessageCredential">
<transport proxyCredentialType="None" clientCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
<binding name="basic_auth_config">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="ATISServices.AuthServiceBehavior"
name="System.Web.ApplicationServices.AuthenticationService">
<endpoint binding="basicHttpBinding" bindingName="userHttps" bindingConfiguration="basic_auth_config"
bindingNamespace="http://asp.net/ApplicationServices/v200"
contract="System.Web.ApplicationServices.AuthenticationService"
address="AuthService"/>
<endpoint address="mex" binding="mexHttpsBinding" bindingConfiguration=""
contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
Perhaps some WCF guru out there can help me correct the problem. I see the credentials getting up to the server via the event log, so I must not be too terribly far off. The actual InnerException message on the fault is At least one security token in the message could not be validated.
Lastly here are some additional web.config settings that may be of interest.
<system.web.extensions>
<scripting>
<webServices>
<authenticationService enabled="true" requireSSL="true"/>
</webServices>
</scripting>
</system.web.extensions>
<authentication mode="Forms" >
<forms cookieless="UseCookies" />
</authentication>
<membership defaultProvider="KCMembershipProvider">
<providers>
<clear/>
<add
name="KCMembershipProvider"
applicationName="/"
type="zcore.MembershipProvider.KCMembershipProvider, zcore.MembershipProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</providers>
</membership>
Any help or tips at this point would be greatly appreciated. I've battled with this for two days. I'm using certificates as well. I made them with 'makecert' tool. One is a Cert Authority and the other is a 'localhost' cert using said Authority. I also have used httpcfg and set the cert thumbprint to port 9307, however when i put ":9307" on the service address, I get connection actively refused. I truly appreciate any help here.
Cheers,
~ck in San Diego
This actually got it to work. Adding this to the service behavior.
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="KCMembershipProvider"/>
</serviceCredentials>

WCF timing out intermittently

All,
I have a WCF service that times out intermittently, usually after about ten or twelve requests from the asp.net client. The service uses reflection to find classes in its assembly (WAP dll) that have a custom attribute set. The process itself is very quick, usually taking only a few milliseconds, and when it works, it works great.
Setting a breakpoint in the calling code and in the service itself tells me that the timeout is occurring between the call from the WCF client proxy class and when that method is actually executed.
Ideas?
Update: binding, etc from web.config:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="Sdd.Services.ControlPanelBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="Sdd.Services.ControlPanelBehavior"
name="Sdd.Services.ControlPanel">
<endpoint address="" binding="wsHttpBinding" contract="Sdd.Services.IControlPanel">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
UPDATE: And here's the relevant portion from the client's web.config:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IControlPanel" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text"
textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:81/services/ControlPanel.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IControlPanel"
contract="PublicSite.IControlPanel" name="WSHttpBinding_IControlPanel">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
Whoops!
This is probably the most idiotic of mistakes, but I figured out the problem: since I'm used to using web references (.asmx web service) instead of service references (WCF), I neglected to close the proxy object. Changed
[WebMethod]
public static List<Page>PagesGetAll()
{
ControlPanelClient cp = new ControlPanelClient();
Page[] pageArray = cp.NavigationPagesGetAll();
List<Page> pageList = pageArray.ToList<Page>();
// make sure that the page list in the database is up-to-date.
foreach(Page page in pageList)
Navigation.PageUpdate(page);
return pageList;
}
to
public static List<Page>PagesGetAll()
{
List<Page> pageList = null;
using (ControlPanelClient cp = new ControlPanelClient())
{
Page[] pageArray = cp.NavigationPagesGetAll();
pageList = pageArray.ToList<Page>();
// implied cp.Close() from "using" statement
}
// make sure that the page list in the database is up-to-date.
foreach(Page page in pageList)
Navigation.PageUpdate(page);
return pageList;
}
And the problem disappeared. After verifying this solution I also increased the number of concurrent requests as it seems logical that having more than 10-12 concurrent requests would create the same problem I was seeing before.
Thanks everyone!
A good way to help diagnose this type of problem is to enable tracing on the client and the server and using the Service Trace View Tool. That will give you a better idea of exactly where (in what method or call) the problem is.
Unfortunately, the most important pieces of the config (the bindings and service endpoints) is missing - and so is the client config.
But the way you describe it, that 10-12 requests seem to work fine and then there's a failure, could point to an issue with concurrency/throttling on the server.
I would try to increase the number of concurrent calls and sessions just to see if that helps anything. To do so, you'll need to add a serviceThrottling section to your behavior config on the server:
<behavior name="Sdd.Services.ControlPanelBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
<serviceThrottling
maxConcurrentCalls="25" // default is 16
maxConcurrentSessions="25" // default is 10
maxConcurrentInstances="25" /> // no default
</behavior>
If that helps - you had an issue with too many sessions or concurrent calls being opened. wsHttpBinding protocol by default will use a session, so maybe you'll just need to tell it to use per-call instead.
Marc

Resources