Error 400 on WCF Rest Service Get Request - c#

I recently developed a WCF rest service where its sole purpose is to handle Get requests and return data.
I have (mostly) successfully done this however I run into an issue when I want to send more than about 200-300 characters in the request. Whenever I try this I end up getting an error 400 on the webpage. Initially I thought I was running into some sort of character limitation but after reading many webpages and other questions I'm stumped as to what is truly failing.
I have tried to change bindings like maxReceivedMessageSize, maxStringContentLength, maxBufferSize, and maxBufferPoolSize hoping one of those was the culprit but alas I was wrong. I also tried to add tracing to see if I could read any errors in the log but when I make a long request nothing gets added to the log. I'm unable to use a different browser than edge currently so I made an app that uses HttpClient to communicate with my server and I am still getting an error 400 when I make a "long" request.
An example of a request that works perfectly fine is http://IP:PORT/POINTINFO/DBNAME/{"User":"testuser","Pc":"testpc","Data":["Point01","Point02"]}
An example of a request that will get an error 400 is http://IP:PORT/POINTINFO/DBNAME/{"User":"testuser","Pc":"testpc","Data":["U1R0011AS","U1R0012AS","U1R0012BS","U1R0041AS","U1R0041BS","U1R0041CS","U1R0044AS","U1R0044BS","U1R0046AS","U1R0046BS","U1R0046CS","U1R0046DS","U1R11A-AV","U1R12A-AV","U1R12B-AV","U1R41A-AV","U1R41B-AV","U1R41C-AV","U1R44A-AV","U1R44B-AV","U1R46A-AV","U1R46B-AV","U1R46C-AV","U1R46D-AV","U1R46E-AV","U1RCSCOLDEST","U1RCSPRESS","U1RXPCNTBE"]}
As you can see, the request is long (at least to type) but it shouldn't be hitting any limitations. This is also perfectly valid JSON so that can't be why it's dying. I've also tried to put a breakpoint on my GetPointList function to see if there's something wrong with my code, but that never even gets called. This is my only exposure to WCF rest services so I'm sure there's a beginners mistake I'm making but I can't see what I'm doing wrong. Any help will be appreciated.
Here is my main:
static void Main(string[] args)
{
WebServiceHost hostWeb = new WebServiceHost(typeof(ConsoleApp1.Service));
ServiceEndpoint ep = hostWeb.AddServiceEndpoint(typeof(ConsoleApp1.IService), new WebHttpBinding(), "");
ServiceDebugBehavior stp = hostWeb.Description.Behaviors.Find<ServiceDebugBehavior>();
stp.HttpHelpPageEnabled = false;
hostWeb.Open();
Console.WriteLine("Service Host started # " + DateTime.Now.ToString());
Console.Read();
}
This is the interface I have:
[ServiceContract]
public interface IService
{
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "POINTINFO/{database}/{pointlist}")]
[return: MessageParameter(Name = "Data")]
List<PointData> GetPointList(string pointlist, string database);
}
Here is my config that is scarred with prior attempts at fixing my issue:
<!--tracing for error detection-->
<system.diagnostics>
<sources>
<source name="System.ServiceModel.MessageLogging" switchValue="Information, ActivityTracing">
<listeners>
<add name="log"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="C:\Users\Administrator\Documents\messages.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
<bindings>
<!--<wsHttpBinding>-->
<basicHttpBinding>
<binding name="basicHttp" openTimeout="00:10:00" closeTimeout="00:10:00" sendTimeout="00:10:00" receiveTimeout="01:00:00" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" maxBufferPoolSize="2147483647">
<security mode="None">
<!--<transport clientCredentialType="None" />-->
</security>
<readerQuotas maxStringContentLength="2147483647"/>
<!--<reliableSession enabled="true" />-->
</binding>
</basicHttpBinding>
<!--</wsHttpBinding>-->
<webHttpBinding>
<binding name="webHttp" openTimeout="00:10:00" closeTimeout="00:10:00" sendTimeout="00:10:00" receiveTimeout="01:00:00" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" maxBufferPoolSize="2147483647">
<security mode="None">
<!--<transport clientCredentialType="None" />-->
</security>
<readerQuotas maxStringContentLength="2147483647"/>
</binding>
</webHttpBinding>
</bindings>
<services>
<service name="ConsoleApp1.Service">
<endpoint address="rest" binding="webHttpBinding" bindingConfiguration="webHttp" contract="ConsoleApp1.IService" behaviorConfiguration="web"></endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:12345" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="mexBehaviour">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<!-- rest api-->
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<diagnostics>
<messageLogging
logEntireMessage="true"
logMalformedMessages="true"
logMessagesAtServiceLevel="true"
logMessagesAtTransportLevel="true"
maxMessagesToLog="300"
maxSizeOfMessageToLog="20000"/>
</diagnostics>
</system.serviceModel>

I figured it out, thanks to this website: https://www.codeproject.com/Questions/847265/WCF-How-to-overcome-urllength-restriction
It turns out that the default character limit of each parameter in a REST url is 260. So you have to go in the registry and change the value of
UrlSegmentMaxLength in HEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\HTTP\Parameters to a REG_DWORD of whatever value you need.

Related

Unable to access the WCF Service metadata when custom validator is introduced

I have a web service(using wsHttpBinding and SSL) developed in Visual Studio 2017. Whenever i introduce the following line, the Web Service just fails and it goes into the "faulted" state.
<authentication certificateValidationMode="Custom" customCertificateValidatorType="SampleProject.SampleService.AuthenticationCertificateValidator, SampleProject.SampleService"/>
The error message when attempting to "Add Service Reference" on the client side i recieve the following error:
There was an error downloading 'https://localhost/SampleService/service'.
The request failed with HTTP status 404: Not Found.
Metadata contains a reference that cannot be resolved:
'https://localhost/SampleService/service'.
There was no endpoint listening at https://localhost/SampleService/service
that could accept the message. This is often caused by an incorrect address
or SOAP action. See InnerException, if present, for more details.
The remote server returned an error: (404) Not Found.
If the service is defined in the current solution, try building the
solution and adding the service reference again.
Here is the code relating to the validator.
public class AuthenticationCertificateValidator : X509CertificateValidator
{
string allowedIssuerName;
public AuthenticationCertificateValidator(string allowedIssuerName)
{
if (allowedIssuerName == null)
{
throw new ArgumentNullException("allowedIssuerName");
}
this.allowedIssuerName = allowedIssuerName;
}
public override void Validate(X509Certificate2 certificate)
{
// Check that there is a certificate.
if (certificate == null)
{
throw new ArgumentNullException("certificate");
}
// Check that the certificate issuer matches the configured issuer.
if (allowedIssuerName != certificate.IssuerName.Name)
{
throw new SecurityTokenValidationException
("Certificate was not issued by a trusted issuer");
}
}
}
However the service works fine when i only have the "ChainTrust" line enabled as shown below:
<!--certificateValidationMode="Custom"
customCertificateValidatorType
="SampleProject.SampleService.AuthenticationCertificateValidator,
SampleProject.SampleService"/>-->
<authentication certificateValidationMode="ChainTrust" />
Ideally i want my service and client to use ChainTrust and also use the custom validator class if that's possible?
Therefore what am i doing wrong regarding configuration? Am i missing something from the config file?
Here is the full Service config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="SampleProject.SampleService.SampleService"
behaviorConfiguration="SampleService_Behavior">
<endpoint
address="https://localhost/SampleService/service"
binding="wsHttpBinding"
bindingConfiguration="SampleService_Binding"
contract="SampleProject.SampleService.ISampleService" />
<endpoint
address="https://localhost/SampleService/service/mex"
binding="mexHttpsBinding"
contract="IMetadataExchange" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="SampleService_Binding"
maxReceivedMessageSize="2147483647"
maxBufferPoolSize="2147483647" >
<readerQuotas
maxDepth="2147483647"
maxStringContentLength="2147483646"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647"/>
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
<message clientCredentialType="Certificate" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="SampleService_Behavior">
<!--Service metadata is needed for when you have an mex endpoint exposed-->
<serviceMetadata httpsGetEnabled="true" httpsGetUrl="https://localhost/SampleService/service/mex"/>
<serviceDebug includeExceptionDetailInFaults="True"/>
<!--The serviceCredentials behavior defines a service certificate
which is used by the service to authenticate itself to its
clients and to provide message protection. -->
<serviceCredentials>
<serviceCertificate
findValue="SampleServer"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
<clientCertificate>
<!--<authentication certificateValidationMode="ChainTrust" />-->
<authentication
certificateValidationMode="Custom"
customCertificateValidatorType
="SampleProject.SampleService.AuthenticationCertificateValidator,
SampleProject.SampleService"/>
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webBehaviour">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
if someone could assist me that would be much appreciated.

Self Hosted WCF Service throws Error Message "405 Method not allowed"

I have a Self Hosted WCF Service, which looks like this:
[ServiceContract]
public interface IService {
[OperationContract]
[WebGet]
List<Data> GetData();
//...and much more Methods
}
My App.config looks like this:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<behaviors>
<serviceBehaviors>
<behavior name="MetaInformation">
<serviceMetadata httpGetEnabled="true"
httpGetUrl="http://localhost:8500/MetaInfo"
httpsGetBinding="" />
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="EndpointBehavior">
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MetaInformation" name="Library.WcfService.ServiceModel">
<endpoint address="http://localhost:8500/Service"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBindingSettings"
contract="Library.WcfService.IService"
bindingName="BasicHttpBindingSettings"
behaviorConfiguration="EndpointBehavior"/>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBindingSettings"
closeTimeout="00:50:00"
openTimeout="00:50:00"
sendTimeout="00:50:00"
maxBufferSize="524288"
transferMode="Streamed"
maxReceivedMessageSize="2147483647"
maxBufferPoolSize="2147483647"
messageEncoding="Text">
<readerQuotas maxDepth="2147483647"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
<system.web>
<httpRuntime maxRequestLength="102400"/>
</system.web>
When I run this Server and the Client Applications on my local machine, it's working fine.
But when i try to run the Server Application on another PC, I cannot add a Service Reference at the Client because I get this:
405 Method not allowed Metadata contains a reference that can not be resolved : "http://192.168.178.54:8500/MetaInfo". It was not a
listening to http://192.168.178.54:8500/MetaInfo endpoint present who
could accept the message. This is often caused by an incorrect
address or SOAP action
I tried almost everything I found at the internet but nothing worked.
Switching to IIS or using an other Protocol should be a plan B, i want to keep it self hosted with http.
Please can somebody help me I'm desperate with this Problem.
your operation contract is decorated with [WebGet] attribute, which means you're trying to expose your service as a REST. But your service is using basicHttpBinding as means of building the communication channel which isn't supported because the content type for this binding is soap+xml. You'll need to use WebHttpBinding in this case which is the only binding that supports restful implementation of WCF Services and supports both Xml and Json data types.

WCF REST method and non-REST method

I have a WCF Service that I need one of my methods accept HTTP POST request and the other one must be non-REST. Consider the code below:
[OperationContract]
long[] Send(string body, List<string> phoneNumbers);
[OperationContract]
[WebInvoke(Method="POST", BodyStyle = WebMessageBodyStyle.WrappedRequest)]
long[] SendByPost(string body, string phoneNumbers);
But I don't know why the error below is raised:
Operation 'Send' of contract 'IService' specifies multiple request
body parameters to be serialized without any wrapper elements. At most
one body parameter can be serialized without wrapper elements. Either
remove the extra body parameters or set the BodyStyle property on the
WebGetAttribute/WebInvokeAttribute to Wrapped.
How can I solve this issue?
First of all, to send multiple parameters in a url, you can use GET method instead of POST.
[OperationContract]
[WebInvoke(Method="POST", BodyStyle = WebMessageBodyStyle.WrappedRequest)]
long[] SendByGet(string body, string phoneNumbers);
Either change it into this:
[OperationContract]
[WebGet(UriTemplate = "/body={body}?phoneNumbers={phoneNumbers}"]
long[] SendByPost(string body, string phoneNumbers);
Or if you want to use POST.
[OperationContract]
[WebInvoke(Method="POST", BodyStyle = WebMessageBodyStyle.WrappedRequest,
UriTemplate = "MyUrl", RequestFormat = WebMessageFormat.Json
, ResponseFormat = WebMessageFormat.Json)]
long[] SendByPost(Info info);
And here is your Info class:
[DataContract]
Class Info
{
[DataMember]
public string Body {get; set;}
[DataMember]
public string PhoneNumbers{get; set;}
}
You have two methods and you want to expose one of them to REST and the other to another binding, right?
For this, you need to create more than one interface for your wcf service ([ServiceContract]).
Take, for example, this Web.config:
<system.serviceModel>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment minFreeMemoryPercentageToActivateService="1" aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
<bindings>
<webHttpBinding>
<binding name="RestBinding" maxBufferSize="1048576" maxReceivedMessageSize="1048576" maxBufferPoolSize="1048576">
<readerQuotas maxDepth="2147483647" maxStringContentLength="1048576" maxArrayLength="1048576" maxBytesPerRead="1048576" maxNameTableCharCount="1048576"/>
</binding>
</webHttpBinding>
<basicHttpBinding>
<binding name="SoapBinding" maxReceivedMessageSize="20000000" messageEncoding="Text" maxBufferSize="20000000" maxBufferPoolSize="20000000" closeTimeout="00:10:00" openTimeout="00:10:00" sendTimeout="00:10:00"/>
</basicHttpBinding>
<wsHttpBinding>
<binding name="SecureHttpBinding" messageEncoding="Mtom" closeTimeout="00:10:00" openTimeout="00:10:00" sendTimeout="00:10:00" maxBufferPoolSize="20000000" maxReceivedMessageSize="20000000">
<readerQuotas maxDepth="32" maxStringContentLength="20000000" maxArrayLength="20000000"/>
<security mode="None">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</wsHttpBinding>
<customBinding>
<binding name="RawReceiveCapable">
<webMessageEncoding webContentTypeMapperType="WCFService.RawContentTypeMapper, WCFService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<httpTransport manualAddressing="true" maxReceivedMessageSize="524288000" transferMode="Buffered" /><!--transferMode="Streamed"-->
</binding>
</customBinding>
</bindings>
<services>
<service name="WCFService.Service" behaviorConfiguration="WCFService.ServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:5000"/>
</baseAddresses>
</host>
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address="SOAP" binding="basicHttpBinding" bindingConfiguration="SoapBinding" contract="WCFService.IService1" name="SOAP_XML"/>
<endpoint address="" binding="webHttpBinding" bindingConfiguration="RestBinding" contract="WCFService.IService2" behaviorConfiguration="EndpointJSONBehavior"/>
<endpoint address="MTOM" binding="wsHttpBinding" bindingConfiguration="SecureHttpBinding" contract="WCFService.IService1" name="SOAP_MTOM"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFService.ServiceBehavior">
<!-- To avoid disclosing metadata information, set the values 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 httpHelpPageEnabled="true" includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="EndpointXMLBehavior">
<webHttp defaultBodyStyle="Wrapped" defaultOutgoingResponseFormat="Xml"/>
</behavior>
<behavior name="EndpointJSONBehavior">
<webHttp defaultBodyStyle="Wrapped" defaultOutgoingResponseFormat="Json"/>
</behavior>
<behavior name="EndpointRawBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
You can see here two ServiceContracts: IService1 and IService2.
To run methods defined in IService1 you need to use soap encapsulation.
Methods exposed by IService2 can be called RESTfully and easily without soap
encapsulation.
For your SendByPost() method to be RESTful you need to put it in IService2 and put the other method in a different ServiceContract (like IService1).

WCF Concurrency?

I have a WCF service deployed to IIS 7 and the client. I thought the service is configured to handle concurrency. When I tested with two client, it took double the amount of time. I have spent hours and not yet able to figure out where I missed it. Any help/suggestions would be appreciated. Service1.svc.cs looks like this:
[ServiceBehavior( ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall)]
[CallbackBehavior(UseSynchronizationContext=false)]
public class Service1 : IService1
{
public byte[] DownloadFile()
{
byte[] byt = File.ReadAllBytes(#"C:\Temp\TestFile.pdf");
System.Threading.Thread.Sleep(1000);
return byt;
}
}
Configuration:
<system.net>
<connectionManagement>
<add address="*" maxconnection="100"/>
</connectionManagement>
</system.net>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<processModel autoConfig="false" maxWorkerThreads="1400" maxIoThreads="1400" minWorkerThreads="2"/>
<httpRuntime minFreeThreads="1000" minLocalRequestFreeThreads="1000"/>
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="Service1Binding" maxBufferSize="2147483647" maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647" transferMode="Streamed">
<readerQuotas maxDepth="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="DocService.Service1">
<endpoint address="http://localhost/DocService/Service1.svc" binding="basicHttpBinding"
bindingConfiguration="" name="Service1Binding" bindingName="Service1Binding"
contract="DocService.IService1" />
<endpoint address="http://localhost/DocService/mex" binding="mexHttpBinding"
name="mexpoint" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<serviceThrottling maxConcurrentCalls="100" maxConcurrentInstances="100" maxConcurrentSessions="100"/>
</behavior>
</serviceBehaviors>
</behaviors>
The requests are taking much longer than 1s sleep time and the read time of, say, 10mb file. They should complete in maybe 1.1-2s There is something fishy here.
Comment out the read and return a new byte[0]. Does it take 1.0s now? Do you have concurrency now?
Edit: What client are you using?
Edit 2: Responding to your comment, the file transfer is not limiting concurrency in some way. WCF does not care what you do inside your service method. It knows nothing about files. The problem is that your disk is too slow and that serializing 36mb is probably slow too! You server is just too slow! You can find out, if the disk or the serializing is the problem by replacing the IO with new byte[1024*1024*36].

The server has rejected the client credentials, WCF as Windows Service

I am able to connect to my WCF service with the Win-form application, however i am not able to do so with my windows service. Whenever i fire open() to the proxy it throws the following error
The server has rejected the client credentials
Inner Exception: System.Security.Authentication.InvalidCredentialException: The server
has rejected the client credentials.
---> System.ComponentModel.Win32Exception: The logon attempt failed
--- End of inner exception stack trace ---
at System.Net.Security.NegoState.ProcessAuthentication(LazyAsyncResult
lazyResult)
at System.Net.Security.NegotiateStream.AuthenticateAsClient(NetworkCredential
credential, ChannelBinding binding, String targetName, ProtectionLevel
requiredProtectionLevel, TokenImpersonationLevel
allowedImpersonationLevel)
at System.Net.Security.NegotiateStream.AuthenticateAsClient(NetworkCredential
credential, String targetName, ProtectionLevel
requiredProtectionLevel, TokenImpersonationLevel
allowedImpersonationLevel)
at System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeInitiator.OnInitiateUpgrade(Stream
stream, SecurityMessageProperty& remoteSecurity)
Tried searching for the solution, but none fitting my requirements, hence posted.
Please help...
Update 1:
#A.R., Tried using
client.ClientCredentials.Windows.AllowedImpersonationLevel =
System.Security.Principal.TokenImpersonationLevel.Impersonation;
but to no avail.
Update 2:
WCF service Configuration
<system.serviceModel>
<diagnostics performanceCounters="All" />
<bindings>
<netTcpBinding>
<binding name="myBindingForLargeData" maxReceivedMessageSize="5242880" maxConnections="10">
<readerQuotas maxDepth="64" maxStringContentLength="5242880" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
</binding>
</netTcpBinding>
</bindings>
<services>
<service behaviorConfiguration="WCFService.ServiceBehavior"
name="WCFService.CollectorService">
<endpoint address="" binding="netTcpBinding" bindingConfiguration="myBindingForLargeData"
name="netTcpEndPoint" contract="WCFService.ICollectorService" />
<endpoint address="mex" binding="mexTcpBinding" bindingConfiguration=""
name="mexTcpEndPoint" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8010/WCFService.CollectorService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFService.ServiceBehavior">
<serviceMetadata httpGetEnabled="False"/>
<serviceDebug includeExceptionDetailInFaults="True" />
<serviceThrottling
maxConcurrentCalls="32"
maxConcurrentSessions="32"
maxConcurrentInstances="32"
/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Thanks for all your help. i got the answer after few days of some research and trial n error method :) well i know i am late to post the answer, but i think its better late than never.
So Here's the solution
i had to make some changes in my configuration files (both client & server)
On the client side i added <security> tag as shown below
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="netTcpEndPoint" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="5242880" maxBufferSize="5242880" maxConnections="15" maxReceivedMessageSize="5242880">
<readerQuotas maxDepth="32" maxStringContentLength="5242880" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://xx.xx.xx.xx:8010/WCFService.CollectorService/" binding="netTcpBinding" bindingConfiguration="netTcpEndPoint" contract="CloudAdapter.CloudCollectorService.ICollectorService" name="netTcpEndPoint">
</endpoint>
</client>
</system.serviceModel>
and also added the same tag on the server side (WCF service configuration), as shown below
<bindings>
<netTcpBinding>
<binding name="myBindingForLargeData" maxReceivedMessageSize="5242880" maxConnections="10">
<readerQuotas maxDepth="64" maxStringContentLength="5242880" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
Hope this help a person in need :)
So the KEY is to make the <security> tag same over the client and the server configuration files.
Basically what is happening is that your calling service doesn't have the appropriate credentials, like you would have when calling from WinForms. What you need is some impersonation. It takes a bit of setting up, and is kind of annoying, but it will work.
Luckily MSDN has a nice little walkthrough.
http://msdn.microsoft.com/en-us/library/ms731090.aspx
There is some more general information on the topic here:
http://msdn.microsoft.com/en-us/library/ms730088.aspx
UPDATE:
Setting impersonation flags is not enough. You have to actually impersonate a credential to make it work. For example:
// Let's assume that this code is run inside of the calling service.
var winIdentity = ServiceSecurityContext.Current.WindowsIdentity;
using (var impContext = winIdentity.Impersonate())
{
// So this would be the service call that is failing otherwise.
return MyService.MyServiceCall();
}
Check out my answer on this post The server has rejected the client credentials.
Note the security node.
<bindings>
<netTcpBinding>
<binding name="customTcpBinding" maxReceivedMessageSize="20480000" transferMode="Streamed" >
<security mode="None"></security>
</binding>
</netTcpBinding>
</bindings>
What is the authentication mode you are using on your WCF Service? Seems like the winform app is running and providing the correct credentials while your windows service is not running with the specified privileges or the credentials being passed are not valid. Try to inspect your request using Fiddler when made from you winforms vs Windwos service and see the difference.
For me it helped to set on both sides (client + server) the security mode to None:
NetTcpBinding binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.None;
(Same answer as from spinner_den_g but in C# - no need to edit the app.config)

Categories