WCF Initiation is taking too much time - wcf

WCF service is taking around 5-6 seconds for first request there after all call execute very fast.
below is the client side configuration for my WCF service.
Using IIS hosting.
WSHttpBinding binding = new WSHttpBinding();
binding.SendTimeout = TimeSpan.FromMinutes(1);
binding.OpenTimeout = TimeSpan.FromMinutes(1);
binding.CloseTimeout = TimeSpan.FromMinutes(1);
binding.ReceiveTimeout = TimeSpan.FromMinutes(1);
binding.AllowCookies = false;
binding.BypassProxyOnLocal = false;
binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
binding.MessageEncoding = WSMessageEncoding.Mtom;
binding.TextEncoding = System.Text.Encoding.UTF8;
binding.UseDefaultWebProxy = true;
binding.Name = "BasicHttpBinding_ILearningService";
binding.Security.Mode = SecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
binding.Security.Transport.Realm = "";
Server side configuration
<services>
<service behaviorConfiguration="LearningServiceServiceBehavior" name="LearningService">
<host>
<baseAddresses>
<add baseAddress="https://xxxxx/LearningService.svc" />
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="TransportSecurity" contract="ILearningSuiteService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="TransportSecurity" messageEncoding="Mtom" sendTimeout="00:1:00" openTimeout="00:2:00">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="LearningServiceServiceBehavior">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" httpGetUrl="http://xxxxxxx/Metadata" httpsGetUrl="https://xxxxxxxx/Metadata" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>

The other issue you may be see is that as you are using transport security you are doing certificate validation on the client each time you create a new proxy. Is it possible the certificate validation is expensive, say, due to the revocation list for the certificate not being available in a timely fashion?
Try turning off security and see if that changes the behavior

Although not completely definite it looks like you are IIS hosting (I say not definite because baseAddresses are not specified by you in IIS hosting, rather the actual .svc file is the base address for the service)
Assuming you are IIS hosting are you seeing the spin up time for the worker process? Depending on which version of Windows you are using you could use Windows Server AppFabric to autostart the service before the first request

The first time you make the call, the client sets up the connection to the server and the server does necessary authentication, this can take some time.
And based on what I found in my project, the WCF serialization can take much time in the first time if your contract is huge. After that, the serialization can be much quicker.

Related

Problem increasing WCF service endpoint size configuration

I have an asp.net project that was hosting a WCF service (via the wcf file exposure technique for IIS) that was put together around 10 years ago. There is an operation on the service that retrieves content that is greater than the default 75K limit. The service configuration (in web.config) property on the binding was adjusted to be larger than the default and was working ok. The ASP.NET project was upgraded in VS2017/2019 - and (I assume) the project was adjusted (somehow). The service operation described above no longer works. I did a lot of investigation and all solutions were handled (which makes sense as the original version of the project was working). I even went through the process of building a new web.config with minimal configuration and still did not work. I also adjusted the service to include the Configure operation that could be used to configure the endpoint configuration in code. It also did not work. For this I have the following:
public static void Configure(ServiceConfiguration config)
{
BasicHttpBinding binding = new BasicHttpBinding();
binding.MaxReceivedMessageSize = int.MaxValue;
binding.MaxBufferSize = int.MaxValue;
binding.MaxBufferPoolSize = int.MaxValue;
binding.BypassProxyOnLocal = true;
binding.ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
{
MaxStringContentLength = int.MaxValue,
MaxDepth = int.MaxValue,
MaxArrayLength = int.MaxValue,
MaxBytesPerRead = int.MaxValue,
MaxNameTableCharCount = int.MaxValue
};
var endpoint = new ServiceEndpoint(
ContractDescription.GetContract(
typeof(IAuthenticateServicePack)),binding,new
EndpointAddress("http://localhost:49437/WCFSevices/AuthenticateServicePack.svc"));
//MyEndpointBehavior Behavior = new MyEndpointBehavior();
//endpoint.Behaviors.Add(Behavior);
config.AddServiceEndpoint(endpoint);
}
The web.config definitions is the following
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true"
/>
<behaviors>
<serviceBehaviors>
<behavior name="ServicePack.ServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceThrottling maxConcurrentCalls="500" maxConcurrentSessions="500"
/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<clear />
<binding name="myBindingForBigArrays" maxReceivedMessageSize="2147483647"
transferMode="Buffered">
<readerQuotas
maxDepth="32"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="4096"
maxNameTableCharCount="10000"
/>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="Lapp.WebAdmin.Mvc.WCFSevices.AuthenticateServicePack"
behaviorConfiguration="ServicePack.ServiceBehavior">
<endpoint address="" binding="basicHttpBinding"
bindingConfiguration="myBindingForBigArrays"
contract="Lapp.WebAdmin.Mvc.WCFSevices.IAuthenticateServicePack" />
<host>
<timeouts closeTimeout="00:01:00" />
</host>
</service>
</services>
</system.serviceModel>
For some reason - the updated asp.net project does not seem to be handling the WCF service endpoint configuration. Has anyone run into this issue?
Note: I can test the older version of the service and is working properly -- and reviewing the old config with the new -- cannot identify any modification that would appear to be causing the new not to use the size limit settings.

WCF Discovery returns machine names in metadata (cannot be resolved)

So I have a WCF service hosted in IIS8 (Windows Server 2012). Here's the relevant part of the configuration file:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<services>
<service name="MovieCorner.DAL.Service.MovieCornerDalService">
<host>
<baseAddresses>
<add baseAddress="http://192.168.221.101/MovieCorner/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<endpoint address="" binding="basicHttpBinding"
contract="MovieCorner.Commons.Services.IMovieCornerDalService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<!-- Metadata Endpoints -->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<endpoint kind="udpDiscoveryEndpoint" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" />
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
<serviceDebug includeExceptionDetailInFaults="True" />
<serviceDiscovery />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
A simple service with a simple binding, and with a discovery endpoint. The service is up and running, everything works fine. Almost...
Here's the code I'm using on the client side (it's just a "unit" test):
var client = new DiscoveryClient(new UdpDiscoveryEndpoint());
var response = client.Find(new FindCriteria(typeof(IMovieCornerDalService)));
Assert.IsNotNull(response);
Assert.IsNotNull(response.Endpoints);
Assert.IsTrue(response.Endpoints.Count > 0);
foreach (var endpoint in response.Endpoints)
{
Console.WriteLine("Address: {0}; Contract: {1}", endpoint.Address, endpoint.ContractTypeNames[0]);
}
The code successfully finds the only running service. The output is the following:
Address: http://ws12-iis8/MovieCorner/MovieCornerDalService.svc;
Contract: http://tempuri.org/:IMovieCornerDalService
The address is returned with the machine name that hosts the service. After the discovery I want to use the service like this:
var endpoint = response.Endpoints[0];
var clientProxy = ChannelFactory<IMovieCornerDalService>.CreateChannel(new BasicHttpBinding(), endpoint.Address);
var user = clientProxy.RegisterUser("1234"); // problem
The actual method call throws an exception, and the inner exception is the following: System.Net.WebException: The remote name could not be resolved: 'ws12-iis8'
The "unit" test runs in my PC, the service is hosted in a VM. I can reach the service at the http://192.168.221.101/MovieCorner/MovieCornerDalService.svc address. But not with the machine name address.
What am I missing? What are my options? How can I retrieve the actual (private) IP of the service hosting VM? I searched for different metadata options, but I'm not a pro in the web world, so I don't know what I'm looking for.
If you need more information, let me know. Thanks for your time!

Pass token from MVC to WCF service

I have a MVC app talking to ACS to get token for authentication. It's a claim based application. This works perfectly fine.
I am trying to call WCF service from MVC once authenticated with same taken so that i can use same claims for authorization.
MVC code is as below
var context = (BootstrapContext)identity.BootstrapContext;
var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.Message);
binding.Security.Message.IssuedKeyType = SecurityKeyType.SymmetricKey;
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.IssuerBinding = new WS2007FederationHttpBinding();
EndpointAddress acsEndPoint =
new EndpointAddress("https://ACS namespace/v2/wsfederation");
binding.Security.Message.IssuerAddress = acsEndPoint;
binding.Security.Message.IssuedTokenType = "urn:ietf:params:oauth:token-type:jwt";
ChannelFactory<IService1> factory =
new ChannelFactory<IService1>(binding, new EndpointAddress("https://localhost/TestWCF/Service1.svc"));
factory.Credentials.SupportInteractive = false;
factory.Credentials.UseIdentityConfiguration = true;
var proxy = factory.CreateChannelWithIssuedToken(context.SecurityToken);
proxy.GetData(1);
WCF web config is as below
<system.serviceModel>
<services>
<service name="TestWCF.Service1">
<endpoint address="" behaviorConfiguration="webHttpAutoFormat" binding="ws2007FederationHttpBinding" bindingConfiguration="secureHttpBinding" contract="TestWCF.IService1"/>
<endpoint address="soap" binding="basicHttpBinding" contract="TestWCF.IService1" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<bindings>
<ws2007FederationHttpBinding>
<binding name="secureHttpBinding">
<security mode="None">
<message establishSecurityContext="false" issuedKeyType="SymmetricKey" issuedTokenType="urn:ietf:params:oauth:token- type:jwt">
<issuerMetadata address="https://ACS namespace/v2/wstrust/mex"></issuerMetadata>
</message>
</security>
</binding>
</ws2007FederationHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<serviceCredentials useIdentityConfiguration="true"></serviceCredentials>
<serviceAuthorization principalPermissionMode="Always" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webHttpAutoFormat">
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
<serviceActivations>
<add relativeAddress="Service1.svc" service="TestWCF.Service1" />
</serviceActivations>
</serviceHostingEnvironment>
</system.serviceModel>
Please note my WCF service is not HTTPS also I am using JWT token from ACS. No certificates.
I get below error
The provided URI scheme 'https' is invalid; expected 'http'.
Parameter name: via
Can anyone help?
You are currently initializing your binding with
var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.Message)
Try changing to
var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential)
From (MSDN - WS Transport With Message Credential):
By default, the wsHttpBinding binding provides HTTP communication.
When configured for transport security, the binding supports HTTPS
communication. HTTPS provides confidentiality and integrity protection
for the messages that are transmitted over the wire. However the set
of authentication mechanisms that can be used to authenticate the
client to the service is limited to what the HTTPS transport supports.
Windows Communication Foundation (WCF) offers a
TransportWithMessageCredential security mode that is designed to
overcome this limitation. When this security mode is configured, the
transport security is used to provide confidentiality and integrity
for the transmitted messages and to perform the service
authentication. However, the client authentication is performed by
putting the client credential directly in the message. This allows you
to use any credential type that is supported by the message security
mode for the client authentication while keeping the performance
benefit of transport security mode.
Your web config should have this instead for <ws2007FederationHttpBinding>:
<ws2007FederationHttpBinding>
<binding name="secureHttpBinding">
<security mode="TransportWithMessageCredential">
<message establishSecurityContext="false" issuedKeyType="SymmetricKey" issuedTokenType="urn:ietf:params:oauth:token- type:jwt">
<issuerMetadata address="https://ACS namespace/v2/wstrust/mex"></issuerMetadata>
</message>
</security>
</binding>
</ws2007FederationHttpBinding>
See also the following answer for some additional info as well: StackOverflow - The provided URI scheme 'https' is invalid; expected 'http'. Parameter name: via

ClientBaseAddress doesn't seem accessible

I am using wsDualHttpBinding, server is self hosted.
I am having a problem that looks to me that my ClientBaseAddress of my client is not accessible. I am at a loss of how to fix this problem.
Here is my service config:
<system.serviceModel>
<services>
<service name="GuiEndpoint.GuiService">
<endpoint address=""
binding="wsDualHttpBinding"
bindingConfiguration="GuiEndpoint"
name="dualHttpBinding"
contract="Common.IGuiService">
<!--<identity>
<dns value="localhost"/>
</identity>-->
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" name="mex" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://192.168.1.199:8733/Design_Time_Addresses/GuiEndpoint/IGuiService/"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsDualHttpBinding>
<binding name="GuiEndpoint">
<security mode="None">
<message clientCredentialType="None"/>
</security>
</binding>
</wsDualHttpBinding>
</bindings>
<diagnostics>
<messageLogging logEntireMessage="true"
maxMessagesToLog="300"
logMessagesAtServiceLevel="true"
logMalformedMessages="true"
logMessagesAtTransportLevel="true" />
</diagnostics>
On my client I am connecting programmaticly with this code:
WSDualHttpBinding binding = new WSDualHttpBinding();
binding.Security.Mode = WSDualHttpSecurityMode.None;
binding.Security.Message.ClientCredentialType = MessageCredentialType.None;
binding.ClientBaseAddress = new Uri("192.168.1.189:8080/TempUri");
EndpointAddress endpoint = new EndpointAddress(Helper.CreateUri(client.Connection.ServerAddress));
context = new InstanceContext(this);
serviceClient = new GuiServiceClient(context, binding, endpoint);
serviceClient.InnerDuplexChannel.Faulted += InnerChannelOnFaulted;
try
{
if (serviceClient.Subscribe())
{
startKeepAliveTimer();
}
}
catch (EndpointNotFoundException)
{
this.Error("Couldn't Connect!");
}
Now, using Fidler I can see the messages going back and forth.
Server:
Client:
As you can see, the client can talk to the server, but the server can't seem to talk to the client.
I have also registered the namespace on the client:
The client port is accessible also:
Starting Nmap 6.25 ( http://nmap.org ) at 2013-01-03 14:05 Mountain Standard Time
Nmap scan report for 192.168.1.189
Host is up (0.10s latency).
PORT STATE SERVICE
8080/tcp open http-proxy
MAC Address: xx:0B:A9:57:xx:xx (Intel Corporate)
Nmap done: 1 IP address (1 host up) scanned in 13.42 seconds
Any kind of help here would be great!
What Microsoft have failed to put in any documentation is that:
The IP ADDRESS you specify in the ClientBaseAddress MUST BE resolvable to a HOST NAME. In other words, if the server can't ping the client by its HOST NAME, then you will never be able to establish a connection.
As you have discovered it just doesn't work!
Try replacing 192.168.1.189 with the host name of the client PC, like this:
http://ClientHostName:8080/TempURI
Also as a hint, if you don't want to have to register any ports, just use the address
http://MyClientHostName/Temporary_Listen_Addresses/TempUri
because you are allowed to register any url starting with
http://+80/Temporary_Listen_Addresses/

Silverlight WCF call is too large for sharepoint wcf

I have a silverlight 4 project calling a WCF service deployed on sharepoint 2010.
There are two methods a get and and a save,
teh get works fine but the save returns a generic message "Not Found"
The save is passing a large object with 2 lists. If I reduce the size of the list it all works.
So I figure I have to increase the maxReceivedMessageSize, this is easily done on the silverlight side just edit ServiceReferences.ClientConfig.
however I dont know where to do it on teh server side
Where is the binding information on the shaprepoint webserver.
I've had a look in \inetpub\wwwroot\wss\VirtualDirectories\80\web.config and it isn't there.
is there an easy way to get the binding info from teh URL?
I tried to setup some bindings for it but I just get errors
my attempt is
<bindings>
<basicHttpBinding>
<binding name="MyDemoBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="MyDemoBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MyDemoBehavior" name="BEIM.Webservices.Service">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="MyDemoBinding" contract="BEIM.Webservices.IService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<host>
<baseAddresses>
<add baseAddress=”http://localhost/_vti_bin/BEIM.Webservices” />
</baseAddresses>
</host>
</service>
</services>
got the answer from here
private static void ConfigureWebService()
{
SPWebService contentService = SPWebService.ContentService;
contentService.ClientRequestServiceSettings.MaxReceivedMessageSize = -1;
SPWcfServiceSettings wcfServiceSettings = new SPWcfServiceSettings();
wcfServiceSettings.ReaderQuotasMaxStringContentLength = 10485760;
wcfServiceSettings.ReaderQuotasMaxArrayLength = 2097152;
wcfServiceSettings.ReaderQuotasMaxBytesPerRead = 10485760;
wcfServiceSettings.MaxReceivedMessageSize = 10485760;
// must be in lower case
contentService.WcfServiceSettings["service.svc"] = wcfServiceSettings;
contentService.Update();
}
I just ran it from a console app