Hay muchas preguntas similares por ahí, pero he probado todas las soluciones en cada una de ellas en vano.Cómo reemplazar WebServiceHostFactory MaxReceivedMessageSize?
Tenemos un servicio web que se inicializa con WebServiceHostFactory, pero si se arrojan más de 64k, obtenemos una '400 Bad Request'. Normalmente, esto se resolvería simplemente aumentando MaxReceivedMessageSize, MaxBufferSize y MaxBufferPoolSize. El problema es que al usar WebServiceHostFactory, Web.Config se ignora por completo. Ningún cambio que realice en la sección de ServiceModel se refleja en el servicio.
Sería bueno abandonar completamente WebServiceHostFactory y configurar el web.config desde cero, pero nuestro servicio no se ejecutará sin él. Uno de los métodos tiene un parámetro de flujo así como algunos otros parámetros de cadenas. Sin la fábrica, obtenemos
System.InvalidOperationException: For request in operation Test to be a stream the operation must have a single parameter whose type is Stream
Por lo tanto, no es una opción eliminar la fábrica. No puedo determinar exactamente qué está haciendo la fábrica que corrige este error, pero pasé 4 días y nunca llegué a ningún lado.
También he intentado anular MaxReceivedMessageSize mediante programación, con algunos ejemplos que he encontrado en todo el lugar:
protected override void OnOpening()
{
base.OnOpening();
foreach (var endpoint in Description.Endpoints)
{
//var binding = endpoint.Binding as WebHttpBinding;
//if (binding != null)
//{
// binding.MaxReceivedMessageSize = 20000000;
// binding.MaxBufferSize = 20000000;
// binding.MaxBufferPoolSize = 20000000;
// binding.ReaderQuotas.MaxArrayLength = 200000000;
// binding.ReaderQuotas.MaxStringContentLength = 200000000;
// binding.ReaderQuotas.MaxDepth = 32;
//}
//var transport = endpoint.Binding.CreateBindingElements().Find<HttpTransportBindingElement>();
//if (transport != null)
//{
// transport.MaxReceivedMessageSize = 20000000;
// transport.MaxBufferPoolSize = 20000000;
//}
var newTransport = new HttpTransportBindingElement();
newTransport.MaxReceivedMessageSize = 20000000;
newTransport.MaxBufferPoolSize = 20000000;
endpoint.Binding.CreateBindingElements().Add(newTransport);
}
}
La primera no funciona como la fábrica crea una customBinding que no puede ser echado a un WebHttpBinding. El segundo no funciona, ya que parece que los elementos de encuadernación son de solo lectura: independientemente de los elementos a los que establezca los elementos, nada cambia, lo que he verificado leyendo los valores después de 'cambiarlos'. El tercero fue un último intento de tratar de lanzar un nuevo elemento de enlace allí, pero, por supuesto, esto también falló.
Ahora estamos completamente perdidos. ¿Cómo podemos hacer que esto funcione? ¡Crees que sería tan simple!
Gracias chicos
Web.Config
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<compilation targetFramework="4.0" />
</system.web>
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="rest" maxReceivedMessageSize="500000000" />
</webHttpBinding>
</bindings>
<services>
<service name="SCAPIService" behaviorConfiguration="ServiceBehaviour">
<endpoint address="" binding="webHttpBinding" bindingConfiguration="rest" contract="ISCAPIService" behaviorConfiguration="web">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
</configuration>
Editar, usando un arreglo sugerido que no ha tenido éxito hasta ahora:
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 ApplyConfiguration()
{
base.ApplyConfiguration();
APIUsers.TestString += "here" + Description.Endpoints.Count.ToString();
foreach (var endpoint in this.Description.Endpoints)
{
var binding = endpoint.Binding;
APIUsers.TestString += binding.GetType().ToString();
if (binding is WebHttpBinding)
{
var web = binding as WebHttpBinding;
web.MaxBufferSize = 2000000;
web.MaxBufferPoolSize = 2000000;
web.MaxReceivedMessageSize = 2000000;
}
var myReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas();
myReaderQuotas.MaxStringContentLength = 2000000;
myReaderQuotas.MaxArrayLength = 2000000;
myReaderQuotas.MaxDepth = 32;
binding.GetType().GetProperty("ReaderQuotas").SetValue(binding, myReaderQuotas, null);
}
}
}
class MyWebServiceHostFactory : WebServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new MyServiceHost(serviceType, baseAddresses);
}
}
Gracias Rajesh. Sin embargo, esto todavía no funciona para mí, por alguna razón no hay puntos finales cuando se llama a ApplyConfiguration, por lo que nunca llega al bucle foreach. Como la fábrica está haciendo toda la creación de la descripción, ¿cómo haría para que cree el punto final antes de que se active ApplyConfiguration? –
Es posible que publique el código de fábrica que tiene para proporcionar más ayuda. – Rajesh
Claro, he actualizado la pregunta con el código. La declaración se ve así: <% @ ServiceHost Language = "C#" Debug = "true" Service = "APINamespace.Service" CodeBehind = "Service.svc.cs" Factory = "WcfService1.MyWebServiceHostFactory"%> En mi código , el APIUsers.TestString se imprime, solo para asegurarse de que este código se esté ejecutando. El resultado fue aquí0 (0 = recuento de puntos finales) –