Error: Validation failed for one or more entities

Si tienes este error al guardar una entidad en Entity FrameworkValidation failed for one or more entities. See ‘EntityValidationErrors’ property for more details“, es posible que te vuelvas loco buscando entre las propiedades de la excepción, cuál es el verdadero problema.

Para ello podemos utilizar el inspector rápido de Visual Studio (Shift + F9) y poner lo siguiente:

((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors

Así veremos el detalle del error que estamos viendo, como podemos ver en la imágen:

excepcion-entity-validation-errors

 

Convertir encriptación en PHP 3DES en C#

Recientemente ha avisado que el sistema de pago por TPV virtual de Redsys se va a actualizar. En esta actualización se van a incorporar medidas de cifrado más potentes que la firma actual que se tiene implementado. Para ello los bancos han enviado cierta documentación (un poco tarde…) para hacer esta migración, puesto que el 23/11/2015 se supone que dejará de funcionar el sistema de encriptación actual.

Realizando la migración en mi empresa me he encontrado con un escollo que me ha costado un poco de solventar, y por lo que veo a muchos más desarrolladores de .NET les ha sucedido lo mismo. El problema está en el cifrado triple DES.

Este es el código de ejemplo que te facilitan en Redsys para realizar este cifrado.

function encrypt_3DES($message, $key){
// Se establece un IV por defecto
$bytes = array(0,0,0,0,0,0,0,0); //byte [] IV = {0, 0, 0, 0, 0, 0, 0, 0}
$iv = implode(array_map("chr", $bytes)); //PHP 4 = 4.0.2


// Se cifra
$ciphertext = mcrypt_encrypt(MCRYPT_3DES, $key, $message, MCRYPT_MODE_CBC, $iv); //PHP 4 >= 4.0.2
return $ciphertext;
}


$key = $this->decodeBase64($key);
$ciphertext = $this->encrypt_3DES($message, $key);

La variable $message sería el texto a encryptar (en el caso de Redsys el número de pedido). La variable $key es la clave de encriptación de Redsys que previamente la decodificamos en Base64.
Al final obtenemos un resultado ($ciphertext) que es un array de bytes.

Ahora viene cuando hacemos lo mismo en .NET C#.


///
/// Uso de la encriptación TripleDES con IV todo 0 -> byte [] IV = {0, 0, 0, 0, 0, 0, 0, 0}
/// Esta encriptación se usa así para los TPV's de Redsys
///


///Texto a encriptar ///Clave de la encriptación en un array de Bytes ///
public static byte[] EncriptarTripleDES_IV_0(string texto, byte[] key)
{
using (TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider())
{
byte[] iv_0 = { 0, 0, 0, 0, 0, 0, 0, 0 };  //same IV that Redsys
byte[] toEncryptArray = Encoding.ASCII.GetBytes(texto);
tdes.IV = iv_0;
//assign the secret key
tdes.Key = key;
tdes.Mode = CipherMode.CBC;
tdes.Padding = PaddingMode.Zeros;
ICryptoTransform cTransform = tdes.CreateEncryptor();
//transform the specified region of bytes array to resultArray
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0,toEncryptArray.Length);
//Clear to Best Practices
tdes.Clear();
return resultArray;
}
}

Esta función nos devuelve el mismo resultado que la orginial proporcionada por Redsys en PHP.

El tipo ‘ObjectContent`1’ no pudo serializar el cuerpo de respuesta para el tipo de contenido

Si estás usando un Web API con Entity Framework, es posible que te salte este error “El tipo ‘ObjectContent`1’ no pudo serializar el cuerpo de respuesta para el tipo de contenido“, al intentar recuperar algún registro.

¿Por qué ha ocurrido esto?, bueno pues una de las posibles causas es que al intentar serializar con JSON, en nuestras tablas tenemos referencias a otras tablas (por ejemplo un foreign key) y la librería de NewtonJson nos diga que hay una referencia circular.

¿Como arreglamos este error?. Tendremos que incorporar las siguientes líneas de código o bien en el WebApiConfig.cs o bien en el Global.asax.cs

WebApiConfig

  
//Evito las referencias circulares al trabajar con Entity FrameWork         
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
            
//Elimino que el sistema devuelva en XML, sólo trabajaremos con JSON
config.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);

Global.asax

  
//Evito las referencias circulares al trabajar con Entity FrameWork         
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
            
//Elimino que el sistema devuelva en XML, sólo trabajaremos con JSON
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);

Otra manera de localizar este problema es cuando nos aparece este mensaje de error:
An exception has occurred while using the formatter ‘JsonMediaTypeFormatter’ to generate sample for media type ‘application/json’. Exception message: Se han producido uno o varios errores.

Espero que os con esto se resuelva vuestro problema.

 

Formato de solicitud no reconocido para la dirección URL, finaliza de manera inesperada….

Hemos creado un servicio web asmx en .NET y al probarlo en local funciona perfectamente. Vemos las definiciones los métodos, podemos hacer llamas a los mismos etc. (maravilloso!!)

Ahora lo subimos a un servidor en internet y nos aparecen las definiciones pero no podemos hacer llamadas a los métodos y nos devuelve el siguiente mensaje de error:
“Formato de solicitud no reconocido para la dirección URL, finaliza de manera inesperada xxxxx”

¿Porque nos aparece este problema?

  • Bueno pues es porque no hemos definido en el web config  los protocolos que va a usar nuestro servicio web y por defecto en IIS vienen desactivados, cosa que no ocurre cuando lo ejecutamos de manera local.

¿Como solucionamos este problema?

  • Añadiendo al web config las siguientes líneas dentro de la sección <system.web>

<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>

Con esto ya podríamos consumir nuestro servicio web asmx de .NET