我的VS2008解决方案中有一个名为“Palladium”的 RESTful WCF Web服务作为项目。它通过名为“Palladium.svc”的页面使用 WebServiceHostFactory 实现托管在ASP.Net 3.5 Web应用程序中。
我的服务工作方式类似于解释here的方式,服务可以接收POST以及URITemplate中定义的其他参数。
该服务运作良好,我可以收到发布的信息并使用它
我的问题发生在帖子数据超过65k并且我得到以下错误(使用web.config和Microsoft服务跟踪查看器中的system.diagnostics
获得)。
已超出传入邮件的最大邮件大小限额(65536)。要增加配额,请在相应的绑定元素上使用MaxReceivedMessageSize属性。
由于服务是通过WebServiceHostFactory实现托管的,因此该服务已为工厂设置了默认绑定。我试图通过在web.config文件中提供绑定设置和端点来覆盖这些绑定。但是,当我这样做时,我收到一条错误消息:
System.InvalidOperationException,mscorlib,Version = 2.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089
对于操作中的请求,LogStartingDetails是一个流,操作必须有一个类型为Stream的参数。
LogStartingDetails
是我在RESTful服务中调用的方法。
显然,LogStartingDetails
方法不需要一个类型为Stream
的参数,就像工厂为我创建绑定时服务响应良好(或更多点到点) ,当工厂为我工作时,它没有需要一个参数。
经过大量研究并打了几个砖墙后,我决定创建自己的继承自WebServiceHostFactory
的类,并覆盖一些实现,以便在绑定上指定 MaxReceivedMessageSize 属性。
当我通过调试在工厂类中逐步完成服务创建时,我可以看到传输接收到新的 MaxReceivedMessageSize 和 MaxBufferSize 值,但它们似乎没有做任何事情而且我最终还是得到了同样的The maximum message size quota for incoming messages (65536) has been exceeded.
异常。
以下是我的服务代码示例。如果有人能帮助我弄清楚我在这里做错了什么,我将不胜感激。
Palladium.svc (托管在ASP.Net Web应用程序中)
<%@ ServiceHost Language="C#" Debug="true" Service="CDS.PalladiumService.Palladium" Factory="CDS.PalladiumService.MyWebServiceHostFactory" %>
MyWebServiceHostFactory.cs (在CDS.PalladiumService项目中)
using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Channels;
using System.ServiceModel.Web;
namespace CDS.PalladiumService
{
public class MyServiceHost : WebServiceHost
{
public MyServiceHost()
{
}
public MyServiceHost(object singletonInstance, params Uri[] baseAddresses)
: base(singletonInstance, baseAddresses)
{
}
public MyServiceHost(Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
}
protected override void OnOpening()
{
base.OnOpening();
if (base.Description != null)
{
foreach (var endpoint in base.Description.Endpoints)
{
var transport = endpoint.Binding.CreateBindingElements().Find<TransportBindingElement>();
if (transport != null)
{
transport.MaxReceivedMessageSize = 5242880;
transport.MaxBufferPoolSize = 5242880;
}
}
}
}
}
class MyWebServiceHostFactory : WebServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new MyServiceHost(serviceType, baseAddresses);
}
}
}
IPalladium.cs (在CDS.PalladiumService项目中)
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Web;
namespace CDS.PalladiumService
{
// NOTE: If you change the interface name "IPalladium" here, you must also update the reference to "IPalladium" in Web.config.
[ServiceContract]
public interface IPalladium
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = UriTemplate.LogStartingDetails)]
void LogStartingDetails(string truckId, string palladiumId, Stream postData);
}
}
Palladium.cs (在CDS.PalladiumService项目中)
using System.IO;
using System.ServiceModel.Activation;
namespace CDS.PalladiumService
{
// NOTE: If you change the class name "Palladium" here, you must also update the reference to "Palladium" in Web.config.
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Palladium : IPalladium
{
public void LogStartingDetails(string truckId, string palladiumId, Stream postData)
{
string contents = string.Empty;
using (var reader = new StreamReader(postData))
{
contents = reader.ReadToEnd();
}
StreamWriter sw1 =
File.AppendText(@"C:\log.txt");
sw1.WriteLine(contents);
sw1.WriteLine("");
sw1.Close();
return;
}
}
}
URITemplate.cs (在CDS.PalladiumService项目中)
namespace CDS.PalladiumService
{
public static class UriTemplate
{
public const string LogStartingDetails = "/log-starting/{truckId}/{palladiumId}";
}
}
答案 0 :(得分:3)
我设法通过在我的WebServiceHost的OnOpening方法中的端点绑定上设置以下3个设置来实现此功能:
protected override void OnOpening()
{
base.OnOpening();
foreach (var endpoint in Description.Endpoints)
{
var binding = endpoint.Binding as WebHttpBinding;
if (binding != null)
{
const int fiveMegaBytes = 5242880;
binding.MaxReceivedMessageSize = fiveMegaBytes;
binding.MaxBufferSize = fiveMegaBytes;
binding.MaxBufferPoolSize = fiveMegaBytes;
}
}
}
我需要一个大的缓冲区大小,因为我无法启用流式传输。
答案 1 :(得分:2)
好的,对于那些正在寻找上述问题解决方案的人 - 我只是对我的web.config文件进行了一些更改,并在我的asp.net网站上托管了该服务。
我将我的网络配置的<system.serviceModel>
部分更改为以下内容 - 这允许“大邮件绑定”,其中帖子的最大长度在配置文件的相应部分中指定。
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="largeMessageBinding" maxBufferPoolSize="5242880" maxReceivedMessageSize="5242880" transferMode="Buffered">
<readerQuotas maxStringContentLength="5242880" maxArrayLength="5242880" maxBytesPerRead="5242880" />
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="largePostEndpointBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="CDS.UI.Resources.Services.PalladiumBehavior">
<serviceMetadata httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="CDS.UI.Resources.Services.PalladiumBehavior"
name="CDS.PalladiumService.Palladium">
<endpoint address="" binding="webHttpBinding" behaviorConfiguration="largePostEndpointBehavior"
bindingConfiguration="largeMessageBinding" contract="CDS.PalladiumService.IPalladium" />
</service>
</services>
</system.serviceModel>