I have a WCF service which can run as Console App and a Windows Service. I have recently copied the console app up to a W2K3 server with the following security settings:
<wsHttpBinding>
<binding name="ServiceBinding_Security" transactionFlow="true" >
<security mode="TransportWithMessageCredential" >
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="Common.CustomUserNameValidator, Common" />
</serviceCredentials>
Security works fine with no problems. I have exactly the same code, but running in a windows service and I get the following error when I try to call any of the methods from a client:
System.ServiceModel.Security.MessageSecurityException was unhandled
Message="An unsecured or incorrectly secured fault was received from
the other party. See the inner FaultException for the fault code and detail."
Source="mscorlib"
StackTrace:
Server stack trace:
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.ProcessReply(Message reply, SecurityProtocolCorrelationState correlationState, TimeSpan timeout)
......
(lots of stacktrace info - not very useful)
InnerException: System.ServiceModel.FaultException
Message="An error occurred when verifying security for the message."
The exception tells me nothing. I'm assuming that it has something to do with acces to system resources from the Windows Service. I've tried running it under the same account as the console app, but no luck. Does anyone have any ideas?
This is an error that sometimes has nothing to do with security.
I would recomend that you try first to get it to work without security, then just with message security, then with transport and finally with TransportWithMessageCredential.
Also if you are running the console app and the windows service app on the same machine make sure to stop the console app before starting the windows service, in order to avoid a port conflict
Enable diagnostics on the service. That should give you a pretty good idea of whether the service is even receiving the message and where the service is throwing an exception.
Update - I changed the customUserNamePasswordValidatorType from Custom to Windows. This worked fine in both the Console and Windows Service. I can only assume that something in the Custom Validator was causing the problem.
The custom validator used a custom config section in the App.config to validate the userid and Password. I would have thought this would have worked from a windows service though.
Thanks to all those who posted a reply.
You're using a custom user/name validator - does the Windows service have access to that file(s) ?
What account are you running the NT Service under ?
Does it work with all security turned off?? (just to see)
Marc
Related
Perhaps I am barking up the wrong tree - but I have a set of services (WebAPI and WCF) that use WebSphere MQ to interact with other systems.
This works without issue - until I now need to find a way of listening for messages on one of the queues.
Is this even possible, or do I need to go down the windows Service route?
You could write a Windows service that is continually calling MQ Get on the queue, and invokes a WCF service to process the message. Or you could write a trigger program (a console application) that MQ will launch for you when a message arrives, that invokes the WCF service.
I might be just better at googling than you are, but I seem to have found the answer here.
Seems you want to load the IBM binding configuration in you app.config
<extensions>
<bindingElementExtensions>
<add name="IBM.XMS.WCF.SoapJmsIbmTransportChannel"
type="IBM.XMS.WCF.SoapJmsIbmTransportBindingElementConfig, IBM.XMS.WCF, Version=7.5.0.0, Culture=neutral, PublicKeyToken=8c7c0be90afcd8ba"/>
</bindingElementExtensions>
</extensions>
Then you can add a WebSphere WCF binding config.
<bindings>
<customBinding>
<binding name="CustomBinding_WMQ">
<textMessageEncoding messageVersion="Soap11" />
<IBM.XMS.WCF.SoapJmsIbmTransportChannel />
</binding>
</customBinding>
</bindings>
Your problem can be broken down into two distinct elements:
How to integrate MQ with a WCF-supported transport
How to expose a WCF endpoint over this transport
To address the first issue, you should look at the MQ-MSMQ bridge which ships with Host Integration Server up to version 2009 (not R2), which allows you to have messages delivered to MQSeries queues forwarded to local MSMQs in windows. Although this feature is deprecated it's probably the easiest way if you have a MSDN license.
Another way of addressing this issue is to use BizTalk server which ships with a MQSeries adapter, though unless you're using BizTalk currently in your enterprise I would avoid.
The last way you could do this is to program directly against the MQSeries .NET client libraries or via the XMS client.
If you manage to solve the first issue then solving the second one is easy enough. You can expose one way WCF service operations over msmq transport by using the netMsmqBinding (for WCF on both ends), or msmqIntegrationBinding for clients using System.Messaging or native msmq COM libraries.
This in-effect acts as a listener service, with messages being handled by the service operation.
how to get connect with ibm websphere mq by using c#.net
Perhaps you could use the above answer and within that queue consumer app create a "Service Reference" to your WCF service.
We have a logging service that works by pushing into an MSMQ queue and then a persistence service that pulls out of that queue to drop into a database. Both services are WCF. Recently, though the logging service has continued to work without issue, the persistence service has stopped working, and it throws the following error when trying to open:
An error occurred while opening the queue:Generic error code. (-1072824319, 0xc00e0001). 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.
Obviously, this error is less than helpful. I've tried switching the persistence service to use the same app pool as the logging service, creating a new app for the service, restarting MSMQ, and restarting the servers - but no dice. I'm out of ideas, so any suggestions would be greatly appreciated.
Service Binding
Here's the binding on the services:
<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>
It hasn't changed since deployment many moons ago, but it looks like the service hasn't been working for just over a month.
EDIT: Well, reinstalling MSMQ on all servers didn't seem to help (in fact, just seemed to mess up my queue access even more). Groovy.
EDIT2: Even if I switch to netMsmqBinding in place of msmqIntegrationBinding, I get the same error.
EDIT3: If I create the queue local to the server instead of on another server, it works. So something about going to the other server is the issue. Restarting DTC doesn't resolve.
EDIT4: I can use a queue on another server, just not the MSMQ server. So it must be something with the connection to the MSMQ server (or the MSMQ server itself).
EDIT5: Ports 1801, 135, 2103, and 2105 are all open between the service server and the queue server.
EDIT6: DTCPing comes back with successes.
I want to test out the possibility of queuing message on remote clients who may or may not be connected, those clients when connected will push the messages sent to an msmq over the internet that is hosted in IIS 6.
Now, I setup MSMQ on the win server2003 hosting IIS. After I did this "MSMQ" shows up in the IIS default web site.
Ok, then I added a new transactional private queue through computer management-> message queuing.
From there all I want to do is see messages stack up, I'll deal with those after this works.
Now, I made a client app that has the following code:
using (var contract = new HttpMsmqBridgeProxy())
{
var valueToSend = 2456;
contract.TestFunction(valueToSend);
Console.WriteLine("value sent: " + valueToSend + "\r\n");
}
Here's the app.config of this client:
<configuration>
<system.serviceModel>
<client>
<endpoint
address="net.msmq://**.**.***.228/private/MarksTestHttpQueue"
binding="netMsmqBinding"
bindingConfiguration="srmpBinding"
contract="HttpMsmqBridgeLibrary.IHttpMsmqBridgeContract">
</endpoint>
</client>
<bindings>
<netMsmqBinding>
<binding name="srmpBinding"
queueTransferProtocol="Srmp">
<security mode="None"/>
</binding>
</netMsmqBinding>
</bindings>
</system.serviceModel>
</configuration>
The IP is my public facing IP that works, I can host a wcf service or webpage just fine. I followed this guide somewhat for using srmpBinding.
http://msdn.microsoft.com/en-us/library/aa395217.aspx
So, in short what happens when I run the app is it succeeds, tells me it was sent, I go into Message Queue of my client and see that a new queue has shown up in Outgoing folder called:
Direct:http://..*.228/msmq/private$/MarksTestHttpQueue
there is no outgoing messages waiting in this queue so I assume the message was sent.
When I look at my msmq now on the winserver2003 there are no arrived queued messages waiting.
ETA: I can send messages to a non-transactional queue using the classic MessageQueue implimintation:
var queue = new MessageQueue("FormatName:DIRECT=http://**.**.***.228/msmq/private$/nonTransQueue");
System.Messaging.Message Msg;
Msg = new System.Messaging.Message();
Msg.Formatter = new ActiveXMessageFormatter();
Msg.Body = "Testing";
queue.Send(Msg);
The messages show up (after altering the mapping file in the system32/msmq/mapping directory) just fine. I'm wondering if because it's IIS6 I won't be able to send using the net.msmq binding.
You are correct in that your WCF service hosted in IIS6 won't be able to process the messages. This is because IIS6 doesn't use WAS which instantiates processes for non-http requests. But I think that this comes after everything you're doing in the workflow. I would expect
you run your client, pushing the message to the remote queue
the message appears in the remote queue
your WCF service does not pickup the message because it's hosted in IIS6, so you are left with a message in the remote queue.
I don't believe that IIS is involved at all up until the point where it wouldn't be working anyway.
A simple test for this is to self host your service on the server, e.g. run it in a console app. It will be able to accept MSMQ messages just as IIS7 would, and will remove that as a potential problem from your rig.
You might also want to test whether you can push a message directly from the client to a transactional queue on the server. If you're having problems sending messages to transactional queues on other machines then you can possibly check the MSDTC log. I don't envy having to delve into there.
I'm trying to get IIS6 to work reliably with a WCF service I have hosted in a separate Windows Service application on the same machine. Users connect to IIS via some HTTP exposed services, which is working fine, and then IIS needs to get some information from the Windows service to put in the HTTP response. I also need a callback channel between the Windows Service and IIS.
After a lot of effort I got it working with a netTcpBinding and everything would be rosey for 5 or 10 minutes but after that IIS would report the WCF channel as being faulted and then clam up and stop processing any requests until the worker process got recycled and the whole thing repeated.
I've been trying to swap to a netNamedPipeBinding but IIS refuses or is refused access to the pipe with an "There was no endpoint listening at net.pipe://localhost/mypipename" error. I can connect to the pipe fine from a console app.
So my question is has anyone got either of those two bindings working with IIS as a client or have any other approaches?
We are using IIS 7 hosting about 20 services with the net.tcp and net.pipe bindings and it's working fine.
Your problem with the pipe looks like a misconfiguration to me. If it helps, this is how we have them configured:
Server:
<endpoint address ="" binding="fooBinding"
contract="Bla.IBlaAPI"
bindingConfiguration="BlaAPI.BindingConfig">
Binding config:
<binding name="BlaAPI.BindingConfig"
receiveTimeout = "10:50:00"
sendTimeout = "10:50:00"
maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647"
maxBufferPoolSize="2147483647"
transactionFlow="false">
<readerQuotas maxDepth="32"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="8192"
maxNameTableCharCount="2147483647" />
<security mode="None"/>
</binding>
Note that we are using long timeouts and have really high quotas for message size and etc. because we are passing some big chunks of data through this service. You can adjust for your own needs. We have the security set to "none" because the service is only being contacted from the local machine which is secured. Again, your mileage may vary.
Client:
<endpoint name="Bla.Bindings.BlaAPI" address="net.pipe://localhost/bla/IBlaAPI.svc"
behaviorConfiguration="BlaAPI.ServiceBehavior"
binding="netNamedPipeBinding" bindingConfiguration="BlaAPI.BindingConfig"
contract="Bla.IBlaAPI" />
About the Faulted state problem, please note that if an unhandled exception occurs during execution of the service code, the service instance will remain in Faulted state until it is closed properly. To avoid this, either handle exceptions at service top-level or use, for example, Enterprise Library Excexption Handling blocks.
Re NetNamedPipeBinding and "There was no endpoint listening at net.pipe://localhost/mypipename"
Is your web application impersonating its users? The above error is what you get if you try to access a WCF service via the named pipe binding, in a security context whose logon token has membership of NETWORK USERS. The WCF client-side channel stack doesn't distinguish between access denied errors and "not found" errors, when it attempts to read the shared memory object created by the service to publish the name of the pipe in use. (See http://blogs.charteris.com/blogs/chrisdi/archive/2008/05.aspx etc)
Impersonation tokens in an IIS application will always have NETWORK USERS membership.
Can you show me the code you use to dispose of the wcf client proxy?
Never use 'using' on a wcf proxy, as it will not dispose correctly every time. This can possibly lead to the faulted state.
I am building a WCF service interface for an existing Windows service process. The purpose of the WCF interface is to provide an "Command Channel" to implement an administrative capability for the Windows Service. There are several OperationContract methods defined that are intended to extract information from and control the behaviour of the Windows service far beyond the Start/Stop/Pause capability of the Services applet.
This WCF service is intended to be part of the existing process. As such, running the WCF service in IIS or ServiceHost is not an option.
My problem is that although the ServiceHost does not throw an error on Open(), I cannot get "WCF Test Client" (or anyting else) to find the service.
This is my first WCF Service, and have had trouble finding examples or patterns that fit what I am trying to do. So I have no illusions and would not be suprised if I did many things wrong. Also, not that I have 'portSharingBinding=false'. I did have that on but it was throwing an error that pointed to another service that I do not wish to run.
Is port sharing required?
Config information:
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="PortBinding" portSharingEnabled="false" />
</netTcpBinding>
</bindings>
<services>
<service name="NameChanged.ServiceManager.CommandService">
<endpoint address="net.tcp://localhost"
binding="netTcpBinding"
bindingConfiguration="PortBinding"
name="ServiceManagerCommandChannel"
contract="NameChanged.ServiceManager.ICommandService" />
</service>
</services>
</system.serviceModel>
I also tried the no config route using the following code:
ServiceHost host = new ServiceHost(typeof(CommandService)))
host.AddServiceEndpoint(typeof(ICommandService),
new NetTcpBinding(), "net.tcp://localhost:8000");
host.Open();
Also, no error on the Open(). But, no success connecting to the service.
Thanks for your time,
Jim
I can only speak to the WCF Test Client, but it is looking for the metadata for your service so it can generate a proxy for it. From the above configuration, it does not appear that you are exposing a metadata exchange endpoint. Take a look at this link for more info:
http://weblogs.asp.net/fabio/archive/2009/02/28/net-tcp-mex-endpoints-and-portsharing-in-wcf.aspx
You can access your service without using exposed metatdata to generate a proxy, but it will require you to manually create channels to do so:
http://msdn.microsoft.com/en-us/library/ms734681.aspx