大致情形是这样的:
Silverlight 2 beta2 (目前最新的支持 VS2008 中文版的开发包)
WCF (采用 SL2b2 安装后新增的那个模板创建的)
LINQ to SQL (对应 SQL 服务器中的四个表)
使用 DataGrid 控件来显示和编辑 SQL 中的 Component 表, 强大的LINQ帮我创建了一个对应的 Component 类, 查询和显示的过程很顺利.
可是到了更新数据这一步, 却碰上了莫名其妙的 404 错误… 少量可以, 大量数据就会出错.
The remote server returned an unexpected response: (404) Not Found.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 [OperationContract] public List<Component> QueryComponentList (Guid TowerID) { using (var db = new LINQDataContext()) { var linq = from l in db.Component where l.TowerID.Equals(TowerID) orderby l.Section, l.Number select l; return linq.ToList(); } } [OperationContract] public void UpdateComponentList (Guid tid, List<Component> source) { using (var db = new LINQDataContext()) { ... } }
在官方论坛上我看到了N种解释, 总结如下:
跨域安全问题, 也就是传说中的 crossdomain.xml 和 clientaccesspolicy.xml 两个文件. 试试, 虽然我知道不会奏效的.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?xml version="1.0" encoding="utf-8" ?> <access-policy > <cross-domain-access > <policy > <allow-from http-request-headers ="*" > <domain uri ="*" /> </allow-from > <grant-to > <resource path ="/" include-subpaths ="true" /> </grant-to > </policy > </cross-domain-access > </access-policy > <?xml version="1.0"?> <!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"> <cross-domain-policy > <allow-http-request-headers-from domain ="*" headers ="*" /> </cross-domain-policy >
Silverlight 项目中的 ServiceReferences.ClientConfig 文件, 增大 maxBufferSize 和 maxReceivedMessageSize. 我加到了 2147483647, 也就是 2G, 结果不行.
1 <binding name ="BasicHttpBinding_WCF" maxBufferSize ="2147483647" maxReceivedMessageSize ="2147483647" />
网站中的 web.config 文件, 增大若干个 max 开头的属性. 我估计有几项是客户端根本无法识别的 设置了也没用…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <bindings > <basicHttpBinding > <binding name ="BasicHttpBinding_WCF" maxBufferSize ="2147483647" maxReceivedMessageSize ="2147483647" > <readerQuotas maxArrayLength ="2147483647" maxDepth ="2147483647" maxBytesPerRead ="2147483647" maxNameTableCharCount ="2147483647" maxStringContentLength ="2147483647" /> <security mode ="None" /> </binding > </basicHttpBinding > </bindings > <services > <service behaviorConfiguration ="WCFBehavior" name ="WCF" > <endpoint address ="" binding ="basicHttpBinding" bindingConfiguration ="BasicHttpBinding_WCF" contract ="WCF" /> <endpoint address ="mex" binding ="mexHttpBinding" contract ="IMetadataExchange" /> </service > </services >
在 web.config 文件中的 system.web/httpRuntime 节点下, 设置 POST 允许的最大长度, 以kb为单位, 那就是 int.MaxValue/1024=2097151. 早就知道问题不在这…
1 <httpRuntime maxRequestLength ="2097151" />
web.config 中关于 WCF 还有个秘密, 那就是 system.serviceModel/behaviors/serviceBehaviors/behavior/dataContractSerializer
. 天啊, 连这个都有人挖出来啦! 兴奋了几秒钟, 发现还是没搞定!
1 2 3 4 5 6 7 8 9 <behaviors > <serviceBehaviors > <behavior name ="WCFBehavior" > <serviceMetadata httpGetEnabled ="true" /> <serviceDebug includeExceptionDetailInFaults ="false" /> <dataContractSerializer maxItemsInObjectGraph ="2147483647" ignoreExtensionDataObject ="true" /> </behavior > </serviceBehaviors > </behaviors >
仔细回忆到底是哪里出了问题, 我发现当数据少于 176 行时是没有问题的, 只要一超过这个数量, 就会弹出异常, 而且感觉上是在异步传递数据之后立即发生的, 比能够上传成功的 176 行数据响应的还快许多, 更奇怪的是虽然 VS2008 跳出异常, 接收到了 404 错误, 但此时任务管理器的 WebDev.WebServer.EXE 和 sqlserver.exe 都正忙着, 查看 SQL 发现数据也是成功写入了…
那这 404 是哪里来的鬼东西? 无意中直接打开 IE 不经过调试, 结果我也没接收到 404 错误, 真的无奈了, 最后决定死马当活马医. 把上传数据那个函数从 void 类型改成 bool 类型, 让它具备一个布尔型的返回结果, 以确认上传是否成功(之前一直感觉这是多余的).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [OperationContract] public bool UpdateComponentList (Guid tid, List<Component> source) { try { using (var db = new LINQDataContext()) { ... } return true ; } catch (Exception) { return false ; } }
古怪的问题就这样华丽的消失了… 别问我为什么, 我也不知道!