Windows Phone 8.1 | Usar el flash de la cámara ¿Torch o Flash?

posterMientras desarrollaba la aplicación Torch8 me encontré con estas dos formas de controlar el flash de la cámara pero, ¿cuál es la adecuada para qué momento y cómo debo usarla?

Si vamos a la documentación podemos observar que la ayuda para tomar esta decisión es mínima y que depende en gran medida de la interpretación que hagamos sobre la descripción.

  • TorchControl : Provides functionality for controlling the torch LED settings on a capture device.
  • FlashControl : Provides functionality for controlling the flash settings on a capture device.

Y os preguntaréis… WTF!! Pero si es análogo!! Pues no exactamente. Digamos que la diferencia es que Torch está pensado simplemente para alumbrar porque sí y Flash está pensando para realizar la acción de flash durante una captura de una foto o un vídeo aunque en definitiva, sea prácticamente lo mismo. De hecho, FlashControl contiene alguans propiedades más como RedEyeReduction y RedEyeReductionSupported que nos dan esa misma idea.

Sea cual sea lo que decidamos usar y que vaya acorde con nuestra aplicación, su uso es muy similar, necesitando únicamente una instancia de MediaCapture desde la que obtener el acceso al controlador tal y como muestro en los ejemplos

TorchControl

public void TurnTorch(bool on)
{
if (mediaCapture.VideoDeviceController.TorchControl.Supported)
{
if (on)
{
if (mediaCapture.VideoDeviceController.TorchControl.PowerSupported)
mediaCapture.VideoDeviceController.TorchControl.PowerPercent = 100;
mediaCapture.VideoDeviceController.TorchControl.Enabled = true;
}
else
mediaCapture.VideoDeviceController.TorchControl.Enabled = false;
}
}

FlashControl

        public void TurnFlash(bool on)
{
var flashControl = mediaCapture.VideoDeviceController.FlashControl;

            if (flashControl.Supported)
{
if (on)
{
if (flashControl.PowerSupported)
flashControl.PowerPercent = 100;
#if WINDOWS_PHONE_APP
if (flashControl.AssistantLightSupported)
flashControl.AssistantLightEnabled = true;
#endif
if (flashControl.RedEyeReductionSupported)
{
flashControl.RedEyeReduction = true;
}
flashControl.Enabled = true;
}
else
flashControl.Enabled = false;
}
}

 

Como podéis observar, con el control del flash se pueden realizar más tareas que sólo tienen sentido en la captura de una imagen pero, que en el caso de mi aplicación de linterna no tendrían razón de ser, por eso, debéis usar la que se adapte mejor a vuestra aplicación en cada momento.

Notas importantes

Como siempre, recordad liberar los recursos de la cámara como os indiqué en el artículo anterior y, como apunte a este artículo, no os asustéis si el led no se enciende cuando estéis desarrollando, simplemente, tened en cuenta que si el dispositivo está conectado al PC (o a la corriente) el led no se activará con este código

 

Espero que os sea de ayuda. Enjoy coding!!

Windows Phone 8.1 | Iniciar cámara para previsualización

posterSupongamos que estamos realizando una aplicació y necesitamos ver lo que estamos enfocando con la cámara ya sea para iniciar una grabación, tomar una foto o simplemente, como en mi caso para hacer una linterna con cámara (Torch8). Dado que ya tenemos disponible el desarrollo para Windows 10 (desktop y mobile) la información escasea acerca de esta temática para la plataforma Windows Phone 8.1 y Windows 8.1, así que he recopilado lo que he encontrado al respecto y os lo condensaré en este artículo.

Seleccionar cámara

Para empezar, debemos seleccionar la cámara del dispositivo dado que podemos tener delantera, trasera o las dos.

// Get all the cameras
DeviceInformationCollection cameras = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);

// Selecting frotal camera
DeviceInformation frontCam = (from webcam in cameras
                              where webcam.EnclosureLocation != null
                              && webcam.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Front
                              select webcam).FirstOrDefault();

// Selecting rear camera
DeviceInformation rearCam = (from webcam in cameras
                                where webcam.EnclosureLocation != null
                                && webcam.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Back
                                select webcam).FirstOrDefault();

 

Inicializar parámetros de captura

Una vez tengamos la cámara deseada, tendremos que inicializar la captura de vídeo con los parámetros que necesitemos como por ejemplo el código que muestro a continuación

// Initialize MediaCapture parameters
await mediaCapture.InitializeAsync(new MediaCaptureInitializationSettings
{
    VideoDeviceId = rearCam.Id, // Using rear camera
    AudioDeviceId = "", // Don’t capture audio
    StreamingCaptureMode = StreamingCaptureMode.Video, // We want to capture video
    PhotoCaptureSource = PhotoCaptureSource.VideoPreview // Capture mode (Auto | Photo | VideoPreview)

});

Comenzar a obtener visualización de la cámara

Llegados a este punto, ya podemos visualizar lo que enfoquemos con la cámara en nuestro dispositivo y, para ello necesitamos tener preparado el control en la vista XAML y referenciarlo desde el código C#

XAML

<CaptureElement Name="PreviewControl"
                Stretch="UniformToFill"
                />

C#

// Set primary use as Video.

mediaCapture.VideoDeviceController.PrimaryUse = Windows.Media.Devices.CaptureUse.Video;

// Set the source of the CaptureElement to your MediaCapture
PreviewControl.Source = mediaCapture;

// Start Preview of Video.

await mediaCapture.StartPreviewAsync();

Más información

Toda esta información y podéis encontrarla con mayor profundidad en este enlace de MSDN 

Nota Importante

Debeis recordar que es absolutamente necesario liberar los recursos de la cámara al cerrar/suspender la aplicación ya que si no, puede haber conflictos con otras aplicaciones e incluso la nuestra no funcionará como esperamos, para ello, en el enlace que os he puesto tenéis a vuestra dispocisión una muestra de código para limpiar los recursos

public async Task CleanupCaptureResources()
{
    if (IsRecording && MediaCapture != null)
    {
        await MediaCapture.StopRecordAsync();
        IsRecording = false;
    }
    if (IsPreviewing && MediaCapture != null)
    {
        await MediaCapture.StopPreviewAsync();
        IsPreviewing = false;
    }

    if (MediaCapture != null)
    {
        if (PreviewElement != null)
        {
            PreviewElement.Source = null;
        }
        MediaCapture.Dispose();
    }
}

Esta limpieza debéis llevarla a cabo al menos al suspender la aplicación tal y como os copio y pego de la documentación

private async void OnSuspending(object sender, SuspendingEventArgs e)
{
    var deferral = e.SuspendingOperation.GetDeferral();

    //cleanup camera resources
    await CleanupCaptureResources();

    deferral.Complete();
}

No obstante debéis consultar en profundidad la documentación acerca de los estados y el ciclo de vida de las aplicaciones Windows Phone 8.1 o incluso estudiar la posibilidad de manejar la suspensión en la vista tal y como se explica en este artículo de MSDN.

 

Espero que os sea de ayuda. Enjoy coding!!!

Talks4Kids | Somos solidarios con los niños y nos lo pasamos genial

talks4kidsEl pasado 4 de diciembre se celebró en el auditorio de las instalaciones de Microsoft Ibérica en Madrid, el evento más solidario de año (dentro del ámbito tecnológico) y, dado que sobrepasamos la cifra establecida para obligarnos a disfrazarnos, tuvimos que sacar nuestras galas y hacer un poco el “payaso” sobre el escenario. Lo siento por los asistentes si les causamos pesadillas para toda la vida xD Para un canario como yo, disfrazarse es algo con lo que se convive (nuestros carnavales son reconocidos a nivel mundial) así que llevé uno de los de la colección que me iba como anillo al dedo con la temática de la sesión “Por qué los espartanos molan y Xerxes debe morir” o, traducido al castellano, “Por qué debemos preocuparnos por el diseño de nuestras Apps”.

El evento lo abrió el inspirador de esta maravillosa idea, Josué Yeray junto con un miembro de la Fundación Theodora a la que iba destinada la recaudación íntegra. Esta chica, doctora sonrisa, nos explicó en qué consiste la labor que realizan, cómo sacan una sonrisa a aquellas personas que más lo necesitan y cómo incluso en momentos críticos son capaces de hacer sonreír a los niños para hacerles la vida un poco más feliz.

IMG_20151204_093835

Como podéis ver, puse la nota guerrera en el evento haciendo de Leónidas con mi disfraz de propia manufactura. Advertencia, el abdominal (sólo hay uno y grande) es de verdad, no es pintado xD

CVYfEziWIAE4VYB

La verdad es que nos lo pasamos como niños en el evento aunque en algunas sesiones no se pudiera atender al contenido debido a lo arriesgado del disfraz del ponente xDDD.

IMG_20151204_142237

 

En resumen, fue un gran evento y esperamos poder repetir el próximo año y veros a todos allí disfrazados si queréis, todo sea por una muy buen a causa.

Codemotion 2015 | Resumen de mis sesiones sobre Branding y Universal Windows Platform Apps con Machine Learning

posterUn año más, Codemotion ha sido uno de los mayores eventos sobre tecnolgías de desarrollo de software de España y, este año, me ha tocado el privilegio de participar por partida doble con sesiones sobre Branding en SharePoint (Online y OnPremises) y sobre Aspectos útiles de Machine Learning en Universal Windows Platform Apps. Además, como siempre, Microsoft ha participado muy activamente arropando a los que íbamos a hablar sobre tecnologías .NET y relacionadas así como ofreciendo a todos los asistentes la posibilidad de pasarse por una amplia zona de entretenimiento y networking en la que se podía contactar con cualquiera de los miembros de DX e informarse de todas las ventajas que se ofrecen.

En la primera sesión sobre Branding en SharePoint hablé sobre cómo aplicar técnicas modernas de desarrollo web a la hora de aplicar Branding en los sitios de SharePoint Online u OnPremises.

2

 

En la segunda sesión, compartía cartel junto con el gran Adrián Díaz para hablar sobre “Aspectos útiles de Machine Learning en Universal Windows Platform Apps” con la sala llena a reventar, teniendo incluso gente de pie y más personas que entraron durante la sesión.

320151231053259WP_20151127_15_47_58_Pro

Ésta última sesión fue grabada y podéis ver el vídeo en Youtube

 

Las slides las podéis obtener de SlideShare

Modern Branding en SharePoint desde todos los ángulos

Aspectos útiles de Machine Learning en Universal Windows Platform Apps

 

Espero que os haya gustado el evento a los que estuvísteis y a los que no, el próximo año más 🙂

 

Enjoy coding!!!

TenerifeDev | Resumen de Reconnect();

posterEl pasado 17 de diciembre celebramos en el salón de Grados de la ESIT la jornada de Reconnect(); que consistía en hacer un resumen de las novedades presentadas en el Connect(); que Microsoft celebró en noviembre.

La sesiones que fueron impartidas por cuatro MVPs de Microsoft, David Rodríguez, César Abreu, Quique Martínez y un servidor supusieron un repaso a novedades en .NET Core, ASP.NET 5, Docker, Visual Studio Code, Desarrollo móvil con Xamarin y Desarrollo para la plataforma Windows. Por mi parte, me encargué de esta última sesión culminando un ejemplo práctico de Microsoft para todas las tecnologías como es Microsoft Health Clinic que podéis descargar desde GitHubreconnect

La nota divertida la puso BB8 (StarWars: Episode VII) controlado por David Rodríguez. Este “droide” construido con la base de Sphero es, sn duda, un entretenimiento para los más frikys como nosotros. Lástima no tener fotos/vídeo de las peripecias de este pequeño asistente durante la sesión xD

x-default

Esperamos veros a todos en el próximo evento de TenerifeDev que se celebrará el 14 de enero para hablar sobre Personal Branding y que seguro que os gustará. ¿A qué esperáis para apuntaros?

Enjoy coding!!!

TenerifeDev | Resumen de la jornada sobre Machine Learning en UWP

bolaTDEl pasado 15 de octubre tuvimos una nueva jornada en TenerifeDev en la que hablé sobre Machine Learning junto a David Rodríguez desde el punto de vista práctico aplicándolo a una App Universal de la plataforma Windows desde la que consumíamos las APIs del proyecto Oxford como son Speech API, y las Face APIS del conjunto Vision.

Fue una jornada bastante buena ya que no sólo tuvimos una afluencia bastante buena, sino que además muchas caras eran nuevas y parecían ávidas de conocimiento.

La jornada transcurrió de forma muy amena y dinámica en la que las preguntas eran una constante para conocer aspectos más profundos sobre lo que estábamos contando y nos obligó a esturjarnos los sesos para transmitir el conocimiento y la experiencia que tenemos a los asistentes que, como recompensa recibieron algunos regalos como ya es habitual en las sesiones de TenerifeDev.

CUMgXNmWoAMxryP

Sin duda, esta ha sido una gran jornada que esperamos repetir en la próxima del día 17 de diciembre de 2015, donde haremos un resumen de todo lo visto Connect(); y que se ha bautizado como Reconnect();. Esperamos volver a verlos y que disfruten tanto como nosotros!!!!

WP_20151119_19_43_19_Pro

Talks4Kids | Evento benéfico en favor de los niños

imageEl próximo viernes 4 de diciembre, gracias a la iniciativa de Josué Yeray, se celebrará el primer Talks4Kids en las instalaciones de Microsoft Ibérica (Urbanización La Finca en Pozuelo de Alarcón, Madrid) y tendré el enorme placer de poder impartir una sesión con un título atópico “Por qué los espartanos molan y Gerges debe morir”, pero no os asustéis, que no va a haber lanceros, ni persas, ni espartanos… ¿o sí? jjjj

 

¿Qué es Talks4Kids?

Bueno, lo mejor es que entréis en la web del evento para informaros de todo lo referente al mismo, pero en resumen, es un evento técnico, como todos los que solemos organizar y realizar, en el que algunos de los mejores ponentes/profesionales del territorio español impartirán charlas dirigidas a profesionales y estudiantes pero, con la diferencia de que esta vez os pedimos un poco de ayuda para los niños hospitalizados en forma de “entrada/donativo”. Todo lo recaudado (absolutamente todo) irá a parar a la Fundación Theodora para que haga más feliz la vida de los niños en los hospitales por medio de la risa.

 

Sorpresas por objetivos

Como objetivo, nos hemos propuesto dar las sesiones disfrazados si llegamos a los 1500€ de recaudación… y ya nos queda poco para tener que pasar vergüenza jjjj Si alguno sufre de problemas del corazón que lleve una venda y así no tendrá que pasar el mal rato viéndonos enseñar cuerpazos y además se evitará las pesadillas jjjj.

 

Me apunto!!

¿Aún no tenéis vuestra entrada? ¿A qué esperáis? O al menos colaborad de alguna de las tres formas que os he propuesto.

  • Entrada General: Si queréis asistir, la entrada/donativo será de 10€
  • Sólo donar: Si no podéis asistir al evento, podréis colaborar de igual forma mediante una donación (o las que queráis) de 5€.
  • Patrocinio: Si queréis patrocinar el evento, el donativo ascenderá a los 150€

Recordad que todo lo recaudado está destinado íntegramente a la Fundación Theodora.

 

Sinceramente os esperamos en el evento porque hay muchos niños que ya están esperando también a los chicos de la Fundación Theodora para alegrarles un poco la estancia en los hospitales. De verdad, ayudadnos a sacar la sonrisa de los niños que no hay cosa más bonita que ver a un niño sonreír.

Xamarin.Forms | Ocultar la barra de navegación en Android e iOS

posterPara hoy traigo un “workaround” sobre cómo ocultar la barra de navegación en Android cuando estamos trabajando con Xamarin.Forms.

Problema

Cuando creamos una aplicación Xamarin.Forms, por defecto, en Android aparecerá la barra de navegación al hacer uso de NavigationPage. Si no queremos mostrar esta barra de navegación porque hacemos uso de navegación por contenidos y con el botón “back” del propio sistema no es una tarea trivial hasta donde he indagado. Por favor, si tenéis alguna solución más elegante, sencilla y efectiva, compartidla conmigo.

 

Solución

He encontrado varias soluciones para lograr el resultado deseado pero algunas me han parecido más complejas de lo necesario como por ejemplo, sobreescribir el “Tema” Theme.Holo.Light, cosa que sólo funcionaría en Android y habría que buscar la solución para iOS. Pero la que mejor me ha encajado tampoco es muy elegante que digamos (siempre desde mi punto de vista).

Lo que debemos hacer es poner una simple línea de texto en cada una de las páginas

   1: NavigationPage.SetHasNavigationBar(this, false);

 

Con esto ya tendríamos oculta la barra de navegación de iOS y Android, aunque como he comentado, hay que hacerlo página por página siendo algo “latoso” y poco elegante cuando podría haber una solución más simple

 

Referencias

http://developer.xamarin.com/recipes/ios/content_controls/navigation_controller/make_the_nav_bar_disappear/

Error con jQuery UI datepicker dentro de formulario en Safari

Escenario

Hace algunos días me encontré con un problema en Safari al establecer fechas con un datepicker de Metro UI que es el mismo que el que corresponde a jQuery UI datepicker. El problema se producía al seleccionar una fecha que, al realizarse la validación con jQuery.validation decía que era incorrecta al contrario que en el resto de navegadores (Internet Explorer, Microsoft Edge, Google Chrome*, Firefox y Opera). Además, parece que el error se reproducía en Google Chrome para Mac lo que hacía más complicado determinar cuál es el problema. Como se puede apreciar en la imagen, tiene problemas al establecer fechas predefinidas como en el campo «inicio» en el que he puesto la fecha actual (tanto desde el modelo como con JavaScript) y, en el campo «Vencimiento» la fecha seleccionada con el datepicker genera un error de validación «incomprensible»

Solución

La solución es sencilla aunque no me parece del todo correcta y pasa por saltarse la validación de los campos que estén relacionados con el datepicker con una simple instrucción que siempre devolverá «true» cuando se trate de una fecha.

jQuery.validator.methods[«date»] = function (value, element) { return true; }

 

Tiene algo de sentido si pensamos que la fecha está establecida por el propio datepicker y que no se debe permitir que se inserte una fecha manualmente, cosa que de forma automática ya cumple el datepicker, pero podría darse el caso de que sí que necesitemos realizar algún tipo de validación que nos estaríamos perdiendo por forzar que siempre devuelva «true».

Explicación

Por lo que he investigado, Safari incluye algún tipo de tratamiento para las fechas que nos rompe nuestra validación y que, por lo tanto, nos generará un error de formato. Yendo un poco más allá, parece que en Mac esto mismo se reproduce para Google Chrome, cosa que me parece «inexplicable» cuando sobre Windows funciona correctamente.

¿Conoces alguna solución?

¿Conocéis algún workaround más elegante u óptimo? Abramos el debate pero adelanto que tengo preestablecido el lenguaje en el fichero web.config «es-ES» y en el propio datepicker «es».

ASP.NET MVC | Cómo enviar modelo con JavaScript desde un formulario a una acción

Escenario

Supongamos que tenemos un formulario en una vista de una aplicación web realizada con ASP.MVC y necesitamos enviar los datos, que corresponden a un modelo de la aplicación, a nuestra acción del controlador. ¿Cómo realizamos esta tarea? Seguro que se nos ocurren ideas «liosas» para realizar esta operación pero generalmente optamos por lo más obvio que, además, no es óptimo ni flexible o no aprovechamos las facilidades que nos ofrece el ModelBinding.

Para explicar las posibilidades, quiero exponer las dos opciones que me he encontrado con más regularidad (por orden de veces que lo he visto) antes de exponer la que a mi parecer es la opción más óptima y os explicaré por qué.

Solución NO óptima 1

Lo que más he visto hacer, es lo más costoso y menos flexible que se podría hacer y no es otra solución que cambiar los parámetros de la acción del controlador por los campos del modelo y, en código JavaScript, recoger cada uno de esos campos por separados y mandarlos en los datos de la acción «Ajax». Esto no es en ningún momento óptimo ni bueno aunque funcione porque no es nada flexible ante cambios con lo que si añadimos una nueva propiedad, tendremos que cambiar todo nuestro código para poder enviarla, recibirla y validarla.

Acción del controlador

  1. [HttpPost] 
  2. public JsonResult Create(string brand, string model, …) {  
  3.     try {  
  4.         if (string.IsNullOrEmpty(brand) || string.IsNullOrEmpty(model) || …) return false;  
  5.         var car = new Car {  
  6.             Brand = brand, Model = model, // …  
  7.         };  
  8.         car.Status = «Solicitados»;  
  9.         return Json(true);  
  10.     } catch {  
  11.         return Json(false);  
  12.     }  
  13. }  

     

    Código JavaScript

  14. $(‘#btn-sendForm’).click(function() {  
  15.     var car = {  
  16.         prop1: document.getElementById(‘brand’).value(),  
  17.         prop2: document.getElementById(‘model’).value(), // …  
  18.     }  
  19.     $.ajax({  
  20.         url: ‘@Url.Action(«ACTION», «CONTROLLER»)’,  
  21.         type: ‘POST’,  
  22.         data: item,  
  23.         success: function(result) {  
  24.             var modelStatus = $(‘.model-status’);  
  25.             if (result) modelStatus.text(«Estado: Enviado con éxito»);  
  26.             else modelStatus.text(«Estado: Enviado con error. Compruebe que ha rellenado todos los campos»);  
  27.         },  
  28.         error: function(jqXHR, textStatus, error) {  
  29.             $(‘.model-status’).text(«Estado: Error inesperado»);  
  30.         }  
  31.     });  
  32. });  

     

    Solución NO óptima 2

    A priori podría parecer que la solución pasaría por dejar el formulario con el parámetro del tipo del modelo y crearnos un objeto en JavaScript con las propiedades necesarias e ir recogiendo los valores uno por uno de los campos del formulario para posteriormente enviarlos en la acción «Ajax» como el código que explico a continuación. Esta opción está muy cerca de la óptima porque recibimos el modelo en la acción y la validación se la delegamos al ModelState, pero aún sigue sin ser flexible ya que, si añadimos un nuevo campo al formulario, tendríamos que añadir esa nueva propiedad al objeto JavaScript para poder enviarlo y, como sabemos, esto siempre puede llevar a olvidos y/o errores.

    Acción del controlador

  33. [HttpPost] 
  34. public JsonResult Create(Car car) {  
  35.     try {  
  36.         if (!ModelState.IsValid) return Json(false);  
  37.         car.Status = «Solicitados»;  
  38.         return Json(true);  
  39.     } catch {  
  40.         return Json(false);  
  41.     }  
  42. }  

     

    Código JavaScript

  43. $(‘#btn-sendForm’).click(function() {  
  44.     var car = {  
  45.         prop1: document.getElementById(‘brand’).value(),  
  46.         prop2: document.getElementById(‘model’).value(), // …  
  47.     }  
  48.     $.ajax({  
  49.         url: ‘@Url.Action(«ACTION», «CONTROLLER»)’,  
  50.         type: ‘POST’,  
  51.         data: item,  
  52.         success: function(result) {  
  53.             var modelStatus = $(‘.model-status’);  
  54.             if (result) modelStatus.text(«Estado: Enviado con éxito»);  
  55.             else modelStatus.text(«Estado: Enviado con error. Compruebe que ha rellenado todos los campos»);  
  56.         },  
  57.         error: function(jqXHR, textStatus, error) {  
  58.             $(‘.model-status’).text(«Estado: Error inesperado»);  
  59.         }  
  60.     });  
  61. });  

     

    Solución ÓPTIMA

    Por último, vamos a ver la solución que a mi parecer es la óptima para estos casos. Lo que haremos, es tener la acción del controlador como en el caso anterior pero variaremos un poco el JavaScript para enviar todo el formulario de golpe. De esta forma, conseguimos que si tenemos que añadir un nuevo campo al formulario, no nos tengamos que preocupar cómo se envía ni cómo se recoge gracias al ModelBinding

    Acción del controlador

  62. [HttpPost] 
  63. public JsonResult Create(Car car) {  
  64.     try {  
  65.         if (!ModelState.IsValid) return Json(false);  
  66.         car.Status = «Solicitados»;  
  67.         return Json(true);  
  68.     } catch {  
  69.         return Json(false);  
  70.     }  
  71. }  

     

    Código JavaScript

  72. $(‘#btn-sendForm’).click(function() {  
  73.     var formContainer = $(‘#car-form’);  
  74.     $.ajax({  
  75.         url: ‘@Url.Action(«Create», «Car»)’,  
  76.         type: ‘POST’,  
  77.         cache: false,  
  78.         data: formContainer.serialize(),  
  79.         success: function(result) {  
  80.             var modelStatus = $(‘.model-status’);  
  81.             if (result) modelStatus.text(«Estado: Enviado con éxito»);  
  82.             else modelStatus.text(«Estado: Enviado con error. Compruebe que ha rellenado todos los campos»);  
  83.         },  
  84.         error: function(jqXHR, textStatus, error) {  
  85.             $(‘.model-status’).text(«Estado: Error inesperado»);  
  86.         }  
  87.     });  
  88. });  

     

    Como podéis observar, lo que haremos será serializar el formulario completo dentro de la propiedad «data» de la acción «Ajax» con lo que estaremos enviando todos los campos del formulario y, una vez en la acción del controlador, gracias al ModelBinding, el parámetro del modelo, en este caso «Car car» se rellenará de forma automática con todos los valores que procedan, los validamos con el ModelState y hemos acabado. Esto es totalmente flexible a cambios y, por lo tanto, no nos dará dolores de cabeza cuando tengamos que hacer modificaciones en el formulario.

     

    Resumen

    Siempre debemos intentar buscar la solución más óptima y flexible para nuestros desarrollos porque en el futuro, cuando tengamos que mantener el código u otro se encargue de esa tarea, nos alegraremos de haber perdido un poco de tiempo en ello.

    Podéis descargaros una solución simple de ejemplo desde mi GitHub