Trabajando con los servicios de WCF me tope con la siguiente excepción CommunicationException. Descubrí que la configuración del documento XML que es devuelto o generado por mi servicio tiene un máximo de 65536 algo así como 5mb que en realidad deberían de ser suficientes para enviar o recibir información a través de los servicios.
pero en mi caso no era así. Así que me puse en la tarea de investigar como debía de obviar esto encontrando lo siguiente en el MSDN:
Propiedad MaxBufferSize – (Desde MSDN) Obtiene o establece el tamaño máximo del búfer a usar. Para los mensajes este valor es el mismo que MaxReceivedMessageSize . Para los mensajes transmitidos, este valor es el tamaño máximo de los encabezados SOAP, que debe leerse en el modo de búfer.
dividiendo…
-
MaxReceivedMessageSize también debe coincidir con lo que se pone en el MaxBufferSize. El valor predeterminado es 65536.
-
MaxStringContentLength – (Desde MSDN) Obtiene y establece la longitud máxima de la cadena devuelta por el lector. El valor predeterminado es 8192.
Esto aparecen en varias lecturas por varias razones; pero la que salta a la vista es la seguridad. Consulte «Consideraciones de seguridad para datos» para obtener más información sobre lo que esas propiedades pueden prevenir.
En mi caso después de hacer mi tarea y leer sobres eso realice el siguiente ejemplo espero que les sirva esto hice para dar solución a mi problema.
primero hare una base de datos, un servicio y simulare el error desde un formulario comencemos:
Ya que tenemos la bases de datos crearemos un proyecto nuevo de tipo WCF:
Crearemos una clase para que me sirva de modelo:
Esta clase quedaría de la siguiente forma:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;
namespace PruebaError
{
[DataContract]
publicclassErrorDatos
{
[DataMember]
publicInt64 Id { get; set; }
[DataMember]
publicstring Numero { get; set; }
[DataMember]
publicstring Cantidad { get; set; }
}
}
Comenzaríamos con la clase donde tenemos los métodos que son expuestos por nuestros servicio esta clase quedaría de esta forma:
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Data;
using System.Data.SqlClient;
namespace PruebaError
{
publicclassService1 : IService1
{
privatestaticstring Conn = @»Data Source=(local);Initial Catalog=Error;Integrated Security=True»;
privatestaticIDbConnection Conexion()
{
returnnewSqlConnection(Conn);
}
publicint AgregarRegistro(ErrorDatos pErrorDatos)
{
IDbConnection conn = Conexion();
conn.Open();
int resultado = newSqlCommand(string.Format(«Insert Into ErrorDatos(Numero,Cantidad) Values»
+«(‘{0}’,'{1}’)»,pErrorDatos.Numero,pErrorDatos.Cantidad), conn asSqlConnection).ExecuteNonQuery();
conn.Close();
return resultado;
}
publicList<ErrorDatos> ListaDatos()
{
List<ErrorDatos> lista = newList<ErrorDatos>();
IDbConnection conn = Conexion();
conn.Open();
IDataReader reader = newSqlCommand(«Select * from errorDatos», conn asSqlConnection).ExecuteReader();
while (reader.Read())
{
ErrorDatos obj = newErrorDatos();
obj.Id = reader.GetInt64(0);
obj.Numero = reader.GetString(1);
obj.Cantidad = reader.GetString(2);
lista.Add(obj);
}
conn.Close();
return lista;
}
}
}
Hoy colocaríamos los métodos que serán pasados por el servicio:
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace PruebaError
{
[ServiceContract]
publicinterfaceIService1
{
[OperationContract]
int AgregarRegistro(ErrorDatos pErrorDatos);
[OperationContract]
List<ErrorDatos> ListaDatos();
}
}
Hoy haremos otro proyecto de tipo windowsform con el cual haremos que se cometa el error.
Cargaremos la referencia de los servicios para este proyecto:
En este proyecto dibujare lo siguiente:
En los botones programare los siguiente:
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using FormError.ServiceReference;
namespace FormError
{
publicpartialclassForm1 : Form
{
Service1Client serv = newService1Client();
public Form1()
{
InitializeComponent();
}
privatevoid button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 200; i++)
{
serv.AgregarRegistro(newErrorDatos() { Numero = i.ToString(), Cantidad = (i + 200).ToString() });
}
MessageBox.Show(«Datos Guardados»);
}
privatevoid button2_Click(object sender, EventArgs e)
{
dataGridView1.DataSource = serv.ListaDatos();
}
}
}
Correríamos este proyecto y le daríamos unas cinco o mas veces al botón guardar Datos
Hoy si damos clic al botón Mostrar Datos no tirara este error del que hablamos al principio del post.
Hemos conseguido recrear este error hoy veamos como darle solución al mismo.
Primero tendremos que configurar del lado del servicio la configuración del WCF:
Cambiaremos la configuración de esta ventana de configuración:
Ya que configuramos y guardamos nuestra configuración solo faltara tomar una parte de esa configuración del app.config y lo colocaremos en el lado del cliente.
En el app.config del lado del cliente tendríamos que pegarlo así:
Solo es borrar la parte del binding y colocar la nueva hoy nos dará error en el bindingConfiguration, esto es por que el name del binding no son iguales para ello solo hay que cambiarlo.
Hoy solo hay que probar si nos da la misma excepción de antes.
Ya vimos como solucionar esta excepción. espero que te sirva de algo…