Failed to Execute URL when calling a WCF service with Windows authentication - wcf

I am having a problem with a WCF service using Windows authentication on one of the servers I am deploying it to (it's a Windows Server 2008 R2 machine), while it works flawlessly on all other machines I have access to (Windows 7, Windows Server 2008 and Windows Server 2008 R2). I managed to reproduce the issue with a really simple sample application which more or less completely excludes my code as the cause of the problem.
The minimum application I can reproduce the issue with is a minor modification of the WCF service project template:
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
}
[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}\nUsername: {1}",
value,
ServiceSecurityContext.Current == null ?
"<null>" :
ServiceSecurityContext.Current.PrimaryIdentity.Name);
}
}
Basically I enabled ASP.NET compatibility (I need it because the actual code uses an HttpHandler for authentication) and the username of the authenticated user is returned.
The contents of web.config are as follows:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<authentication mode="Windows"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="HttpWindowsBinding" maxReceivedMessageSize="2147483647">
<readerQuotas maxBytesPerRead="2147483647" maxArrayLength="2147483647" maxStringContentLength="2147483647" maxNameTableCharCount="2147483647" maxDepth="2147483647"/>
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
<services>
<service name="TestService.Service1" behaviorConfiguration="ServiceBehavior">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="HttpWindowsBinding"
contract="TestService.IService1" />
<endpoint address="problem"
binding="basicHttpBinding"
bindingConfiguration="HttpWindowsBinding"
contract="TestService.IService1" />
</service>
</services>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Notice the two endpoints: one with the default address, the other one with a relative address. Calling the first one succeeds even on the problematic server, while the call to the second one fails with following error:
Exception type: HttpException
Exception message: Failed to Execute URL.
at System.Web.Hosting.ISAPIWorkerRequestInProcForIIS6.BeginExecuteUrl(String url, String method, String childHeaders, Boolean sendHeaders, Boolean addUserIndo, IntPtr token, String name, String authType, Byte[] entity, AsyncCallback cb, Object state)
at System.Web.HttpResponse.BeginExecuteUrlForEntireResponse(String pathOverride, NameValueCollection requestHeaders, AsyncCallback cb, Object state)
at System.Web.DefaultHttpHandler.BeginProcessRequest(HttpContext context, AsyncCallback callback, Object state)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
The call only fails when the classic pipeline is used (I need it because of the HttpHandler, but the issue can be reproduced even without it). With integrated pipeline the problem is gone. Also if I disable Windows authentication, the problem is gone as well:
<binding name="HttpBinding" maxReceivedMessageSize="2147483647">
<readerQuotas maxBytesPerRead="2147483647" maxArrayLength="2147483647" maxStringContentLength="2147483647" maxNameTableCharCount="2147483647" maxDepth="2147483647"/>
<security mode="None">
<transport clientCredentialType="None" />
</security>
</binding>
I have noticed another detail with an HttpHandler registered. The value of HttpRequest.CurrentExecutionFilePath property for the endpoint with the relative address differs between the problematic server (~/Service1.svc/problem) and the working servers (~/Service1.svc). Although I'm not that well familiar with IIS, I suspect this could hint at the cause of the problem - maybe something related to the routing of requests?
I am running out of ideas therefore I'm posting this here in the hope the someone will recognize what the problem could be. Any suggestion are welcome.

Do you have URL rewriting on IIS turned on? This smells like a permission issue of some sort. What is the difference between Classic and Integrated pipeline mode in IIS7? Might be helpful.

The problem may be the address "~/Service1.svc/problem"
When the address is "~/Service1.svc" the call hits the svc file, and uses the information in the file to find the interface and then the configuration for that interface.
When you use a relative address without a svc file, it looks at the address in the config file.
Do you have a directory "Service1.svc" on one of the servers, or is the address without the ".svc" on the server where it works?

Related

WCF This could be due to the service endpoint binding not using the HTTP protocol

Default.aspx.cs
WCFService.Service1Client client = new WCFService.Service1Client();
string stream = client.JsonSerializeFromDatabase();
client.Close();
WCFService.Service1Client client2 = new WCFService.Service1Client();
foreach (WCFService.Person in client2.JsonDeserializeFromDatabase(stream))
Service1.svc.cs
public IList<Person> JsonDeserializeFromDatabase(string value)
{
MemoryStream ms = new MemoryStream(Encoding.ASCII.GetBytes(value));
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(List<Person>));
IList<Person> tableData = (IList<Person>)ser.ReadObject(ms);
ms.Close();
ms.Dispose();
return tableData;
}
IService1.cs
[OperationContract]
IList<Person> JsonDeserializeFromDatabase(string value);
Server Web.config
<httpRuntime maxRequestLength="8192"/>
</system.web>
...
<system.serviceModel>
<services>
<service name="TestWCF.Service1" behaviorConfiguration="TestWCF.Service1Behavior">
<endpoint address="" binding="wsHttpBinding" contract="TestWCF.IService1">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="TestWCF.Service1Behavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<dataContractSerializer maxItemsInObjectGraph="2147483646"/>
</behavior>
</serviceBehaviors>
Client Web.config
<httpRuntime maxRequestLength="8192"/>
</system.web>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="debuggingBehaviour">
<dataContractSerializer maxItemsInObjectGraph="2147483646" />
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService1" closeTimeout="00:50:00" openTimeout="00:50:00" receiveTimeout="00:50:00" sendTimeout="00:50:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxDepth="64" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
<reliableSession ordered="true" inactivityTimeout="00:50:00" enabled="false"/>
<security mode="Message">
<message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="~~~~~/Service1.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1" contract="WCFService.IService1" name="WSHttpBinding_IService1" behaviorConfiguration="debuggingBehaviour">
Exception Information
- Type: System.ServiceModel.CommunicationException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- Message: An error occurred while receiving the HTTP response to ~~~~~/Service1.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.
I got this exception information from Server trace viewer, so please do not advise me to put <-system.diagnostics-> tag.
As you can see, I increased all the size thing.
Like.. i don't know why I am getting an error when I call JsonDeserializeFromDatabase(stream).
"An error occurred while receiving the HTTP response to ~~~~~/Service1.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."
I too have experienced this error message when returning records from a database in a WCF service. As well as increasing maxReceivedMessageSize in the binding in the client configuration (App.config), a separate problem seems to be that WCF has problems serializing Entity Framework objects if they have relationships that lead to circularity in their object graphs.
I solved this by returning buddy class objects (which are copies of the raw database records, but without any relationship links) rather than the raw database classes themselves.
Hope this helps -
And WHY doesn't Microsoft produce better error messages?? Here, as in many other cases, the error message gives no clue to the real problem (the serialization of the return value from the WCF call)!
re: WCF & problems serializing Entity Framework objects if they have relationships that lead to circularity in their object graphs. I was getting the same error and the answer provided by user1956642 and it did point me in the right direction, but later realized I could serialize these entities by configuring the DbContext
context.Configuration.ProxyCreationEnabled = false;
Lazy loading is still enabled, but I believe the dynamic proxies are used for change tracking and lazy loading. So yea ... just my 5c

Wcf WS-Security server

i have created service with such binding configuration:
<bindings>
<customBinding>
<binding name="DefaultBinding">
<textMessageEncoding messageVersion="Soap12" />
<httpTransport />
</binding>
</customBinding>
</bindings>
And when my service receives message starting like this:
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<Security s:mustUnderstand="1" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<UsernameToken>
<Username>
</Username>
<Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">...</Password>
<Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">KWVa4abCrEemOMT55VEZkgIAAAAAAA==</Nonce>
<Created xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2013-08-28T13:29:05.966Z</Created>
</UsernameToken>
</Security>
...
It produces error:
The header 'Security' from the namespace 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' was not understood ...
I also tried:
<wsHttpBinding>
<binding name="DefaultBinding">
<security mode="Message" />
</binding>
</wsHttpBinding>
How i can process this header or ignore it ?
Update
As i understood i need username over insecure transport, so i tried:
<customBinding>
<binding
name="DefaultBinding">
<textMessageEncoding messageVersion="Soap12" />
<security authenticationMode="UserNameOverTransport" allowInsecureTransport="True">
</security>
<httpTransport>
</httpTransport>
</binding>
</customBinding>
I also tried CUB:
<bindings>
<clearUsernameBinding>
<binding name="myClearUsernameBinding" messageVersion="Soap12">
</binding>
</clearUsernameBinding>
</bindings>
Both ends with error on client: An error occurred when verifying security for message. But it works with test CUB's client. What could be wrong ?
CUB's envelope's header.
Test client's header.
Solution was simple:
Create service behavior
Create dispatch message inspector
Add created service behavior to server
And then just parse or just delete unused "mustUnderstand" headers.
Step 1:
public class WSSecurityBehavior : IServiceBehavior {
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase,
Collection<ServiceEndpoint> endpoints,
BindingParameterCollection bindingParameters) {
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {
var endpoints = serviceHostBase
.ChannelDispatchers
.Cast<ChannelDispatcher>()
.SelectMany(dispatcher => dispatcher.Endpoints);
foreach (var endpoint in endpoints)
endpoint.DispatchRuntime.MessageInspectors.Add(new WSSecurityInspector());
}
}
Step 2:
public class WSSecurityInspector : IDispatchMessageInspector {
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) {
var headerPosition = request.Headers.FindHeader("Security",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
if (headerPosition > -1)
request.Headers.RemoveAt(headerPosition);
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState) {
}
}
Step 3:
Host.Description.Behaviors.Add(new WSSecurityBehavior());
You've got a mismatch in the soap structure/contract you're exchanging between the client and host. The structure of the messages exchanged between the client and host (including the namespace) must match exactly. If they don't, you get this error.
What you want to do is get Fiddler running on your host. Then, running Fiddler as an man-in-the-middle proxy, resend the request from your client machine. When the request/response is finished, examine the messages in Fiddler, particularlly the namespace and structure differences between the request and response and there you should find the problem.
The client is trying to authenticate to your server using user/pass in the message level. You need to decide if this is expected behavior, in which case you need to configure your service to do username authentication. This is not just a matter of setting a binding, you need to decide how you authenticate users (e.g. via a database, windows credentials etc). Once you know that you should be able to use a binding like this:
<customBinding>
<binding name="NewBinding0">
<textMessageEncoding />
<security authenticationMode="UserNameOverTransport">
<secureConversationBootstrap />
</security>
<httpsTransport />
</binding>
</customBinding>
I cannot be sure that this is what you need since you did not publish the full soap envelope. You might need to set messageVersion attribute on the text encoding element, or use CUB in case there is no SSL.
Then you need to configure how you are going to verify the username. One example is here.
you can use basicHttpBinding, download the project and sample code from this post for password digest in wcf PasswordDigest Auth this is my configuration with this implementation (i edited some code for custom needs but this solution works fine).
Create a binding:
<bindings>
<basicHttpBinding>
<binding name="securityBinding">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
And after set a behavior
<behavior name="securityBehavior">
<DataMessageTracer/>
<serviceCredentials type="WCF.SecurityExtensions.ServiceCredentialsEx, WCF.SecurityExtensions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<serviceCertificate findValue="hypori2.zed.pa" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyService.Utils.PassValidator, MyService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</serviceCredentials>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>

WCF ERROR: The server did not provide a meaningful reply;

please somebody can help me to find out what is happened. I have my WCF service which worked fine, and now suddenly I have this error:
The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal
server error
I must tell that it still works when I select some thousands of records, but when the data is huge I receive this error, although before it worked fine!
private static string ConnString = "Server=127.0.0.1; Port=5432; Database=DBname; User Id=UName; Password=MyPassword;"
DataTable myDT = new DataTable();
NpgsqlConnection myAccessConn = new NpgsqlConnection(ConnString);
myAccessConn.Open();
string query = "SELECT * FROM Twitter";
NpgsqlDataAdapter myDataAdapter = new NpgsqlDataAdapter(query, myAccessConn);
myDataAdapter.Fill(myDT);
foreach (DataRow dr in myDT.Rows)
{
**WHEN I HAVE TOO MANY RECORDS IT STOPS HERE**
...
web.config
<configuration>
<system.web>
<compilation debug="false" targetFramework="4.0" />
<httpRuntime maxRequestLength="2147483647" executionTimeout="100000" />
</system.web>
<system.diagnostics>
<trace autoflush="true" />
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="Traces4.svclog"/>
</listeners>
</source>
</sources>
</system.diagnostics>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IDBService" closeTimeout="00:30:00"
openTimeout="00:30:00" receiveTimeout="00:30:00" sendTimeout="00:30:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
messageEncoding="Text" textEncoding="utf-8" transferMode="Streamed"
useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IDBService" contract="DBServiceReference.IDBService"
name="BasicHttpBinding_IDBService" />
</client>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="2147483646" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
</configuration>
client config (Edited)
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IRouteService" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
<binding name="BasicHttpBinding_IDBService" closeTimeout="00:30:00"
openTimeout="00:30:00" receiveTimeout="00:30:00" sendTimeout="00:30:00"
maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"
transferMode="Buffered" >
<security mode="None" />
</binding>
</basicHttpBinding>
<customBinding>
<binding name="CustomBinding_IRouteService">
<binaryMessageEncoding />
<httpTransport maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://dev.virtualearth.net/webservices/v1/routeservice/routeservice.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IRouteService"
contract="BingRoutingService.IRouteService" name="BasicHttpBinding_IRouteService" />
<endpoint address="http://dev.virtualearth.net/webservices/v1/routeservice/routeservice.svc/binaryHttp"
binding="customBinding" bindingConfiguration="CustomBinding_IRouteService"
contract="BingRoutingService.IRouteService" name="CustomBinding_IRouteService" />
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IDBService"
contract="DBServiceReference.IDBService" name="BasicHttpBinding_IDBService" />
</client>
</system.serviceModel>
</configuration>
In my file scvlog I don' t get any exception!
I don't have any other idea what else I can do for understand where is the problem. Please somebody help me!!!
A different answer, just in case anyone arrives here as I did looking for a general answer to the question.
It seems that the DataContractSerializer that does the donkey-work is incredibly finicky, but doesn't always pass the real error to the client. The server process dies straight after the failure - hence no error can be found. In my case the problem was an enum that was used as flags, but not decorated with the [Flags] attribute (picky or what!).
To solve it I created an instance of the serializer and inspected the error in the debugger; here's a code snippet since I have it to hand.
EDIT: In response to request in comments ...
Amended the code snippet to show the helper method I now use. Much the same as before, but in a handy generic wrapper.
public static T CheckCanSerialize<T>(this T returnValue) {
var lDCS = new System.Runtime.Serialization.DataContractSerializer(typeof(T));
Byte[] lBytes;
using (var lMem1 = new IO.MemoryStream()) {
lDCS.WriteObject(lMem1, returnValue);
lBytes = lMem1.ToArray();
}
T lResult;
using (var lMem2 = new IO.MemoryStream(lBytes)) {
lResult = (T)lDCS.ReadObject(lMem2);
}
return lResult;
}
And to use this, instead of returning an object, return the object after calling the helper method, so
public MyDodgyObject MyService() {
... do lots of work ...
return myResult;
}
becomes
public MyDodgyObject MyService() {
... do lots of work ...
return CheckCanSerialize(myResult);
}
Any errors in serialization are then thrown before the service stops paying attention, and so can be analysed in the debugger.
Note; I wouldn't recommend leaving the call in production code, it has the overhead of serializing and deserializing the object, without any real benefit once the code is debugged.
Hope this helps someone - I've wasted about 3 hours trying to track it down.
I don't know if it's really can be an answer, but I have tried to change in web.config from <security mode="None" /> to <security mode="Transport" /> and It worked!!!
I'd want to pay attention that this part should be changed only in web.config and in client configuration remains <security mode="None" />, because with Transport in both It doesn't work!
So after that, I decided to try to come back again to None security and It worked for some minutes and then stopped again, and it came back the error:
The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error
So It seems that the solution in my case is to set in web.config
security mode to Transport
In my case, I was working on a windows app project communicating with a WCF Web Service.
The web service, using netTcpBinding was returning a Stream object (a picture).
As the windows app doesn't have configuration file, default values are used for bindings. And simply extending the MaxReceivedMessageSize on the client side backend code solved my problem.
var API = new StreamService.StreamServiceClient(
new System.ServiceModel.NetTcpBinding(System.ServiceModel.SecurityMode.None)
{
MaxReceivedMessageSize = 2147483647
},
new System.ServiceModel.EndpointAddress("net.tcp://machine/app/service.svc")
);
Sometimes this problem is caused by an oversized message that was cut due to default values in the binding.
You should add maxReceivedMessageSize, maxBufferPoolSize and maxBufferSize with some large enough values to the binding in your app.config file - that should do the trick :)
Example:
<bindings>
<netTcpBinding>
<binding
name="ExampleBinding" closeTimeout="00:01:00"
maxReceivedMessageSize="73400320"
maxBufferPoolSize="70000000"
maxBufferSize="70000000"/>
</netTcpBinding>
</bindings>
Good Luck!
In my case I was working on an MVC application and I have changed
maxReceivedMessageSize ="10000000"
to
maxReceivedMessageSize ="70000000"
and it worked! It's because the response from the web server exceeds maxReceivedMessageSize ="10000000",
so I have increased maxReceivedMessageSize to maxReceivedMessageSize ="70000000".
In my experience of this error, just check the service's host computer's event log to see what is the actual root exception.
For me it was a lazy-loading list of items retrieved from the DB.
The WCF receiver would try to iterate them, which would try to go to the DB, which obviously could not work.
In BizTalk we use to get this issue.
Mostly the issue will happen due to size of the message from the service. So we need to increase the size of the receiving message from 65,356 to 2,365,60. It worked for me.
enter image description here
ASP.NET applications can execute with the Windows identity (user account) of the user making the request. Impersonation is commonly used in applications that rely on Microsoft Internet Information Services (IIS) to authenticate the user. ASP.NET impersonation is disabled by default.
Enable this, your API will start working - it is in IIS authentication
In my case, after upgrading from .NET Framework 4.5 to .NET Framework 4.8, I had to remove read-only modifiers of properties that were decorated with DataMemberAttribute.

Using wsHttpBinding

After reading more about it and trying to implement wshttpbinding, it just won't happen. No matter what I try, I keep getting the below error message (with security mode commented out). I understand why because of the different SOAP versions between bindings.
"(415) Cannot process the message because the content type 'application/soap+xml; charset=utf-8' was not the expected type 'text/xml; charset=utf-8'"
I read more about the TransportWithMessageCredentials at the following link:
http://msdn.microsoft.com/en-us/library/ms789011.aspx
but still could not get it to work.
I can use basicHttpBinding just fine for internal apps and works great (if I don't include any transactions), but my application in the WCF layer still needs to support transactions (see below), from which I understand that basicHttpBinding doesn't support, because it doesn't contain the transactionflow attribute.
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
When I try and run the below with the security mode included, the svc config editor doesn't even start up and throws the following error: "System.InvalidOperationException: Could not find a base address that matches scheme https for the endpoint with binding WSHttpBinding. Registered base address schemes are [http]."
I know it's expecting some kind of SSL/https security, but my website (as you can see below is http) . That would be fine for the public facing websites, but for internal sites, for now, all I want to do is have support for transactions.
Here is my server side setup for wsHttpBinding:
<bindings>
<wsHttpBinding>
<binding name="WsHttpBinding_IYeagerTechWcfService" closeTimeout="00:02:00" openTimeout="00:02:00" receiveTimeout="24.20:31:23.6470000" sendTimeout="00:10:00" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" transactionFlow="true">
<security mode="Transport" >
<transport clientCredentialType = "Windows" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<?xml version="1.0"?>
<services>
<clear />
<service name="YeagerTechWcfService.YeagerTechWcfService">
<endpoint address="" binding="wsHttpBinding" contract="YeagerTechWcfService.IYeagerTechWcfService" >
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://abc.com/yeagerte/YeagerTechWcfService.YeagerTechWcfService.svc" />
</baseAddresses>
</host>
</service>
</services>
Here is my client side setup:
<?xml version="1.0"?>
<client>
<endpoint address="http://abc.com/yeagerte/YeagerTechWcfService.YeagerTechWcfService.svc"
binding="wsHttpBinding" contract="YeagerTechWcfService.IYeagerTechWcfService"
name="WsHttpBinding_IYeagerTechWcfService" />
</client>
Could somebody please provide the following:
Is there another way to support transactions in WCF for basicHttpBinding or any other way for that matter?
If so, how do I implement it?
If not, what are my options?
For the above question, I may have figured out an answer but want to run it by somebody more experienced in this matter.
Instead of having the WCF layer handle the transactions (like mentioned above), I propose I use basicHttpBinding and the following code in my Controller when it passes the data to the WCF layer:
// method here
using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
{
db.EditCategory(cat);
// the above code would execute the EditCategory method below in the WCF layer and keep the transaction alive ts.Complete();
ts.Dispose();
}
return Json(new GridModel(db.GetCategories()));
// end method
WCF layer:
public void EditCategory(Category cat)
{
try
{
using (YeagerTechEntities DbContext = new YeagerTechEntities())
{
Category category = new Category();
category.CategoryID = cat.CategoryID;
category.Description = cat.Description;
// do another db update here or in another method...
DbContext.Entry(category).State = EntityState.Modified;
DbContext.SaveChanges();
}
}
catch (Exception ex)
{
throw ex;
}
}
For public facing websites using SSL, how do I properly implement wsHttpBinding?
I encountered the same problem when using WCF Transactions
I used Message security with Windows authentication and did not have to setup any certificates.
<wsHttpBinding>
<binding name="WSHttpBinding_Transactional"
transactionFlow="true">
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None" />
</security>
</binding>
</wsHttpBinding>

Subscribing to TFS events and WCF

Sorry for asking a question about something I don't know much about, but I've been pulling my hair out trying to get this working.
So, I have a WCF service that is hosted on IIS and seems to be working insomuch that I can "see" it on the network by going to http://servername/MyService.svc in a browser.
That .svc looks like:
<% #ServiceHost Service="Foo.Bar" %>
The relevant code looks like:
[ServiceContract(Namespace = "http://schemas.microsoft.com/TeamFoundation/2005/06Services/Notification/03")]
public interface IBar
{
[OperationContract(Action = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03/Notify", ReplyAction = "*")]
[XmlSerializerFormat(Style = OperationFormatStyle.Document)]
void Notify(string eventXml, string tfsIdentityXml);
}
and:
public class Bar : IBar
{
public void Notify(string eventXml, string tfsIdentityXml)
{
// Just some test output to see if it worked
var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "tfs.txt");
File.WriteAllText(path, tfsIdentityXml + eventXml);
}
}
That's all been built and the ensuing .dll put into the bin dir in the site root in IIS.
I now want to subscribe via bissubscribe.exe (or a similar method) to TFS check-in events. I tried doing something like:
bissubscribe /eventType CheckinEvent
/address http://servername/MyService.svc
/deliveryType Soap
/server mytfsserver
But nothing; it doesn't even look like there was log activity. So keeping in mind I know nothing about WCF, what am I doing wrong? I imagine the address param is one thing; am I not supposed to point it to the .svc?
I have created a blog post how you can use WCF in combination with the Event Services of TFS: http://www.ewaldhofman.nl/post/2010/08/02/How-to-use-WCF-to-subscribe-to-the-TFS-2010-Event-Service-rolling-up-hours.aspx
TFS 2010 and WCF 4.0 configurations are described below...
Method signature:
public void Notify(string eventXml) /* No SubscriptionInfo! */
Web config:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="Microsoft.TeamFoundation, Version=10.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
</assemblies>
</compilation>
</system.web>
<system.serviceModel>
<services>
<service behaviorConfiguration="NotificationServiceBehavior" name="TF.CheckinListener.CheckinListener">
<endpoint address="Notify" binding="wsHttpBinding" bindingConfiguration="noSecurity" contract="TF.CheckinListener.ICheckinListener" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="NotificationServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
</binding>
<wsHttpBinding>
<binding name="noSecurity" maxBufferPoolSize="20000000" maxReceivedMessageSize="200000000">
<readerQuotas maxStringContentLength="200000000" maxArrayLength="200000000" />
<security mode="None" />
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Subscription address for bissubscribe:
http://MachineName/VirtualDirectoryName/Service.svc/Notify
One point that jumps out is the fact you have a method that doesn't return anything except void. Those should be marked as "one-way" method in WCF:
[ServiceContract(Namespace = "http://schemas.microsoft.com/TeamFoundation/2005/06Services/Notification/03")]
public interface IBar
{
[OperationContract(Action = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03/Notify", ReplyAction = "*", IsOneWay=true)]
[XmlSerializerFormat(Style = OperationFormatStyle.Document)]
void Notify(string eventXml, string tfsIdentityXml);
}
Add the "IsOneWay=true" to your [OperationContract] attribute.
Other than that, there's nothing obviously wrong in your code, but to really tell, we'd need a lot more config info to really tell. Try the IsOneWay=true first and see if that solves your issue.
How is your service configured? In particular, is it configured to use basicHttpBinding?
Try creating a client to call your service to make sure it can be called.
Then, see if there's an example service from the TFS SDK - see if you can get the example to work.
I was able to complete this connection with the following:
[ServiceContract(Namespace = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03")]
public interface ITeamSystemObserver : IObservable
{
[OperationContract( Action = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03/Notify", ReplyAction = "*" )]
[XmlSerializerFormat(Style=OperationFormatStyle.Document)]
void Notify(string eventXml, string tfsIdentityXml, SubscriptionInfo SubscriptionInfo);
}
Note you are missing the SubscriptionInfo parameter. Here is my web.config:
<basicHttpBinding>
<binding name="TfsEventServiceBasic">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" />
</security>
</binding>
</basicHttpBinding>