none
Manejar campos requeridos y mostrar error RRS feed

  • Pregunta

  • Buenas, mediante MVC5 y EF6 he creado un formulario del tipo "Create" para la inserción de clientes , para ello he modificado la vista para adaptarla un poco a un diseño de 3 columnas.

    Ahora tengo una duda con los campos requeridos , el modelo tiene diversos campos que no pueden ser nulos por ejemplo "nombre" y "apellido1" por lo que si no pongo el campo requerido a la vista , la ejecuto y intento hacer una inserción en blanco me da este error

    Código VISTA 

    @model testProject.Models.Clientes
    
    
    @using (Html.BeginForm()) 
    {
        @Html.AntiForgeryToken()
    
            <div class="row">
                <div class="col-xs-6 col-sm-4">
                    @Html.Label(testProject.Resources.idiomas.nombre, htmlAttributes: new { @class = "control-label col-md-2" })
                    <div class="col-md-10">
                        @Html.EditorFor(model => model.nombre, new { htmlAttributes = new { @class = "form-control", required = "required" } })
                        @Html.ValidationMessageFor(model => model.nombre, "", new { @class = "text-danger" })
                    </div>
                </div>
    
    }
    

    Resultado en Chrome

    Mi duda es como debo gestionar esto? Es decir en los campos textbox les puedo poner la etiqueta tipo esto

    @Html.TextBoxFor(m => m.ShortName, 
    new { @class = "form-control", placeholder = "short name", required="required"})

    A esto no le veo ningún problema , más que saber que campos del modelo no pueden ser nulos y que me aparece este mensaje de error en inglés que supongo que en algún archivo de jquery podrá traducir no?

    Gracias,

    lunes, 9 de enero de 2017 12:28

Todas las respuestas

  • Una solución que he visto pero que no he probado es poner la propiedad required en el modelo de la clase

    [Required]
    public string ShortName {get; set;}

    Que me recomiendan hacer?

    Gracias,

    lunes, 9 de enero de 2017 12:31
  • golfgti6,

    Efectivamente, puedes hacer uso de los atributos que expone el espacio de nombres DataAnnotations para definir reglas de validación para cada propiedad del modelo, de hecho una de las ventajas es que la validación se dará tanto en el cliente como en el servidor. Te dejo un enlace que te dará un mayor alcance de lo que te he platicado Using Data Annotations for Model Validation.

    Por otro lado, entiendo que usas el enfoque DataBase First de Entity Framework, por tanto debes escribir los atributos de validación en un archivo distinto al generado por Entity Framework para evitar que una actualización sobre escriba los cambios realizados. Para separar una definición de clase en mas de un archivo puedes hacer uso de clases parciales, aquí otro alcance de lo comentado Generación automática entidades poco se pierde data anotations


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    lunes, 9 de enero de 2017 14:16
  • Hola puede personalizar las DataAnotations, y definir el mensaje que quieres que salga.

    [Required(ErrorMessage = "{0} es requerido")]
    public string ShortName {get; set;}

    ahi por ejemplo, cuando se genere el error te dira, ShorName es requerido.


    Horacio Xochitemol Bautista

    • Propuesto como respuesta Xochitemol lunes, 9 de enero de 2017 15:17
    lunes, 9 de enero de 2017 14:54
  • golfgti6,

    Efectivamente, puedes hacer uso de los atributos que expone el espacio de nombres DataAnnotations para definir reglas de validación para cada propiedad del modelo, de hecho una de las ventajas es que la validación se dará tanto en el cliente como en el servidor. Te dejo un enlace que te dará un mayor alcance de lo que te he platicado Using Data Annotations for Model Validation.

    Por otro lado, entiendo que usas el enfoque DataBase First de Entity Framework, por tanto debes escribir los atributos de validación en un archivo distinto al generado por Entity Framework para evitar que una actualización sobre escriba los cambios realizados. Para separar una definición de clase en mas de un archivo puedes hacer uso de clases parciales, aquí otro alcance de lo comentado Generación automática entidades poco se pierde data anotations


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.

    Si , uso el enfoque DataBase First por lo que creo que la opción correcta es generar una clase parcial.

    En mi caso tengo esta estructura

    Un ejemplo para el campo "nombre" podria ser este no?

        [MetadataType(typeof(ClientesMetaData))]
        public partial class Clientes { }
        class ClientesMetaData
        {
            [DisplayName("Nombre")]
            public String      Nombre   { get; set; }
            [Required(ErrorMessage = "El campo nombre es obligatorio")]
            ...
        }

    Esto lo pongo en un archivo de tipo clase (.cs) dentro de la carpeta Models?

    Para respetar la arquitectura.

    Gracias

    • Propuesto como respuesta Xochitemol lunes, 9 de enero de 2017 15:17
    lunes, 9 de enero de 2017 15:15
  • golfgti6,

    En tanto los archivos que definen una clase (clases parciales) se encuentren dentro de un mismo espacio de nombres el compilador será capaz de combinarlos. Por temas de organización es correcto contener las clases "personalizadas" dentro de la carpeta Models, si deseas podrías crear una carpeta llamada Validaciones (Models > Validaciones) que contenga las clases parciales que definen las reglas de validación.


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    lunes, 9 de enero de 2017 15:29
  • golfgti6,

    En tanto los archivos que definen una clase (clases parciales) se encuentren dentro de un mismo espacio de nombres el compilador será capaz de combinarlos. Por temas de organización es correcto contener las clases "personalizadas" dentro de la carpeta Models, si deseas podrías crear una carpeta llamada Validaciones (Models > Validaciones) que contenga las clases parciales que definen las reglas de validación.


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.

    Vale lo he puesto dentro de una carpeta y me ha quedado este código

    Y la clase para validaciones

    El proyecto me compila y se me ejecuta pero cuando hago uso del CREATE para el objeto clientes y dejo el campo apellido1 en blanco me da este error

    Gracias,

    lunes, 9 de enero de 2017 17:32
  • hola

    no tienes que usar el modelo de EF como model de mvc eso esta mal, se que miles de ejemplso en la web lo hacen pero justamente son ejemplo que no debes seguir

    tiene que crear una clase en la carpeta Model de mvc con las propiedades que usaras en la view y luego en el action mapear la clase de EF retorna con el model que usaras en la view

    podrias ayudarte con automapper para convertir de una clase a otra, de esta forma podras agregar atributos de validacion en la clse model de mvc sin afectar la clase de EF

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    lunes, 9 de enero de 2017 17:50
  • para obtener una descripcion de la validacion que falla en EF cunado realizas el SaveChanges() debes usar

    try
    {
    	//codigo qie invoca al SaveChanges()
    }
    catch (DbEntityValidationException ex)
    {
    	// Retrieve the error messages as a list of strings.
    	var errorMessages = ex.EntityValidationErrors
    			.SelectMany(x => x.ValidationErrors)
    			.Select(x => x.ErrorMessage);
    
    	// Join the list to a single string.
    	var fullErrorMessage = string.Join("; ", errorMessages);
    
    	// Combine the original exception message with the new one.
    	var exceptionMessage = string.Concat(ex.Message, " The validation errors are: ", fullErrorMessage);
    
    	// Throw a new DbEntityValidationException with the improved exception message.
    	throw new DbEntityValidationException(exceptionMessage, ex.EntityValidationErrors);
    }

    al controlar el exception podras ver que valiadacion es la que impide el save

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    lunes, 9 de enero de 2017 17:51
  • golfgti6,

    ¿Leíste la definición de clases parciales?

    Para que el compilador pueda combinar o fusionar todos los archivos que corresponden a una definición de clase estos deben estar contenidos en el mismo ensamblado y en el mismo espacio de nombres y además deben tener el mismo nombre que identifica a la clase, caso contrario, ¿de qué forma se podría relacionar uno con otro?. Por la excepción que obtienes es claro que se está desconociendo la clase donde contienes las validaciones porque el nombre de la clase Clientes nada tiene que ver con la clase ClientesDataValidation, sigue el siguiente ejemplo:

    namespace XXXX.Models
    {
        [MetadataType(typeof(Metadata))]    
        
        partial class Clientes //Mismo nombre que la clase "origen"
        {
            private sealed class Metadata
            {
                //Propiedades y atributos de validación
            }        
        }
    }


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    lunes, 9 de enero de 2017 19:24