最近一段時間,一直在折騰Mono,折騰Linux。讓我無比痛苦的是Mono下的WCF的坑真的是太多了,這不又遇到了一個莫名其妙的問題。
環境:mono 3.2.1,Jexus 5.4.3,OS CentOS 6.2。
1:定義服務契約
using System.ServiceModel; namespace BugTest.Contract { [ServiceContract(Name = "Calculator", Namespace = "http://www.wcfbugtest.com")] public interface ICalculator { [OperationContract] int Add(int x, int y); } }
2:實現服務
WriteInfo方法主要是為了記錄當時調用Add方法,傳入的X,Y值,也是為了更好的展現這個Bug。
using System; using System.IO; using System.ServiceModel; using System.ServiceModel.Activation; using System.Text; using BugTest.Contract; namespace BugTest.Service { [ServiceBehavior(IncludeExceptionDetailInFaults = true)] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class CalculatorService : ICalculator { public int Add(int x, int y) { WriteInfo(string.Format("x={0},y={1}", x, y)); return x + y; } public void WriteInfo(string logInfo) { var type = Type.GetType("Mono.Runtime"); if (type != null) { string filePath = "/var/www/getextent/Logs/Info.log"; using (var sw = new StreamWriter(filePath, true, Encoding.UTF8)) { sw.Write(logInfo + "\r\n"); sw.Flush(); } } } } }
3:寄宿服務
主要是看Web.config,我的生產環境客戶端使用的是Silverlight,終結點使用的綁定是customBinding,編碼方法采用的是Binary Message Encoding,主要是為了減少服務端與客戶端傳輸消息的大小,能夠稍微的提升性能。此外,要在Mono下跑WCF,要為站點添加一個Global.asax,在Application_Start添加如下代碼:
protected void Application_Start(object sender, EventArgs e) { Environment.SetEnvironmentVariable("MONO_STRICT_MS_COMPLIANT", "yes"); }
詳細的配置如下:
<configuration> <system.web> <compilation debug="true" targetFramework="4.0"/> <customErrors mode="Off"/> <httpRuntime/> </system.web> <system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="ServiceBehavior"> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> </behaviors> <bindings> <customBinding> <binding name="customBinding0" sendTimeout="00:10:00" openTimeout="00:10:00" closeTimeout="00:10:00"> <binaryMessageEncoding/> <httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647"/> </binding> </customBinding> </bindings> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/> <services> <service behaviorConfiguration="ServiceBehavior" name="BugTest.Service.CalculatorService"> <endpoint address="http://192.168.8.141:6060/CalculatorService.svc" binding="customBinding" bindingConfiguration="customBinding0" contract="BugTest.Contract.ICalculator"/> </service> </services> </system.serviceModel> </configuration>
最后發布站點,部署到Linux下面的Jexus Web服務器上。
4:客戶端調用
客戶端,可以使用控制台應用程序,添加服務引用,輸入服務的地址,生成好客戶端的代理文件,及App.config文件。
測試代碼如下:
using System; using MonoClient.ServiceReference; namespace MonoClient { class Program { static void Main(string[] args) { var client = new CalculatorClient(); Console.WriteLine("x + y = {2} where x = {0} and y = {1}", -1, 2, client.Add(-1, 2)); client.Close(); Console.Read(); } } }
執行的結果如下:
Log的內容如下:
問題出現了,客戶端傳入的-1,在服務端莫名其妙地變成了255了。A bug ???
在windows下,使用IIS寄宿服務,是不會有問題。
此外如果使用baseHttpBinding,在Mono下WCF也是不會有問題的。即將配置按下面的方式修改:
<system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="ServiceBehavior"> <serviceMetadata httpGetEnabled="true"/> </behavior> </serviceBehaviors> </behaviors> <services> <service name="BugTest.Service.CalculatorService" behaviorConfiguration="ServiceBehavior"> <endpoint binding="basicHttpBinding" contract="BugTest.Contract.ICalculator"/> </service> </services> </system.serviceModel>
問題出在哪里呢? 是binaryMessageEncoding的問題嗎?