BadRequest en servicios de datos ADO.NET

En servicios de datos ADO.NET puede haber varios motivos por los que tenemos un error BadRequest en nuestras peticiones. Este tipo de servicios no suele dar mucha información del error que se produce y en alguna ocasiones tenemos que mirar un poco e investigar cual puede ser el motivo.

En el caso de BadRequest con código 400 uno de los motivos puede ser el tamaño del mensaje. Sorprendetemente el tamaño esta limitado por defecto a 65536 bytes. Estamos hablando de tan solo 64KB. En aplicaciones que deban enviar tipos de datos complejos o imagenes este tamaño queda en seguida en insuficiente y es en este momento que recibimos el error BadRequest.

Para solucionarlo debemos configurar el servicio de la siguiente manera:

1) Des del servidor abriendo el web.config añadimos lo siguiente para configurar el servicio para que acepte el volumen en bytes que nosotros deseamos.

<services>
    <!-- The service name below has to be the EXACT Namespace.ClassName of your WCF Data Service-->
    <service name="YourDomainNameHere.YourClassNameHere">
        <!-- The address below must be the EXACT address of your service or blank-->
        <endpoint address ="http://localhost:19766/YourServiceName.svc" binding="webHttpBinding" bindingConfiguration="higherMessageSize" contract ="System.Data.Services.IRequestHandler">
        </endpoint>
    </service>
</services>

2) Necesitas especificar el tamaño en la propiedad maxReceivedMessageSize del elemento binding de la configuración de enlace higherMessageSize

<bindings>
    <webHttpBinding>
        <!-- The maxReceivedMessageSize and the maxBufferSize must both be specified as shown below-->
        <binding name="higherMessageSize" maxReceivedMessageSize ="2048000" maxBufferSize="2048000"/>
    </webHttpBinding>
</bindings>

No olvides que si el servicio se hospeda en un IIS ese mismo tiene limitado el tamaño de las peticiones a 4MB. Por lo tanto debes añadir en el archivo de configuración lo siguiente para equilibrar los valores.

<system.web> 
  <httpRuntime MaxRequestLength="ValueInKiloBytes" />
</system.web>

 

Otros enlaces:

How do I increase the size of data sent to ADO.Net Data Services?

Change max message size in DataServiceContext

 

ADO.NET Data Services y GUID

En el post anterior hablando de como podemos enlazarnos a un servicio web para leer imagenes comenté que debiamos construir la URL de la siguiente manera:

http://<url servei>/<nom servei>/<nom taula>(<valor clau primaria>)/Image/$value

Es correcto. Pero cuando la clave primaria es un numero unico GUID el formato cambia un poco. Debes cambiarlo por:

http://<url servei>/<nom servei>/<nom taula>(guid'<el valor del guid>')/Image/$value

Que cosas verdad?

ADO.NET Data Services i tipus Image a Sql Server 2008

Considero que ADO.NET Data Services és una tecnologia que va molt bé per generar serveis web que gestionen una base de dades d’una manera ràpida i senzilla, a més a més, utilitza REST per comunicar-se amb el servei. Només per peticions HTTP es pot fer totes les operacions bàsiques a una base de dades. Aquestes peticions bàsiques segueixen una sintaxi determinada per un protocol estàndard que està definit a odata.org

Per tant hi treballo bastant però quan hi estic posat sempre recordo els tipus de dades de SQL Server que no son compatibles (de moment) amb aquesta tecnología. Al següent link hi ha el mapeig que es fa de tipus SQL Server a .Net Framework.

SQL Server Data Type Mappings

Un dels casos que ens podem trobar sovint és com gestionem les imatges. M’explico: Tenim un servei que emmagatzema imatges, per exemple les fotos del perfil, directament a la base de dades amb format binary (utilitzant per tant el tipus Image de Sql Server). Per sort aquest tipus de dades no té cap problema amb ADO.NET Data Services i es pot utilitzar tranquil·lament.

En la imatge es pot veure com les imatges es transporten com arrays binaris per la web.

Ara toca construir la nostra aplicació client web que ens permeti almenys visualitzar aquest contingut. Utilitzant DataBinding pots agafar un GridView i enllaçar-lo a un ObjectDataSource que ens farà de proxy per el servei ADO.NET. El GridView colocaràs un ImageField per poder enllaçar el camp de la imatge que t’arriba en format binary, però l’enllaç simple no et pot funcionar ja que el que vol ASP.NET aqui és una URL. Per exemple el següent tros de codi mostra el que no funcionarà, tingues en compte que el camp de la taula de la base de dades que conté la imatge en format binary és Image:

<asp:ImageField DataImageUrlField="Image" HeaderText="Image">
 </asp:ImageField>

Per tant una solució és tornar a demanar al servei que vols aquest camp però directament el seu valor. Per fer-ho construeixes la Url de la següent manera:

http://<url servei>/<nom servei>/<nom taula>(<valor clau primaria>)/Image/$value

el resultat final et quedaria com:

<asp:ImageField DataImageUrlField="IdRegistre" DataImageUrlFormatString="http://localhost:52159/Service.svc/Profiles({0})/Image/$value" HeaderText="Image">
 </asp:ImageField>

on IdRegistre indica el camp de la taula que és clau primaria.

Com pots veure ADO.Net Data Service és una bona manera de construir serveis per accedir a les taules de la base de dades sense haver d’escriure grans linies de codi. Tot l’accés és per HTTP i és aplicable des de JQUERY i Silverlight i altres sense cap tipus de problema.

Links que et poden ampliar aquesta informació o et poden interessar:

Images as a Service with ADO.NET Data Services

Retrieving Images from a Database ( C# )

ImageField.DataImageUrlFormatString (Propiedad)