MSMQ receives messages only from some Clients - wcf

I have a WCF service where client applications can connect via a MSMQ:
[ServiceContract(Namespace="http://example.com", SessionMode = SessionMode.NotAllowed)]
public interface IMyService
{
[OperationContract(IsOneWay = true)]
void Update(DataSet ds);
}
and then:
string queueName = ConfigurationManager.AppSettings["QueueName"];
NetMsmqBinding binding = new NetMsmqBinding("MyBinding");
if (!MessageQueue.Exists(#".\private$\" + queueName))
{
MessageQueue.Create(#".\private$\" + queueName, binding.ExactlyOnce);
}
ServiceHost msmqHost = new ServiceHost(typeof(MyService));
msmqHost.AddServiceEndpoint(typeof(IMyService), binding, "net.msmq://localhost/private/" + queueName);
with the following configuration:
<system.serviceModel>
<bindings>
<netMsmqBinding>
<binding name="MyBinding" durable="false" exactlyOnce="false" maxReceivedMessageSize="20000000">
<security mode="None" />
<readerQuotas maxDepth="32" maxStringContentLength="543192" maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="8456384" />
</binding>
</netMsmqBinding>
</bindings>
<services>
<service name="MyService" behaviorConfiguration="MsMqBehavior" />
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MsMqBehavior">
<serviceThrottling maxConcurrentCalls="50" maxConcurrentSessions="50" maxConcurrentInstances="50" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
I have the service with the same configuration already in use without problems on other installations. But now on a new installation I receive only messages from some clients (9 actually - there are 31). The messages I receive are always from the same servers. I can't find an error message anywhere (Windows Event Log (Client/Server), WCF Trace file) and also the MSMQ state says "connected" on the client machines that don't send messages. The dead letter queues are also empty.
The messages must get lost somewhere between the MSMQ Client and Server (I stopped my app and on the server queue I received only messages from the nine Clients - same behaviour if I enable journaling).
Any help would be appreciated
Update
I've used performance counters to monitor the queue. The session counter shows the correct value of 31 sessions. Also the incoming message counter shows correct values. However if I stop the app or enable journaling only a part of the messages are stored in the queue.

The problem comes through cloning the server as described in this blog entry: http://blogs.msdn.com/b/johnbreakwell/archive/2007/02/06/msmq-prefers-to-be-unique.aspx
Basically it says there that you must not clone servers with MSMQ feature turned on. If you do so you either have to re-install the MSMQ feature on your client machines or do a registry change:
1.Stop the MSMQ Service
2.Delete the QMId value completely
3.Add a SysPrep DWORD (Under HKLM\Software\Microsoft\MSMQ\Parameters) and set it to 1
4.Start the MSMQ Service

Related

How to authenticate wsdl get with TransportWithMessageCredential security mode for the endpoint?

I have a WCF endpoint that exposes a API with a basicHttpBinding. This biding is set to use security mode TransportWithMessageCredentialand UserName for clientCredentialType.
Because security is implemented at message level, at the WCF, the IIS needs to allow anonymous access. And so, wsdl can be obtain without providing any credentials.
How to force authentication to get the service metadata?
Here the current service configuration looks like (from web.config)
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="secure">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="secure" name="someProject.MyService">
<endpoint binding="basicHttpBinding" contract="someProject.IService" bindingConfiguration="secure" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="secure">
<serviceMetadata httpsGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
I try the obvious, to set a specific binding for the metatada, by using service behavior configuration:
<behavior name="secure">
<serviceMetadata httpsGetEnabled="true" httpsGetBinding="basicHttpBinding" httpsGetBindingConfiguration="transportSecure" />
</behavior>
//and add the new binding
<basicHttpBinding>
<binding name="transportSecure">
<security mode="Transport">
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>
But it is not supported. It throws this:
MessageVersion 'Soap11 (http://schemas.xmlsoap.org/soap/envelope/)
AddressingNone
(http://schemas.microsoft.com/ws/2005/05/addressing/none)' is not
supported in this scenario. Only MessageVersion 'EnvelopeNone
(http://schemas.microsoft.com/ws/2005/05/envelope/none) AddressingNone
(http://schemas.microsoft.com/ws/2005/05/addressing/none)' is
supported.
I don't understand this error or how to get around it.
Normally we will not disclose our metadata in the production environment,But if you want to enable metadata, we can use https binding to protect the metadata.
1.Configure a port with an appropriate X.509 certificate. The certificate must come from a trusted authority, and it must have an intended use of "Service Authorization." You must use the HttpCfg.exe tool to attach the certificate to the port.
2.Create a new instance of the ServiceMetadataBehavior class.
3.Set the HttpsGetEnabled property of the ServiceMetadataBehavior class to true.
4.Set the HttpsGetUrl property to an appropriate URL. Note that if you specify an absolute address, the URL must begin with the scheme https://. If you specify a relative address, you must supply an HTTPS base address for your service host. If this property is not set, the default address is "", or directly at the HTTPS base address for the service.
5.Add the instance to the behaviors collection that the Behaviors property of the ServiceDescription class returns, as shown in the following code.
ServiceMetadataBehavior sb = new ServiceMetadataBehavior();
sb.HttpsGetEnabled = true;
sb.HttpsGetUrl = new Uri("https://myMachineName:8036/myEndpoint");
myServiceHost.Description.Behaviors.Add(sb);
myServiceHost.Open();
This is authentication enabled on WCF, you can also enable windows authentication on IIS, both methods can protect metadata.
But in the production environment, I do not recommend that you enable metadata, because this will lead to the risk of metadata leakage.The call of WCF service can also be called through the channel factory. In this case, we can call WCF service without knowing the metadata of the server.
For more information on how to protect metadata, you can refer to this link:
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-secure-metadata-endpoints?redirectedfrom=MSDN

How to configure WCF BasicHttpBinding with Basic Authentication for usage in Adobe Flex?

Architecture
I have a simple example web service that exposes two operations by ServiceContract and OperationContract, nothing fancy. This service should be consumed by an Adobe Flex 4 client. Unfortunately Flex can just handle SOAP 1.1 (and not SOAP 1.2), so I have to use the BasicHttpBinding on WCF side. To secure the access to the web service I've to use Basic Authentication, because it's the only authentication method both sides (WCF and Flex) understand. Basic Authentication goes along with SSL to encrypt the transport. I run the service in IIS Express with Visual Studio 2012.
WCF service configuration
Web.config
<system.serviceModel>
<services>
<service name="UserAuthentication.AuthenticationService"
behaviorConfiguration="AuthenticationServiceBehavior">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="AuthenticationBinding"
contract="UserAuthentication.IAuthenticationService" />
<endpoint contract="IMetadataExchange"
binding="mexHttpBinding"
address="mex" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="AuthenticationBinding" maxReceivedMessageSize="65536">
<!-- Use SSL (Transport) and MessageCredential by Username (referencing behaviors/serviceBehaviors/behavior/serviceCredentials) -->
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None" />
<message clientCredentialType="UserName" />
</security>
<readerQuotas maxArrayLength="65536" maxBytesPerRead="65536" maxStringContentLength="65536"/>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="AuthenticationServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="false" />
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
<!-- Use Custom DistributorValidator for Basic Authentication -->
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="UserAuthentication.DistributorValidator,UserAuthentication"/>
<!--<serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />-->
</serviceCredentials>
<!-- For Debug purpose: #see http://intrepiddeveloper.wordpress.com/2008/08/07/security-event-logging-auditing/ -->
<serviceSecurityAudit auditLogLocation="Application" serviceAuthorizationAuditLevel="Failure" messageAuthenticationAuditLevel="Failure" suppressAuditFailure="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
DistributedValidator.cs
Should be used to authenticate the user by username and password from Basic Authentication.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
namespace UserAuthentication
{
public class DistributorValidator : UserNamePasswordValidator
{
/* Throw exeption to deny access for user */
public override void Validate(string userName, string password)
{
if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password))
throw new SecurityTokenException("Username and password required");
if( userName.Equals("user") == false || password.Equals("secretpwd") == false)
throw new FaultException(string.Format("Wrong username ({0}) or password ", userName));
}
}
}
Start service with SSL in IIS Express
Select project in Solution Explorer press F4 to open the properties panel
Set property SSL enabled to True
To run project press F11 (HTTP version of the page should open in your browser)
Right click on the IIS Express icon in your task bar tray and select the HTTPS version of your page
You can now open the WSDL file of the service via HTTPS
Consuming web service with Flex
Connect to web service as described in the Adobe documentation. This works fine so far and the service has been created in the Data/Services panel of the Flash Builder.
Problem
Test the web service through the Test Operation panel in the Flash Builder, the result is the HTML source code from https://localhost:44301/AuthenticationService.svc and not an expected SOAP message.
Trying the same web service and operation with the free version of SoapUI, the result is this SOAP envelope:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<s:Fault>
<faultcode xmlns:a="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">a:InvalidSecurity</faultcode>
<faultstring xml:lang="de-AT">An error occurred when verifying security for the message.</faultstring>
</s:Fault>
</s:Body>
</s:Envelope>
In addition a MessageSecurityException is logged to the Windows Event Viewer:
Message authentication failed.
Service: https://localhost:44301/AuthenticationService.svc
Action: http://tempuri.org/IAuthenticationService/GetData
ClientIdentity:
ActivityId: <null>
MessageSecurityException: Security processor was unable to find a security header in the message. This might be because the message is an unsecured fault or because there is a binding mismatch between the communicating parties. This can occur if the service is configured for security and the client is not using security.
In both cases (Flex and SoapUI) the custom DistributorValidator is never touched, so the problem is placed deeper in the magic of WCF.
Question
Is there any possibility to run a WCF service with BasicHttpBinding and Basic Authentication that play nicely together with Adobe Flex?
You need to mess with the headers to get basic HTTP auth to work with HTTPService.
It would look something like this when making the call from Flex...
var encoder:Base64Encoder = new Base64Encoder();
encoder.insertNewLines = false; // or else your header may fail...
encoder.encode("user_name:user_pass");
service.headers = {Authorization:"Basic " + encoder.toString()};
service.send(); //where servie is an instance of HTTPService

Remote computer is not available when trying to pull from remote private queue

I have a remote private queue that I can write to without issue. I am trying to create a WAS-hosted WCF service to pull the data for processing. I need the service to be on a different machine than the queue; I currently have it in the same site as the writing service - same app pool but a different application.
The queue I am targetting is called PersistenceService/Log.svc and is transactional and authenticated. My service is running at http://appdev.me.com/PersistenceService/Log.svc. The below contains my endpoint and binding:
<bindings>
<msmqIntegrationBinding>
<binding exactlyOnce="true" durable="true" serializationFormat="Xml" maxReceivedMessageSize="2147483647"
closeTimeout="00:00:30" sendTimeout="00:00:30" receiveTimeout="00:00:30" timeToLive="24:00:00"
receiveRetryCount="1" maxRetryCycles="1" retryCycleDelay="00:10:00" receiveErrorHandling="Move">
<security mode="Transport" />
</binding>
</msmqIntegrationBinding>
</bindings>
<services>
<service name="Me.Logging.Persistence.PersistenceService">
<endpoint address="msmq.formatname:DIRECT=OS:DIRECT=OS:meserver\private$\persistenceservice/log.svc"
binding="msmqIntegrationBinding"
bindingNamespace="http://me.logging/services/2012/11"
contract="Me.Logging.Service.Shared.Service.Contracts.ICatchAll" />
</service>
</services>
The error that I get is the below:
An error occurred while opening the queue:The remote computer is not available. (-1072824215, 0xc00e0069). The message cannot be sent or received from the queue. Ensure that MSMQ is installed and running. Also ensure that the queue is available to open with the required access mode and authorization.
I have cleared the way for communications by shutting down McAfee so it's not blocking traffic. I have granted ANONYMOUS LOGON access to the queue temporarily - though it should be coming in as the same user through which I'm writing to the queue, and that user has full rights on the queue.
The WCF trace doesn't reveal anything other than this error. Any ideas as to where to look would be greatly appreciated.
Your endpoint looks to be incorrect. You have "DIRECT=OS:" in there twice. Try:
<endpoint address="msmq.formatname:DIRECT=OS:meserver\private$\persistenceservice/log.svc"
binding="msmqIntegrationBinding"
bindingNamespace="http://me.logging/services/2012/11"
contract="Me.Logging.Service.Shared.Service.Contracts.ICatchAll" />

Wcf 3.5 - Different endpoints with different bindings and SOAP

I have a problem... I explored whole internet and I don't know what I'm doing wrong.
Problem: WCF web service, .Net Framework 3.5, 2 different type of clients (Handheld device and usual computer)
What I'm trying to do is to create 2 diferent endpoints, one with basicBinding (For SOAP request) and other with wsBinding (for usual computers)
So I go thru web.config and I created 2 different bindings, related with 2 different endpoints:
<bindings>
<basicHttpBinding>
<binding name="BasicBinding" openTimeout="00:10:00" receiveTimeout="23:59:00"
sendTimeout="23:59:00" messageEncoding="Text" />
</basicHttpBinding>
<wsHttpBinding>
<binding name="DefaultBinding" openTimeout="00:10:00" receiveTimeout="23:59:59"
sendTimeout="23:59:59">
<reliableSession inactivityTimeout="01:00:00" />
<security mode="None">
<transport clientCredentialType="None" />
<message clientCredentialType="None" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="qtswsdl.QTS_ServiceBehavior"
name="qtswsdl.QTS_Service">
<endpoint address="http://host.com/service.svc/ForHh"
binding="basicHttpBinding" bindingConfiguration="BasicBinding"
name="handHeldEndPoint" contract="qtswsdl.QTSPort" />
<endpoint address="http://host.com/service.svc/ForCp"
binding="wsHttpBinding" bindingConfiguration="DefaultBinding"
name="coProcessorEndPoint" contract="qtswsdl.QTSPort" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="qtswsdl.QTS_ServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
<serviceThrottling maxConcurrentCalls="2147483647"maxConcurrentSessions="2147483647"
maxConcurrentInstances="2147483647" />
</behavior>
</serviceBehaviors>
</behaviors>
So when I try to send SOAP messages to "http://host.com/service.svc/ForHh" Im getting a "HTTP 400 - Bad Request" (the /ForCp is also not working)
I tried with custom clients, with WcfTestClient.exe and I was not able to fin what is happening
Any tip or suggestion?
Thanks for your time
EDIT:
After enable Svc trace I got a couple of exceptions:
<Message>The message with Action 'http://Host.com/Service.svc/ForHh' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).</Message>
Funny thing is that I'm sending the SOAP request programatically. It's my understanding that if I'm sending SOAP request programatically i don't need to define any contract because it is being send using SOAP 1.1 by default.
Code that sends the request is the following code:
private string SendRequestAndGetAnswerFromWebService(string methodName, string requestXml){
StringBuilder soapRequest = new StringBuilder("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
soapRequest.Append(" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" ");
soapRequest.Append("xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body>");
soapRequest.Append(requestXml);//Body
soapRequest.Append("</soap:Body></soap:Envelope>");
WebRequest webRequest = WebRequest.Create(#"http://Host.com/Service.svc/" + methodName);
HttpWebRequest httpRequest = (HttpWebRequest)webRequest;
httpRequest.Method = "POST";
httpRequest.ContentType = "text/xml; charset=ascii";
httpRequest.Headers.Add("SOAPAction: " + #"http://Host.com/Service.svc/Service.svc/" + methodName);
httpRequest.ProtocolVersion = HttpVersion.Version11;
httpRequest.Credentials = CredentialCache.DefaultCredentials;
httpRequest.Timeout = 7000;
httpRequest.ContentLength = System.Text.Encoding.ASCII.GetByteCount(soapRequest.ToString());
Stream requestStream = httpRequest.GetRequestStream();
//Create Stream and send Request
StreamWriter streamWriter = new StreamWriter(requestStream, Encoding.ASCII);
streamWriter.Write(soapRequest.ToString());
//Send the request
streamWriter.Close();
//Get the Response
HttpWebResponse wr = (HttpWebResponse)httpRequest.GetResponse();
StreamReader srd = new StreamReader(wr.GetResponseStream());
string resulXmlFromWebService = srd.ReadToEnd();
return resulXmlFromWebService;
}
Maybe my assumption about contract and soap messages sent programatically are wrong...
Generally, this is very bad practice -- you should NOT be manually authoring SOAP requests to WCF services this way. It is better if you were to take advantage of the out-of-the-box WCF request/reply paradigms instead of resorting to setting up headers manually.
What I would recommend is to create an alternative example where you DO achieve the same thing out-of-the-box (with perhaps DataContracts, OperationContracts, and ServiceContracts on the client-end, perhaps taking advantage of WebHttpBehavior and WebHttpBinding). Examine the exact messages that are sent and received in that scenario, and closely examine, character by character, how those messages are different from the ones you're sending here.
Also, it's hard to tell what else you could be doing wrong from just the detail you've provided.
Here is what I suggest:
Enable tracing on the service side, generate tracing logs, and analyze with SvcTraceViewer. To do this, follow the instructions at this MSDN article on using the service trace viewer. Notice what's different between the first and second time.
Turn on debug exceptions. This is done by turning in includeExceptionDetailInFaults, which you can do by following the instructions here. Notice what's different between the first and second time.
Use Fiddler to monitor the wire traffic on both the client side and the service side.
Generally, once you do this, you should plenty of more info on what's going funky at the service side and can diagnose the issue pretty quickly. Try it, and please report back! :)

WCF Service (wsHttpBinding binding) behind F5 load balancer

current setup:
- i have got a WCF service with wsHttpBding, see the service config below
- i have implemented a ServiceHostFactory to solve the problem of incorrect schema location and soap addresses, modifying them from machine name to the correct server hostname
- my test client (WCFStorm) i can generate a proxy, see all the methods and invoke them successfully.
- my dev environment (client-> HTTPS -> service) works perfectly.
problems:
- prod environment (client -> HTTPS -> F5 -> HTTP -> service)
- my service is behind F5 load balancer which offloads SSL
- my test client (WCFStorm) i can generate a proxy and see all the methods but when i invoke any of the methods i get a remote server not found 404 error
my service config:
<services>
<service behaviorConfiguration="Service1Behavior"
name="MyService">
<endpoint name="secure" address="" binding="wsHttpBinding" bindingConfiguration="custBinding" contract="IService"/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="custBinding">
<security mode="Transport">
<transport clientCredentialType="None" />
<message clientCredentialType="None" negotiateServiceCredential="false"
establishSecurityContext="false" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="Service1Behavior">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="true" httpGetUrl="http://myserver/MyService.svc"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<dataContractSerializer maxItemsInObjectGraph="6553600" />
</behavior>
</serviceBehaviors>
</behaviors>
please note that all my schema locations and soap addresses on the wsdl are correct in prod, but i simply cannot invoke any methods.
please help.
We have a similar situation and here's how we got it working.
in the service - we changed the binding to use basicHttpBinding and added a key that must be passed with every request.
in the client - we changed the http in the config to https and in the basicHttpBindings config changed the security mode to Transport with clientCredentialType="None".
Hope this helps.
UPDATE: I found this article soon after and I updated the configuration and it worked. So now we are using wsHttpBinding instead of basicHttpBinding.
http://blogs.msdn.com/b/morgan/archive/2010/04/15/setting-up-wcf-with-a-load-balancer-using-ssl-in-the-middle.aspx
The problem with your service config is that the security mode is Transport, where in reality it should be None. Because any calls to your service will be HTTP behind F5 load balancer, you can not use Transport security mode there (client -> HTTPS -> F5 -> HTTP -> service). However, when calling the service from your client, the client config will need to be Transport security mode and the endpoint address will need to have an HTTPS address.
<wsHttpBinding>
<binding name="custBinding">
<security mode="None">
<transport clientCredentialType="None" />
<message clientCredentialType="None" negotiateServiceCredential="false" establishSecurityContext="false" />
</security>
</binding>
</wsHttpBinding>
This might be a little late for you, but here is how we do it. Once I have generated the proxy, I just change the http: in the config to https. Now, if I have to sometimes call it with ssl, and othertimes without, I will copy the config section, and give the copy a different name, and then when you construct the client, you can pass in the config name, and it will pick up the correct one.
We couldn't get this working through Layer 7 load balancing - there was various error messages returned from the service. Instead it's set up on Layer 4 load balancing with no issues.