Cómo validar un ViewModel completo utilizando IValidatableObject

Cuando tienes un “ViewModel”, puedes utilizar estas anotaciones en cada propiedad:

[Required(ErrorMessage = "Requerido")]
public string Nombres { get; set; }

Sin embargo, también puedes especificar validaciones conformadas por reglas más complicadas que utilicen varias propiedades.

Por ejemplo, validar que el parámetro de un URL contenga únicamente letras, minúsculas y guiones y que además este URL no esté asociado ya con otro registro en la base de datos.

Para realizar la validación en todo el “ViewModel”, haz lo siguiente.

Haz que la clase herede de “IValidatableObject”, de esta forma:

public class MiViewModel : IValidatableObject

Después crea este método dentro de “MiViewModel”:

public IEnumerable Validate(ValidationContext validationContext)

Y dentro de él coloca tus reglas.

Para el ejemplo que mencioné arriba, el método completo quedaría así:

public IEnumerable Validate(ValidationContext validationContext)
 {
    // # Que haya solamente letras minusculas, números y guiones en el URL
    bool BanderaURL = Regex.IsMatch(URL, @"^[a-z0-9-]+$");
    if (Regex.IsMatch(URL, @"^[a-z0-9-]+$") == false)
    {
       yield return new ValidationResult("El URL contiene caracteres no válidos.", new[] { "URL" });
    }
 // # Que no exista previamente el URL que quieren colocar
    if (miRepositorio.ChecarSiYaExisteElURL(URL) == true)
    {
       yield return new ValidationResult("El URL ya está asociado con otro registro.", new[] { "URL" });
    }
 }

El valor que regresamos con “ValidationResult” en la línea que comienza con “yield” recibe primero la descripción del error, y después un arreglo con las propiedades que están generando dicho error. En nuestro caso es solamente una.

Si la información ingresada por el usuario no pasa la validación, entonces los mensajes que estableciste aparecerán en donde coloques este código en tu “View” (.cshtml):

@Html.ValidationMessageFor(model => model.URL, "", new { @class = "help-block text-danger" })

Nota que nos estamos refiriendo a la propiedad “URL” del “model”, que coincide con la que utilizamos arriba en la línea que empieza con “yield”. Si no coinciden, no aparecerá el mensaje de error.

Y también podrás evaluarlas en tu código con:

if (ModelState.IsValid)

Utiliza “Local” en Entity Framework para buscar registros que aún no han sido guardados en la base de datos

Considera este código:

var alumno = new Alumno();
alumno.Nombre = "Juan Luna";
context.Alumnos.Add(alumno);
//No vamos a usar "context.SaveChanges" en este ejemplo
var buscarAlumno = context.Alumnos.SingleOrDefault(a => a.Nombre == "Juan Luna");

Como no guardamos el registro, entonces “buscarAlumno” será nula porque no se encontró el alumno “Juan Luna”.

Esto puede parecer confuso porque lo acababamos de insertar, pero en nuestro código la búsqueda está yendo a buscar el registro en la base de datos, y como no hemos utilizado “SaveChanges” entonces el registro está en memoria, pero no en la base de datos.

Si quieres buscar el registro localmente, cambia la línea donde buscas al alumno por la siguiente, agregando “Local”:

var buscarAlumno = context.Alumnos.Local.SingleOrDefault(a => a.Nombre == "Juan Luna");

Listo, ahora sí se encontrará al alumno.

Esto suele ser útil cuando estás guardando muchos registros de golpe en un ciclo antes de ejecutar “SaveChanges” al final.

Validation failed for one or more entities. See ‘EntityValidationErrors’ property for more details.

Al intentar insertar varios registros mediante mi Repository y después intentar guardar los cambios, me aparecía este error:

Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.

Esto ocurre cuando estás tratando de insertar un registro que rompe las reglas de validación. Por ejemplo, estás tratando de insertar un valor en un campo que no coincide con su tipo de dato o estás ingresando un texto “nvarchar” de mayor longitud al permitido.

Para poder visualizar los errores de validación que se están generando, agrega un “try…catch” en el momento en que guardas, de esta forma:

try 
{
   miRepositorio.Guardar();
} 
catch (DbEntityValidationException dbEx) 
{
   foreach(var validationErrors in dbEx.EntityValidationErrors) 
   {
      foreach(var validationError in validationErrors.ValidationErrors) 
      {
         Trace.TraceInformation("Property: {0} Error: {1}",
             validationError.PropertyName,
             validationError.ErrorMessage);
      }
   }
}

Ahora corre tu aplicación en modo “debug” utilizando Visual Studio.
Abre la ventana “output” que encuentras en el menú Debug -> Windows -> Output.

La instrucción “Trace” va a escribir los errores en esta ventana. Es posible que el contenido de esta ventana esté lleno de información del “debugger”, si es así oprime CTRL-F y busca “Property:”, verás lo siguiente:

Visual Studio Trace

De esta forma podrás ver los errores que están apareciendo y modificar tu código para corregirlos.

Fuente.

This program is blocked by group policy. For more information, contact your system administrator

Tratando de subir una aplicación web escrita en asp.net MVC 4.5.2 a un hospedaje de Godaddy, me salía este error:

This program is blocked by group policy. For more information, contact your system administrator.

Este error se debe a que Godaddy no permite la compilación en el servidor.
Busca en tu archivo web.config esta configuración:

<system.codedom>

   <compilers>

      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warninglevel="4" compileroptions="/langversion:6 /nowarn:1659;1699;1701"></compiler>

      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warninglevel="4" compileroptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+"></compiler>

   </compilers>

</system.codedom>

Y eliminar todo el contenido, hasta que quede así:

<system.codedom>
<!-- Nada aquí -->
</system.codedom>

Otra forma de hacer esto mismo, es colocar esto en tu archivo web.release.config.

<system.codedom xdt:transform="Remove">

Notas:

  • Cuando publiques tu sitio utilizando web deploy, en las opciones de File Publish Options marca la casilla Remove additional files at destination. Esto hace que se elimine cualquier archivo que esté provocando problemas en el servidor. Toma en cuenta que también eliminará cualquier archivo que hayas marcado como excluir del proyecto en Visual Studio, y que tal vez el sitio web esté utilizando (imágenes subidas por los usuarios por ejemplo).
  • También intenta marcar o desmarcar la opción Precompile during publishing. A mí me funciona bien desmarcada, pero a veces sirve marcarla.

Fuente: http://stackoverflow.com/questions/24638267/deploying-asp-net-mvc4-app-to-godaddy-compiler-issue

Error System.Security.SecurityException: Request failed

Tratando de subir una aplicación web escrita en asp.net MVC 4.5.2 a un hospedaje de Godaddy, me salía este error:

Error System.Security.SecurityException: Request failed

Se debe a que la aplicación necesita correr con permisos full trust. Hace un tiempo había una página en el panel de control de Godaddy que te permitía mover este ajuste, pero al parecer ya lo retiraron. Pero lo puedes especificar en tu archivo web.config, de esta forma:

<system.web>
   <trust level="Full"></trust>
</system.web>

Con esto se arregla el problema.

Fuente: http://stackoverflow.com/questions/11524582/system-security-securityexception