如果你在使用ADO.NET Data Service做应用开发,那么有时候你可能会遇到如下的情况,尤其是你传输的数据量比较大的情况下,例如要上传或者下载一个比较大的文件时。
System.Net.WebException was unhandled by user code
Message=The underlying connection was closed: An unexpected error occurred on a receive.
Source=System
StackTrace:
at System.Net.HttpWebRequest.GetResponse()
at System.Data.Services.Client.DataServiceContext.SaveResult.BatchRequest(Boolean replaceOnUpdate)
at System.Data.Services.Client.DataServiceContext.SaveChanges(SaveChangesOptions options)
at System.Data.Services.Client.DataServiceContext.SaveChanges()
at System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e)
at System.Windows.Forms.ToolStripMenuItem.OnClick(EventArgs e)
at System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e)
at System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e)
at System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met)
at System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met)
at System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea)
at System.Windows.Forms.ToolStripDropDown.OnMouseUp(MouseEventArgs mea)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ToolStrip.WndProc(Message& m)
at System.Windows.Forms.ToolStripDropDown.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
InnerException: System.IO.IOException
Message=Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
Source=System
StackTrace:
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead)
InnerException: System.Net.Sockets.SocketException
Message=An existing connection was forcibly closed by the remote host
Source=System
ErrorCode=10054
NativeErrorCode=10054
StackTrace:
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
InnerException:
如果你无法看到如上的错误消息,那么你需要在服务里面开启一个选项
public static void InitializeService(DataServiceConfiguration config) { // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc. // Examples: config.SetEntitySetAccessRule("*", EntitySetRights.All); config.SetServiceOperationAccessRule("*", ServiceOperationRights.All); config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2; config.UseVerboseErrors = true; }
当然,其实即便你看到了如上的错误消息,估计你也是一头雾水。事实上,上面的错误消息中并没有告诉你问题的真相。(所以我才要写这篇文章的嘛,呵呵)
出现这个问题到底是什么原因呢?
了解了如上的原因,我们就可以设法来解决它
首先,设置WCF的最大消息数据大小为10MB(这里只是举例,你可以根据需要设置为你希望的大小)
<system.serviceModel> <bindings> <webHttpBinding> <binding name="my" maxReceivedMessageSize="10485760"></binding> <!--最大传输数据量为10MB:10*1024*1024--> </webHttpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name=""> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="false" /> </behavior> </serviceBehaviors> </behaviors> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> <services> <service name="Web.AdministrationService"> <endpoint address="" binding="wsHttpBinding" contract="Web.IAdministrationService"></endpoint> </service> <service name="Web.MyDataService"> <endpoint address="" binding="webHttpBinding" bindingConfiguration="my" contract="System.Data.Services.IRequestHandler"></endpoint> </service> </services> </system.serviceModel>
【注意】大家可以看到,ADO.NET Data Service所使用的binding是webHttpBinding,它的contract是System.Data.Service.IRequestHandler
【注意】这里的maxReceivedMessageSize单位是Byte,所以是10*1024*1024
接下来,我们还需要设置网站级别处理请求的最大长度
<httpRuntime maxRequestLength="10240"/>
【注意】这个参数的单位是KB,所以是10*1024即可(关于单位不统一这一点,我是颇有微词的,很多地方单位都不一样,让你不得不记住那么多东西,例如同样的问题还存在于设置timeout的地方,这里就不多说了)
完成上面两个设置之后,再次运行程序,就不会遇到错误了。然后,整个世界清静了……