I recently discovered a problem when using WCF in a self-hosted setup that I had never encountered before:
I was using the following binding syntax in my module:
this.Bind<IMyService, MyServiceImpl>();
As it turned out, this was causing a strange "Object reference not set to instance of an object". Changing the syntax to :
this.Bind<IMyService>().To<MyServiceImpl>().InTransientScope();
... solved the problem.
Showing posts with label wcf. Show all posts
Showing posts with label wcf. Show all posts
Wednesday, October 18, 2017
Using Ninject in a Self-Hosted environment, e.g. a Windows Service
Windows Services are a great way to host WCF, typically in scenarios where on-premise services are a requirement. As Dependency Injection becomes a standard practice in large scale systems, it can be hard to choose the right DI container. One of my personal favourites in Ninject because of its (typical) ease of configuration. Some benchmarks will show that Ninject isn't the fastest container out there in terms of constructing objects, but in practical use I've never once found that to be a problem.
The following example shows a function that can be used in a Windows Service for setting up Ninject to create ServiceHost instances in a self-hosting scenario:
private static NinjectServiceHost CreateServiceHost(IKernel standardKernel, Type serviceType) { if (standardKernel == null) { throw new ArgumentNullException("standardKernel"); } if (serviceType == null) { throw new ArgumentNullException("serviceType"); } NinjectServiceHost ninjectServiceHost = new NinjectServiceHost( serviceBehavior: new NinjectServiceBehavior( instanceProviderFactory: type => new NinjectInstanceProvider(type, standardKernel), requestScopeCleanUp: new WcfRequestScopeCleanup(true) ), serviceType: serviceType ); return ninjectServiceHost; }
This function will be good enough to boot strap your services in your Windows ServiceBase
implementation in the vast majority of cases. You need only pass in your pre-configured
IKernel instance and the Type of the WCF Service implementation.
Wednesday, November 09, 2016
Solving "System.Net.WebException: The remote server returned an error: (417) Expectation Failed" with a WCF service
I recently started getting the following error message when trying to connect to a web service we had put on an Azure VM running behind an Azure load balancer:
System.ServiceModel.ProtocolException: The remote server returned an unexpected response: (417) Expectation Failed. ---> System.Net.WebException: The remote server returned an error: (417) Expectation Failed.
It turns out the fix was to put the following element in my <configuration> :
<system.net>
<settings>
<!-- This is required when running in Azure VMs behind an Azure load balancer -->
<servicePointManager expect100Continue="true" />
</settings>
</system.net>
System.ServiceModel.ProtocolException: The remote server returned an unexpected response: (417) Expectation Failed. ---> System.Net.WebException: The remote server returned an error: (417) Expectation Failed.
It turns out the fix was to put the following element in my <configuration> :
<system.net>
<settings>
<!-- This is required when running in Azure VMs behind an Azure load balancer -->
<servicePointManager expect100Continue="true" />
</settings>
</system.net>
Solving "System.Net.WebException: The remote server returned an error: (417) Expectation Failed" with a WCF service
I recently started getting the following error message when trying to connect to a web service we had put on an Azure VM running behind an Azure load balancer:
System.ServiceModel.ProtocolException: The remote server returned an unexpected response: (417) Expectation Failed. ---> System.Net.WebException: The remote server returned an error: (417) Expectation Failed.
It turns out the fix was to put the following element in my <configuration> :
<system.net>
<settings>
<!-- This is required when running in Azure VMs behind an Azure load balancer -->
<servicePointManager expect100Continue="true" />
</settings>
</system.net>
System.ServiceModel.ProtocolException: The remote server returned an unexpected response: (417) Expectation Failed. ---> System.Net.WebException: The remote server returned an error: (417) Expectation Failed.
It turns out the fix was to put the following element in my <configuration> :
<system.net>
<settings>
<!-- This is required when running in Azure VMs behind an Azure load balancer -->
<servicePointManager expect100Continue="true" />
</settings>
</system.net>
Tuesday, September 06, 2016
Solving "m_safeCertContext is an invalid handle."
I've recently been trying to get an application working in Azure App Service that acts as a client who calls out to another service via WCF with TransportWithMessageCredential mode for security and Certificate mode for authentication. I've been getting the following error:
m_safeCertContext is an invalid handle.
According to this blog post, this error gets thrown when the certificate isn't correctly imported or has incorrect trust (for any of many possible reasons). Some of those reasons can include incorrect passwords, but there are others as well, like what I was encountering: in Azure App Service, there's no local user signed on when your application is running. Because of that, you run afoul of a subtle issue with managing certificates: all of the constructors, by default, use the user certificate store to temporarily store the PrivateKey of any loaded X509Certificate2 objects. Therefore, on an Azure App Service application, unless you use the new X509Certificate2(certBytes, passwordString, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable) constructor with the MachineKeySet | Exportable flags, your certificate will not be correctly read and will SILENTLY FAIL!!
m_safeCertContext is an invalid handle.
According to this blog post, this error gets thrown when the certificate isn't correctly imported or has incorrect trust (for any of many possible reasons). Some of those reasons can include incorrect passwords, but there are others as well, like what I was encountering: in Azure App Service, there's no local user signed on when your application is running. Because of that, you run afoul of a subtle issue with managing certificates: all of the constructors, by default, use the user certificate store to temporarily store the PrivateKey of any loaded X509Certificate2 objects. Therefore, on an Azure App Service application, unless you use the new X509Certificate2(certBytes, passwordString, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable) constructor with the MachineKeySet | Exportable flags, your certificate will not be correctly read and will SILENTLY FAIL!!
Friday, September 02, 2016
Solving 'The remote certificate is invalid according to the validation procedure' with WCF channels
This typically happens most often (when using certificates) when the certificate Common Name (CN) doesn't match the DNS host name of the server.
Solving "Binding validation failed because the binding's MsmqAuthenticationMode property is set to WindowsDomain but MSMQ is installed with Active Directory integration disabled"
I've been trying to set up remote reads from an MSMQ queue to a WCF service hosted on another machine. I seem to have all my application settings correct, but I'm being screwed over by machine-level configuration on the service machine: the service machine won't run in Active Directory mode, no matter what I do.
After searching for the problem, I found this page on John Breakwell's MSDN blog. It describes the problem: essentially there's a legacy msmq object left around when you install MSMQ Server and Active Directory Integration features together in the same transaction. Here's how you **actually** fix the problem:
After searching for the problem, I found this page on John Breakwell's MSDN blog. It describes the problem: essentially there's a legacy msmq object left around when you install MSMQ Server and Active Directory Integration features together in the same transaction. Here's how you **actually** fix the problem:
- Uninstall all of the MSMQ features.
- Execute this PowerShell command (or one similar to it) to actually delete the Active Directory object described in the article (which doesn't go into nearly enough detail on this point): get-adobject -filter “name -eq ‘msmq'” | Where { $_.DistinguishedName -eq ‘CN=msmq,CN=MyAffectedServerNameHere,OU=Web Servers,OU=Member Servers,DC=MyDomainNameHere,DC=Network,DC=ads’} | Remove-ADObject
- Reinstall **just** MSMQ server, then reboot your machine.
- Reinstall **just** MSMQ active directory integration, then reboot your machine.
You should now be good to go.
Labels:
activedirectory,
fix,
fuckyeahfinally,
mode,
msmq,
service,
wcf,
workgroup
Solving "Binding validation failed because the binding's MsmqAuthenticationMode property is set to WindowsDomain but MSMQ is installed with Active Directory integration disabled"
I've been trying to set up remote reads from an MSMQ queue to a WCF service hosted on another machine. I seem to have all my application settings correct, but I'm being screwed over by machine-level configuration on the service machine: the service machine won't run in Active Directory mode, no matter what I do.
After searching for the problem, I found this page on John Breakwell's MSDN blog. It describes the problem: essentially there's a legacy msmq object left around when you install MSMQ Server and Active Directory Integration features together in the same transaction. Here's how you **actually** fix the problem:
After searching for the problem, I found this page on John Breakwell's MSDN blog. It describes the problem: essentially there's a legacy msmq object left around when you install MSMQ Server and Active Directory Integration features together in the same transaction. Here's how you **actually** fix the problem:
- Uninstall all of the MSMQ features.
- Execute this PowerShell command (or one similar to it) to actually delete the Active Directory object described in the article (which doesn't go into nearly enough detail on this point): get-adobject -filter “name -eq ‘msmq'” | Where { $_.DistinguishedName -eq ‘CN=msmq,CN=MyAffectedServerNameHere,OU=Web Servers,OU=Member Servers,DC=MyDomainNameHere,DC=Network,DC=ads’} | Remove-ADObject
- Reinstall **just** MSMQ server, then reboot your machine.
- Reinstall **just** MSMQ active directory integration, then reboot your machine.
You should now be good to go.
Labels:
activedirectory,
fix,
fuckyeahfinally,
mode,
msmq,
service,
wcf,
workgroup
Wednesday, August 31, 2016
MSMQ, WCF and IIS: Getting them to play nice: The extras, Part I
I've recently been trying to set up queued publishing of data in my company within our internal applications so that we can publish that data out to other applications running in our hybrid cloud with Azure. To move the data around on-premise, I've been working off of the advice given to me by some very knowledgeable people in the IT space, and using architectural design patterns that have been proven to work (though not by me). To implement our new data-publishing architecture, I decided to leverage components I already had at my disposal and use WCF with MSMQ bindings to deal with unreliable connections from some of our remote sites. To help me get started, I began following the series of articles published here on MSDN by Tom Hollander. I was able to get past Part 1 of the tutorial without problem. I even needed the same architecture: a queued message client publishing to a service, via a queue hosted on a 3rd party system.
Part 2 however, securing the queue, proved to be a little bit harder, to the point where I needed to go to stackoverflow.com for help and posted this question. In the question, I kept running into an error when I tried to enable Transport security along with ActiveDirectory support. When I didn't enable ActiveDirectory support, I got a different error, with the code 0xC00E0030. Looking on the page for MSMQ queueing error codes on MSDN, I found that this error means that there was corrupted security data, somewhere. Here's what I had to do to resolve it:
Part 2 however, securing the queue, proved to be a little bit harder, to the point where I needed to go to stackoverflow.com for help and posted this question. In the question, I kept running into an error when I tried to enable Transport security along with ActiveDirectory support. When I didn't enable ActiveDirectory support, I got a different error, with the code 0xC00E0030. Looking on the page for MSMQ queueing error codes on MSDN, I found that this error means that there was corrupted security data, somewhere. Here's what I had to do to resolve it:
- In the EndpointAddress for my WCF binding, I had to add an extra parameter to the constructor for the EndpointIdentity of my binding: New EndpointAddress(queueUri, EndpointIdentity.CreateDnsIdentity(queueUri.Host))
- I had to gain access to the server where I was hosting my MSMQ Server, and gain full access to the Server itself: Computer Management -> Message Queueing -> Right-click -> Properties -> Security tab -> [my name] -> "Full Control"
- I had to re-register my own Internal Certificate for MSMQ on the server: [previous steps] -> User Certificate tab -> Internal Certificate section -> Renew....
After cleaning up the certificate and adding the endpoint, I was good to go, and I could now authenticate and send messages to the MSMQ server.
To be fair to Tom Hollander, he did say that there would be some extra specifics to getting Authentication working, and I guess these were mine. I have to send him a lot of thanks for going through what he did AND recording and publishing the steps. People like him make the world a better place.
Wednesday, April 08, 2015
Removing a certificate binding from a port in Windows
As many people don't know, in Windows certificates can be bound to ports for securing content transferred over those ports. IIS happens to be particularly negatively affected by this if another program has a certificate bound to a port that you want to use, e.g. 443 for serving web pages.
Use the information at the following page to find the certificate binding and delete it :
https://msdn.microsoft.com/en-us/library/ms733791(v=vs.110).aspx
The short version:
Find the port: netsh http show sslcert | grep -C 5 443
This command will show all the SSL certificates that are bound to ports on your machine.
Delete the port: netsh http delete sslcert ipport=0.0.0.0:443
This should help deal with some of the more annoying (and less verbose) errors when doing things like trying to configure WCF services to use SSL.
Use the information at the following page to find the certificate binding and delete it :
https://msdn.microsoft.com/en-us/library/ms733791(v=vs.110).aspx
The short version:
Find the port: netsh http show sslcert | grep -C 5 443
This command will show all the SSL certificates that are bound to ports on your machine.
Delete the port: netsh http delete sslcert ipport=0.0.0.0:443
This should help deal with some of the more annoying (and less verbose) errors when doing things like trying to configure WCF services to use SSL.
Friday, March 20, 2015
Creating ChannelFactory instances that are configured with Custom credentials in WCF
Check this out: Setting Client Credentials
I just discovered this wonderful piece of information on how to properly create ChannelFactory instances in WCF for clients.
I just discovered this wonderful piece of information on how to properly create ChannelFactory instances in WCF for clients.
Sunday, March 15, 2015
Using Ninject in an IIS-hosted environment to create a WCF service instance that's in a shared assembly (i.e. not the web application assembly)
Recently I wanted to create several WCF services for some of our internal applications and host these services in multiple different servers. There'd be no difference in the code between the locations where they'd be hosted. In order to avoid code duplication, I wanted to make these WCF services common and then just host them in the IIS applications. However, it's not as simple as creating a new (shared) assembly, creating the WCF service in that assembly and then sharing it between the different services. When I tried this, I ran into the problem where even though I specified the service in the config section:
After adding the .svc file and using the path to it in the system.serviceModel configuration in the configuration file, everything worked perfectly.
<system.serviceModel>....
</system.serviceModel>
... it still wouldn't find my service and load it (I'm using Ninject as a dependency injection container for my WCF services). They key to getting the shared services to be found and loaded properly was to create a .svc file in each of the services where the WCF services were shared, and it looked something like this in each case:
<%@ ServiceHost Language="C#" Debug="false" Service="MyWcfSharedServices.MySharedWebService" Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory" %>
After adding the .svc file and using the path to it in the system.serviceModel configuration in the configuration file, everything worked perfectly.
Thursday, January 22, 2015
Implementing a WCF service on an Active Directory domain using a ServiceHost in a Windows Service with Windows authentication and a non-system user service account
So, as it turns out, when you want to implement a WCF service on an Active Directory domain using a ServiceHost in a Windows Service with Windows authentication and a non-system user service account, you have to jump through a few hoops for the configuration. I kept getting the error message "A call to SSPI failed. see inner exception". The inner exception is "The target principal name is incorrect.". Like many other people, I kept thinking it had to do with authentication of the *client*. As it turns out, like those other people, I was wrong. It was to do with *verification of the service account running the service*. This is presumably because the *service user is a domain user service account*. To get this scenario working, you have to specify the name of the service user account as the 'userPrincipalName' in the 'identity' element of the 'endpoint' element for your service, like so:
<configuration>Now you'll get proper connections and authentication via Windows.
<system.serviceModel>
<services>
<service name="MyProject.MyService">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:12345/MyService"/>
</baseAddresses>
</host>
<endpoint name="MyServiceTcpEndpoint"
address=""
binding="netTcpBinding"
bindingConfiguration="MyServiceTcpBinding"
contract="MyProject.IMyService">
<identity>
<userPrincipalName value="MyDomainName\MyServiceUserName"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="MyServiceTcpBinding"
transferMode="Buffered"
maxReceivedMessageSize="65535">
<security mode="Transport">
<!-- Use Windows authentication to ensure that we at least have authentication if not encryption -->
<transport clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
</configuration>
Wednesday, May 08, 2013
Journey to robust web services: installing a WCF 4.0 application on IIS 6.0
Due to budget and other constraints, I'm unable to get my hands on the latest and greatest software for running a WCF application I've been working on, so I'm forced to use what my company's got: Windows Server 2003 and IIS 6.0. Suffice it to say that working with these old bits of software are less than ideal. However, I'm stuck with it. So, moving forward, here's some of the things I found while working on the application:
- There's no easy way to set certain items in the registry for the Network Service user. (Sorry, for various reasons, I can't elaborate on that statement.)
- Due to (1), I've decided to run my application as a custom normal (non-Administrator) user that I've created. However in order to use this user with IIS and its applications, certain steps must be taken.
Using a custom user to run an IIS 6.0 application
The following are pre-requisites in order to be able to use a custom user to run an IIS 6.0 application:
- The user must have already been created and should have absolutely the least number of privileges possible.
- Thanks to this question on Stack Overflow, the following must also have the following:
- The "Log on as a service" right (Start -> Control Panel -> Administrative Tools -> Local Security Policy -> Local Policies -> User Rights Assignment -> Log on as a service)
- "Access this computer from the network" (similar location as in the step above)
- "Deny logon locally"
- "Log on as a batch job"
- "Read & Execute", "List Folder Contents" and "Read" access to the file system that underpins the web site/application
- Thanks to this troubleshooting article on MSDN, I also found out that the user must be part of the "IIS_WPG" group.
Monday, May 06, 2013
Journey to robust web services: apparently we shouldn't use 'using'
I recently stumbled across an article stating why we shouldn't use the 'using' keyword with WCF services, and I found it rather interesting. I'd have to re-read it, and re-evaluate it, before I use it but you can read the blog post on the original site.
Journey to robust webservices: kickstarting use of certificates phase II: using certificates for client authentication
There are a number of means of authenticating users, and one of the most secure is via a certificate. This article on CodeProject provides a start. Unfortunately, the article doesn't really mention a few things:
- Depending on how you ran the tools, you may have inadvertently run the commands it gives you as an administrator. I ran them in a console that I already had open that was running as administrator, so they were installed as administrator, and I also happened to have been running in Visual Studio as an administrator at the time, so everything happily worked. Then when I rebooted my machine this morning and was running as a normal user, nothing worked, and I wasted over an hour trying to figure out why. That was why. Regardless of how you generated and installed the keys, you should go and explicitly grant permissions on the key to the users you want to have access to them. On the Microsoft website, there is a bundle of WCF samples (which you can find here). Included in the samples is a tool called FindPrivateKey. Download the samples, compile the program, and use it to find the key that you just generated. You'll need a command similar to the following : "C:\Samples\WCFWFCardSpace\WCF\Tools\FindPrivateKey\CS\bin\FindPrivateKey.exe My LocalMachine -t "28 ce e3 2c 7e 05 3a 97 a0 b4 92 fd d5 b0 f9 de 0e 4c 2e 4b"" where the value in quotes is the thumbprint of the non-signing (client) key you generated in the instructions from the article. Once it spits out the location of the file, you'll need to go and alter its permissions to allow whatever user your server / client application is running under access to the file.
- Depending on the binding you're using with WCF on the server side, you may need to have a certificate with full chain trust on the IIS server (or other?) in order to use the binding (*cough* basicHttpBinding and any other transport-only security bindings *cough*). With that in mind, after you've generated the certificates in the article, while you're in the certificate manager MMC snap-in, you'll also need to copy (not move) the IIS developer certificate used in IIS to the "Trusted Root Certification Authorities" store.
Journey to robust web services: kick starting use of credentials and certificates for message security, phase I
As any sensible developer of a large scale system knows, security is paramount. Therefore, encryption of sensitive data is an absolute must, encryption of all data is recommended, depending on the field in which you're working. Encryption with WCF is baked in, and is relatively straight forward to setup, though there are a number of important details to which attention must be paid. The steps are somewhat different depending on whether you're using IIS or a self-hosted service (e.g. in a Windows Service).
If you're using a Windows Service, you'll need to perform the following steps to get started:
If you're using a Windows Service, you'll need to perform the following steps to get started:
- Generate a self-signed certificate (which can be done in the Windows Control Panel)
- Configure the port to which you're binding the service with the certificate you've just generated, according to this MSDN article.
- [to be continued]
If you're using IIS, getting started in a development environment is somewhat simpler.
- Generate a self signed certificate with IIS. In most cases, IIS will have a developer certificate already installed that you can use.
- Retrieve the thumbprint of the certificate. You'll need this in order for your application to be able to find it at runtime. WARNING: Don't just copy the thumbprint out of the certificate properties window in IIS, because there are non-printing characters in the text control that will cause you problems when you try to paste the thumbprint into your Web.config file. Write them out by hand.
- There are two methods you can take for making the certificate available to your WCF service:
- Follow the guide here if you want to make the certificate available to your application by code.
- Use the information on this page to create a
element underneath a configuration/system.serviceModel/behaviors/behavior/serviceCredentials element.
Journey to robust web services: debugging services and logging messages
One of the quickest and best ways to debug issues with the services you're developing is to log and trace all activity with WCF along with the messages being sent back and forth. This page on MSDN will provide you with the instructions required to setup logging and tracking for WCF.
Sunday, May 05, 2013
Journey to robust web services: my clients are unable to connect!
I've been testing out some web services I've been working on extensively on my own machine, but the time has finally come where I want to start making clients that aren't running on the same machine. In one case, I have a WCF service running on Windows 7, but the client I want to connect to that service is running on Windows 8 on a separate machine. When I tried to connect, I would get a variety of errors, the most common of which being that the socket on the server was forcibly closed. I Googled around a bit, and the most common cause of this problem that I found was that the server's quota's were being reached and therefore the client was being rejected, however this shouldn't have been the case for me since there was no way my quota's could have been reached. After further research, I found that since I don't want security (yet), I had to apply some settings in order for clients that weren't on my localhost to connect. In order to allow external clients to connect, I had to change the following :
- In my
, I had to change my base address to use the network name of my computer (rather than localhost) in the base address URL. - In the net.tcp and ws2007HttpBindings for my services, I had to go to the the
child element of the elements, and explicitly set mode="None" on those elements, otherwise they may assume some form of security by default depending on the type of the binding.
Now, I did mention above that I don't want to add security (*YET*) being the important qualifier of that statement. Security is of course always paramount, and should always be baked into a product as early as possible. As soon as I get to it, I'll add a post about all the steps required to add security to your WCF clients and services, along with links to the relevant MSDN articles (and any other useful ones that I may find.
Sunday, April 28, 2013
Journey to robust web services: debugging a net.tcp service
I'm creating a net.tcp-based WCF web service for use with my current project, and so far the learning curve hasn't been very shallow. I've just recently learned, thanks to this post on Stack Overflow, that the default ASP.NET application doesn't support the net.tcp protocol, so IIS must be used instead. With that in mind, I've decided to move on to just using the Web Service I'm creating through a Windows Service via a ServiceHost. However, I've now encountered some problems debugging the Windows Service startup. This page on MSDN contains links and instructions on how to debug the startup of a Windows Service. While attempting to install the Debugging tools, I encountered a failure trying to install them as part of the Windows 7 SDK. This page on Stack Overflow had a solution, but it wasn't quite complete. This page had the missing parts.
Subscribe to:
Posts (Atom)