WCF, REST, Concurrency, Sessions - asp.net

We have a WCF REST service that sends data from the server to the web client. These are the web.config settings
<binding name="Binding_Service_Name"
closeTimeout="00:01:30" openTimeout="00:01:30" receiveTimeout="00:01:30"
sendTimeout="00:01:30" allowCookies="false" bypassProxyOnLocal="false"
hostNameComparisonMode="StrongWildcard" maxBufferSize="1048576"
maxBufferPoolSize="524288" maxReceivedMessageSize="1048576" messageEncoding="Text"
textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
<client>
<endpoint address="https://FQDN//RESTService.svc"
binding="basicHttpBinding" bindingConfiguration="Binding_Service_Name"
contract="Contract"
name="BindingName" />
</client>
<services>
<service behaviorConfiguration="RESTServiceBehavior"
name="Name">
<endpoint address="" behaviorConfiguration="webBehavior" binding="customBinding"
bindingConfiguration="jsonpBinding" contract="contract">
</endpoint>
<!--<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> jsonpBinding-->
</service>
<serviceBehaviors>
<behavior name="Bco.Sitecore.UI.RESTApi.RESTServiceBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<!--HTTPS-->
<!--<serviceMetadata httpsGetEnabled="true"/>-->
<!--HTTP-->
<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="true"/>
<serviceThrottling maxConcurrentCalls="1000" maxConcurrentInstances="1000" maxConcurrentSessions="1000" />
</behavior>
</serviceBehaviors>
Compatibility mode in web.config - aspnetCompatibilitymode = true
The REST Service has read/writes into the HttpSession.
When there are concurrent calls from the website, asp.net serializes these calls. What do I do to have these as concurrent calls? Read/writes to the session for this REST service is something we carried over from our older code and it's impossible to get around the Session Read/Writes
Would appreciate a solution to this/direction to solve this problem.Thanks!

When an application uses session state, calls to the application are always serialized.

Related

WCF Services - Configuration web service binding exception

All,
Env:
Asp.net 4.0
IIS 7 (or greater)
WCF service consumed by SL component
Authentication:
Anonymous/Forms
When I attempt to browse to my WCF web service (using browser) I get the following exception on my web service, I need to get rid of this error:
The authentication schemes configured on the host ('IntegratedWindowsAuthentication') do not allow those configured on the binding 'BasicHttpBinding' ('Anonymous'). Please ensure that the SecurityMode is set to Transport or TransportCredentialOnly. Additionally, this may be resolved by changing the authentication schemes for this application through the IIS management tool, through the ServiceHost.Authentication.AuthenticationSchemes property, in the application configuration file at the element, by updating the ClientCredentialType property on the binding, or by adjusting the AuthenticationScheme property on the HttpTransportBindingElement.
I looked at ALL related posts and none of them help me.
I am not using any authentication or user/pwd transmission for my service.
The service I need to get working is consumed by Silverlight component and has this name in web.config file:
Htmls.WebStore.Services.WebStoreServices (ignore the other service).
Here's my web.config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="WebStoreServices_InsecureTransport" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="4096" />
<security mode="None" />
</binding>
<binding name="basicHttpBinding" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="SitefinityWebApp.Sitefinity.Services.Content.EventsAspNetAjaxBehavior">
<enableWebScript />
</behavior>
<behavior name="EndpBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<behavior name="Telerik.Sitefinity.Web.Services.LocalizationBehavior" />
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Htmls.WebStore.Services.WebStoreServices">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="WebStoreServices_InsecureTransport" contract="Htmls.WebStore.Services.IWebStoreServices" />
</service>
<service name="SitefinityWebApp.Sitefinity.Services.Content.Events">
<endpoint address="" behaviorConfiguration="SitefinityWebApp.Sitefinity.Services.Content.EventsAspNetAjaxBehavior" binding="webHttpBinding" contract="SitefinityWebApp.Sitefinity.Services.Content.Events" />
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
The exception was caused by having incorrect permission on the folder where the xxxxx.svc file was. The folder was locked down using security permissions.

Webservices wcfstorm client

I am using WCFstrom lite to find the problem with the webservice connection. It comes up with the error
"
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.RSS Feed
"
But as it is lite version I cannot find any configuration on the wcfstrom.
My web config looks like.
<system.serviceModel>
<extensions>
<behaviorExtensions>
<!-- Declare that we have an extension called WSDL Extras-->
<add name="wsdlExtensions" type="WCFExtras.Wsdl.WsdlExtensionsConfig, WCFExtras, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
<services>
<service name="xxxxxxxxxxxxxxxxxx" behaviourConfiguration="xxxxxxxxxxxxxx">
<!-- Service Endpoints -->
<endpoint address="" binding="wsHttpBinding" behaviorConfiguration="WcfExtras.EndpointBehavior" contract="xxxxxxxxxxxx">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" behaviorConfiguration="WcfExtras.EndpointBehavior" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="WcfExtras.EndpointBehavior">
<wsdlExtensions location="http://localhost:3893/xxxxxxxx.svc" singleFile="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="xxxxxxx.xxxxxxxx">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above 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>
Where do I add the following code:
<bindings>
<basicHttpBinding>
<binding name="LoggedInUsersSoap" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
I found the answer, just select the service in the wcf Client and edit on end points then you can edit the maxReceivedmessages property
In WCFStorm (at least in the current 1.3.0 version), you can also increase the MaxReceivedMessage by loading a client app.config file which has a the right (large) value.
http://www.wcfstorm.com/wcf/loading-client-appconfig-files.aspx

Endpoint not found When Hosting in ASP.NET

I get "Endpoint not found" when attempting to access my service via the browser at
http://localhost:10093/Services/Service1.svc
I get "Error: Cannot obtain Metadata from http://localhost:10093/Services/Service1.svc" when attempting to access the same address from the wcftestclient.
If I place a breakpoint in the service implementation it is hit, so I assume the svc file is setup correctly:
<%# ServiceHost Language="C#" Debug="true"
Service="MyApp.Core.Service.Service.MyAppService,MyApp.Core.Service"
Factory="CommonServiceFactory.WebServiceHostFactory,CommonServiceFactory" %>
Here is my config:
<system.serviceModel>
<services>
<service name="MyApp.Core.Service.Service.MyAppService,MyApp.Core.Service"
behaviorConfiguration="MainServiceBehavior">
<endpoint name="newEndpoing"
binding="basicHttpBinding" bindingConfiguration=""
contract="MyApp.Core.Service.IMyAppService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MainServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
So you have a *.svc file to host your service. Can you right-click in Visual Studio on that file and say "Show in Browser" ? Do you get anything there, or does it throw an error right away??
Next: your service endpoint has no address="" attribute, which I believe is mandatory - try adding that (even if you don't specify an address in it).
If you're hosting in IIS, your service address is defined by the virtual directory where your SVC file is present, and the SVC file itself - you might not be able to define a specific port or anything (IIS will handle that).
So try to connect to
http://localhost/Services/Service1.svc
Does that work by any chance??
Update: reading your post again more closely, you're specifying a special factory for the service - WebServiceHostFactory. Is this the default WebServiceHostFactory provided by .NET, or is that something you built yourself??
The point is: the .NET WebServiceHostFactory will use the webHttpBinding for RESTful WCF services - that won't work with an endpoint specifying basicHttpBinding, nor will the REST service have any metadata....
Update #2: try to use just the service's fully qualified class name, but without the assembly specification, in both your SVC file, and the config file.
So change this:
Service="MyApp.Core.Service.Service.MyAppService,MyApp.Core.Service"
to this:
Service="MyApp.Core.Service.Service.MyAppService"
SVC file:
<%# ServiceHost Language="C#" Debug="true"
Service="MyApp.Core.Service.Service.MyAppService" %>
Config file:
<services>
<service name="MyApp.Core.Service.Service.MyAppService"
behaviorConfiguration="MainServiceBehavior">
<endpoint name="newEndpoing"
binding="basicHttpBinding" bindingConfiguration=""
contract="MyApp.Core.Service.IMyAppService" />
</service>
</services>
On your Solution Explorer, open your .svc by using "view markup", make sure you have something like:
... ServiceHost Language="C#" Debug="true"
Service="Yourservice.yourservice" CodeBehind="yourservice.svc.cs" %>
Where Yourservice is your namespace and yourservice is name of your .svc created.
I had the same results (Endpoint not found) when I put this in the browser window
http://c143253-w7a:2221/ws/myService.svc
Then when I put the whole url to the method, it ran fine. Like this
http://c143253-w7a:2221/ws/myService.svc/HelloWorld?theInput=pds
In my .svc file I am using this
Factory="System.ServiceModel.Activation.WebServiceHostFactory"
I think that the Factory doesn't spin up the endpoint until it is needed. That is why we get Endpoint not found in the browser(?).
Here is what the method signature looks like in the interface code.
using System.ServiceModel.Web;
[WebGet(UriTemplate = "HelloWorld?theInput={theInput}")]
[OperationContract]
string HelloWorld(string theInput);
I put nothing in the webconfig. There is some stuff in there, but I think that came in w the VS, Add WCF Service template. It looks like this:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
my web.config for my WCF service is very similar to yours. You definitely have to add the MEX endpoint like Shiraz said. I've added a behavior configuration that lets any message size go through the WCF. Try to use these settings if it can help you (don't forget to change the contract settings):
<system.serviceModel>
<diagnostics>
<messageLogging logMalformedMessages="true" logMessagesAtTransportLevel="true" />
</diagnostics>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="524288000" maxBufferPoolSize="524288000" maxReceivedMessageSize="524288000" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxDepth="500000000" maxStringContentLength="500000000" maxArrayLength="500000000" maxBytesPerRead="500000000" maxNameTableCharCount="500000000" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None" realm="">
<extendedProtectionPolicy policyEnforcement="Never"/>
</transport>
<message clientCredentialType="UserName" algorithmSuite="Default"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<dataContractSerializer maxItemsInObjectGraph="6553600" />
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="serviceBehavior" name="RC.Svc.Web.TPF.Service">
<endpoint
address=""
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IService"
contract="RC.Svc.Web.TPF.IService" />
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
</service>
</services>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<client />
Your error message is "Cannot obtain Metadata" and you do not have a MetadataExchange endpoint defined. You do have httpGetEnabled="True", which is also required.
Try defining a MEX endpoint, for details how to see: http://bloggingabout.net/blogs/dennis/archive/2006/11/09/WCF-Part-4-3A00-Make-your-service-visible-through-metadata.aspx

Why does my WCF web service end the response when the output data is fairly large?

I've set up a WCF web service to be called from my web site. It's working great, but if I request a large amount of data (not sure on the size, but it's easily 3-4 times larger than the "standard" data I'm returning), Cassini (Visual Studio Web Server) just closes the response without sending anything-- no error or anything. Nothing in event log. Just nada.
I'm a newbie to WCF, but I know there must be some configuration option I'm missing here (like a message/response max size/limit) that solves my problem. Here's what my web.config section looks like:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<behaviors>
<endpointBehaviors>
<behavior name="securetmhAspNetAjaxBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="tmhsecureBehavior">
<serviceMetadata httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="securetmh">
<endpoint address="" behaviorConfiguration="securetmhAspNetAjaxBehavior" binding="webHttpBinding" contract="securetmh" />
</service>
</services>
</system.serviceModel>
Any help would be appreciated.
For security reasons, WCF limits the data returned by a service call to 64 K by default.
You can obviously change that - there's a gazillion of entries to tweak. See this sample config here:
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="customWebHttp"
maxBufferPoolSize="256000"
maxReceivedMessageSize="256000"
maxBufferSize="256000">
<readerQuotas
maxArrayLength="256000"
maxStringContentLength="256000"/>
</binding>
</webHttpBinding>
</bindings>
<services>
<service name="YourService">
<endpoint name="test"
address="....."
binding="webHttpBinding"
bindingConfiguration="customWebHttp"
contract="IYourService" />
</service>
</services>
</system.serviceModel>
You need to define a custom binding configuration based on the webHttpBinding, and you can tweak all those various settings - I set them all to 256K (instead of 64K).
Hope this helps!

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