Calling a Web Service from a Pipeline Extensibility Executable in FAST Search 2010
So you want to call a Web Service (*.asmx) from a custom Pipeline Extensibility executable. You write all of your code, it works when you call it manually from the cmdline, but then when you try it within the content pipeline. it doesn't work. You probably see an error like with the exceptions returned:
Unhandled Exception: System.Runtime.InteropServices.ExternalException: Cannot execute a program. The command being executed w as "C:\Windows\Microsoft.NET\Framework64\v2.0.50727\csc.exe" /noconfig /fullpath s @"D:\FASTSearch\tmp\OICE_3594445B-638D-4C80-B8CC-22D9B7C70775.0\bfid6zql.cmdline".
To understand the problem you have to know about the characters involved:
- Pipeline Sandbox
- Your custom executable
- Serialization
- csc.exe
The issue is not a bug but a feature in the Pipeline Sandbox that only allows executing code to write to the UserProfile's locallow directory. While this may not seem like an issue for a simple executable that just makes a web service call, it is the very web service call that is at the heart of the issue. Specifically the need for the serialization of an object into a xml representation of that object. What occurs during a Web Service call is that the .NET Framework reflects your proxy and creates an assembly that does the serialization and deserialization. In order to do this, it generates a temporary assembly using csc.exe, places that assembly into a temp directory and then binds it to your assembly. Normally this is not an issue, but with the Sandbox feature for Pipeline Extensibility executables in FAST Search, this won't work since the csc.exe call is under the context of the Sandbox. Since the only allowed directory you can write to in the Sandbox is the UserProfile's locallow, when the .NET framework is trying to write to a temp directory, the above error occurs.
Makes sense right? Well the solution is simple and in the end will increase the performance of your application. By using SGen and the XmlSerializerAssembly attribute, you prevent the need for the .NET Framework to generate the temporary assemblies using csc.exe. I added the high level steps below.
- Open a Visual Studio command prompt
- Compile your custom extensibility executable that makes the web service call
- execute SGEN.exe /a:<file name of your assembly> /o:<your project source files directory>
- Add the newly created source files to your visual studio project.
- Add the following attribute: [XmlSerializerAssembly("<your custom pipeline extensibility executable>")]
- Compile
- Test it out
It should be noted only C# files are generated so if you use a different language than you will need to create a seperate C# assembly.
Overall, it is suggested that you use WCF as oppose to Web Services in custom pipeline extensibility executables. The data contract serialization used in WCF does not use the serialization method mentioned above and should not have this issue.