I have a WCF service that authenticates via Azure ACS , it works beautifully except that when I upload large files to it, I get "(413) Request Entity Too Large"
So clearly I need to increase MaxReceivedMessageSize
, however, my binding type isn't a WSHttpBinding
but a IssuedTokenWSTrustBinding
so doesn't expose this property and I guess I don't fully understand how the HTTP bindings are created in the code below. Is it possible to configure MaxReceivedMessageSize on my bindings somehow?
public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
{
string acsUsernameEndpoint = String.Format("https://{0}.{1}/v2/wstrust/13/username", ACSServiceNamespace, AcsHostUrl);
ServiceHost rpHost = new ServiceHost(typeof(DataTransferService));
rpHost.Credentials.ServiceCertificate.Certificate = GetServiceCertificateWithPrivateKey();
rpHost.AddServiceEndpoint(typeof(IUploadService),
Bindings.CreateServiceBinding(acsUsernameEndpoint),
new Uri(ServiceAddress));
// Windows Identity Foundation token handlers can pick up the relevant settings.
ServiceConfiguration serviceConfiguration = new ServiceConfiguration();
// FederatedServiceCredentials.ConfigureServiceHost etc...
return rpHost;
}
public static class Bindings
{
public static Binding CreateServiceBinding(string acsUsernameEndpoint)
{
return new IssuedTokenWSTrustBinding(CreateAcsUsernameBinding(), new EndpointAddress(acsUsernameEndpoint));
}
public static Binding CreateAcsUsernameBinding()
{
return new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential);
}
}
Solved! As I'm not explicitly defining my endpoints it should be possible to set ReaderQuotas
and MaxReceivedMessageSize
etc on the 'default' endpoints with .Net 4+ by not naming them, this didn't work.
In the end I managed to change the ReaderQuotas
and MaxReceivedMessageSize
on the binding by creating a new Binding class that overrides CreateBindingElements()
, this new class takes the binding by the IssuedTokenWSTrustBinding
and calls its CreateBindingElements()
to create a clone of its binding components, this then allows me to tweak the settings. I'm left with a completely code-based WCF configuration, not sure I like the .clone() - there might be a more eloquent solution.
private class LargeTransportBinding : Binding
{
Binding originalBinding;
public LargeTransportBinding(Binding sourceBinding)
{
originalBinding = sourceBinding;
}
public override BindingElementCollection CreateBindingElements()
{
// Copy
BindingElementCollection modifiedBindingElementCollection = originalBinding.CreateBindingElements().Clone();
// Tweak Reader Quoters and max buffer sizes
TextMessageEncodingBindingElement encoding = (TextMessageEncodingBindingElement)modifiedBindingElementCollection[1];
encoding.ReaderQuotas.MaxArrayLength = int.MaxValue;
encoding.ReaderQuotas.MaxBytesPerRead = int.MaxValue;
encoding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
HttpTransportBindingElement transport = (HttpTransportBindingElement)modifiedBindingElementCollection[2];
transport.MaxBufferPoolSize = int.MaxValue;
transport.MaxBufferSize = int.MaxValue;
transport.MaxReceivedMessageSize = int.MaxValue;
return modifiedBindingElementCollection;
}
public override string Scheme
{
get { return originalBinding.Scheme; }
}
}
and calling it as follows:
var binding = Bindings.CreateServiceBinding(acsUsernameEndpoint);
rpHost.AddServiceEndpoint(typeof(IUploadService),
new LargeTransportBinding(binding),
new Uri(ServiceAddress));
Remembering to reduce the Int.MaxValue to something more realistic to reduce the chance of a DoS attack. I hope this saves somebody the many days I had to spend trawling the internet to solve this.
For IIS 7, this is also required in the web.config:
<system.web>
<httpRuntime maxRequestLength="10240" />
</system.web>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.