Validando ASP.NET Web Form con DataAnnotation en Ambos lado(Cliente y Servidor).

DataAnnotation es el namespace que desde el SP1 de .NET Framework 3.5 ha sido incluido para hacer validaciones a los campos definidos en un modelo de datos (Entity Framework por Ejemplo), la funcionalidad se muestra mucho en ASP.NET MVC y se utiliza definiendo atributos de validacion a un objeto; atributos que son aprovechados en ASP.NET MVC para hacer validaciones automaticas. En estos dias estoy involucrado en un proyecto de Webform que contiene un monton de clases y objetos, es por eso que he querido utilizar esta funcionalidad para reutilizar codigo disminuyendo considerablemente la cantidad de validadores que conlleva cada formulario web.

Si se busca en internet vemos que en la version actual de ASP.NET MVC (version 2) se logra combinar DataAnnotation con JQuery Validators para hacer validaciones tanto del lado del servidor como del lado del cliente con el minimo esfuerzo de programacion, pero si esa funcionalidad se quiere incorporar en ASP.NET Webform, se hace cuesta arriba buscar alternativas para hacer un trabajo similar.  Es por eso que he decidio compartir este codigo implementado luego de algunas horas de investigacion por parte de mis compañeros y yo involucrados en el proyecto.

 

La finalidad es la siguiente:

  • Hacer uso de DataAnnotation para centralizar las validaciones de los objetos.
  • Simplificar y Retulizar el codigo utilizado para validacion.
  • Tener Validacion del lado del servidor, asi como tambien del lado del cliente con el minimo esfuerzo.

 

Incluyendo el namespace System.ComponentModel.DataAnnotations en nuestra clase de personas podemos hacer lo siguiente:

public class Person
{

//Public Properties
[Display(Name = "Nombre")]
[Required(ErrorMessage = "El nombre es requerido.")]
[StringLength(35)]
public string Name { get; set; }

[Display(Name = "Apellido")]
[Required(ErrorMessage = "El apellido es requerido.")]
[StringLength(35)]
public string LastName { get; set; }

[Display(Name = "Edad")]
[Required(ErrorMessage = "La edad es requerida.")]
[Range(typeof(Int32), "18", "65",
ErrorMessage = "La edad debe ser entre 18 y 65 años.")]
public int Age { get; set; }

[Display(Name = "Email")]
[RegularExpression(@"w+([-+.']w+)*@w+([-.]w+)*.w+([-.]w+)*",
ErrorMessage = "El email es inválido.")]
public string Email { get; set; }

public Person()
{

}
}

 

 

Como podemos observar ante de cada propiedad hay algunos atributos  que son colocados de acuerdo a los tipo de validacion que querramos hacer.  Una vez incluido los atributos crearemos un “Custom Validator” que procese cada atributo de la propiedad segun el ASP.NET Control asociado a dicha propiedad.

 

public class DACustomVal : BaseValidator
{

public string PropertyName { get; set; }
public string SourceType { get; set; }

protected override bool EvaluateIsValid()
{
//Obtenemos la info del tipo, propiedades y del control.
Type objType = Type.GetType(SourceType, true, true);
PropertyInfo propInfo = objType.GetProperty(PropertyName);
Control control = this.FindControl(this.ControlToValidate);

//Verificamos si el control es de tipo textbox.
if (control is TextBox)
{
TextBox txt = this.FindControl(this.ControlToValidate) as TextBox;
foreach (ValidationAttribute attr in
propInfo.GetCustomAttributes(typeof(ValidationAttribute), true).OfType<ValidationAttribute>())
{
if (!attr.IsValid(txt.Text))
{
//this.Text = attr.ErrorMessage;
this.ErrorMessage = attr.ErrorMessage;
return false;
}
}
}
//Verificamos si el control es un dropdownlist.
else if (control is DropDownList)
{
DropDownList ddl = this.FindControl(this.ControlToValidate) as DropDownList;
foreach (ValidationAttribute attr in
propInfo.GetCustomAttributes(typeof(ValidationAttribute), true).OfType<ValidationAttribute>())
{
if (!attr.IsValid(ddl.SelectedValue))
{
this.Text = attr.ErrorMessage;
return false;
}
}
}


return true;
}

}

 

Una vez conluido este “Custom Validator” podemos hacer uso de este en nuestro formulario web, como se exibe a continuación:

 

 <fieldset class="general-form">
<
h4>Registro de Personas</h4>
<
asp:ValidationSummary ID="vs" CssClass="error" runat="server" DisplayMode="BulletList" />
<
p>
<
label for="txtName">Nombre:</label>
<
asp:TextBox runat="server" ID="txtName" />
<
CustomDAVal:DACustomVal ID="cvName" runat="server"
ControlToValidate
="txtName" PropertyName="Name" SourceType="Objects.Person" />
</
p>
<
p>
<
label for="txtApellido">Apellido:</label>
<
asp:TextBox runat="server" ID="txtApellido" />
<
CustomDAVal:DACustomVal ID="DACustomVal1" runat="server"
ControlToValidate
="txtApellido" PropertyName="LastName" SourceType="Objects.Person" />
</
p>
<
p>
<
label for="txtEdad">Edad:</label>
<
asp:TextBox runat="server" ID="txtEdad" />
<
CustomDAVal:DACustomVal ID="DACustomVal2" runat="server"
ControlToValidate="txtEdad" PropertyName="Age" SourceType="Objects.Person" />
</
p>
<
p>
<
label for="txtEmail">Email:</label>
<
asp:TextBox runat="server" ID="txtEmail" />
<
CustomDAVal:DACustomVal ID="DACustomVal3" runat="server"
ControlToValidate="txtEmail" PropertyName="Email" SourceType="Objects.Person" />
</
p>
<
p>
<
asp:Button Text="Guardar" ID="btnSave" runat="server" CssClass="button"
Height="31px" Width="86px" />
</
p>
</
fieldset>

 

 <CustomDAVal:DACustomVal>  representa mi “Custom Validator” el cual asocia el control de ASP.NET con la propiedad del objeto.   En este punto ya contamos con la validacion del lado del servidor, en este caso usamos un “Validation Summary” (El class hide evita que el texto se despligue al lado de los textbox, un issue que se puede manejar.).  Como la validación que hacemos es del lado del servidor, debemos hacer postback al servidor para que los validadores funciones, tal y como se muestra en la pantalla.

 

VS[1]

 

Para que esta misma funcionalidad se aproveche en el lado del cliente y evitar un postback al servidor, se ha incluido en el metodo “OnPreRender” del “Custom Validator” algunas lineas de código que  itera sobre los controles del formulario y de forma dinamica incluye los validadores de .NET de acuerdo a los atributos definidos en cada una de las propiedades.

 

protected override void OnPreRender(EventArgs e)
{
if (this.EnableClientScript == true) {

//Para que los validadores no escriban nada del lado del control,
//asignamos este valor a la propiedad text de cada validador.
string emptyVal = "&nbsp;";

//Obtenemos la info del tipo, propiedades y del control.
Type objType = Type.GetType(SourceType, true, true);
PropertyInfo propInfo = objType.GetProperty(PropertyName);
Control control = this.FindControl(this.ControlToValidate);

foreach (object attr in propInfo.GetCustomAttributes(false))
{

if (attr is RequiredAttribute)
{
RequiredAttribute reqAttr = (RequiredAttribute)attr;

// Create requiredFieldValidator
RequiredFieldValidator rfVal = new RequiredFieldValidator();
rfVal.ControlToValidate = this.ControlToValidate;
rfVal.ErrorMessage = reqAttr.ErrorMessage;
rfVal.Text = emptyVal;
rfVal.ID = String.Format("rfv_{0}", PropertyName);
rfVal.ValidationGroup = this.ValidationGroup;

if (control is DropDownList)
rfVal.InitialValue = "-1";

this.Controls.Add(rfVal);
}
else if (attr is StringLengthAttribute){

//Si tenemos un atributo de maximo de caracteres le aplicamos ese atributo a la propiedad del texbox.
StringLengthAttribute slAttr = (StringLengthAttribute)attr;

if (this.FindControl(this.ControlToValidate) is TextBox){
((TextBox)this.FindControl(this.ControlToValidate)).MaxLength = slAttr.MaximumLength;
}

}
else if (attr is RegularExpressionAttribute){

RegularExpressionAttribute rexAttr = (RegularExpressionAttribute)attr;
RegularExpressionValidator rexVal = new RegularExpressionValidator();

rexVal.ControlToValidate = this.ControlToValidate;
rexVal.EnableClientScript = true;
rexVal.ErrorMessage = rexAttr.ErrorMessage;
rexVal.Text = emptyVal;
rexVal.ValidationExpression = rexAttr.Pattern;
rexVal.ID = String.Format("rexv_{0}", PropertyName);
rexVal.ValidationGroup = this.ValidationGroup;

this.Controls.Add(rexVal);
}
else if (attr is RangeAttribute)
{

RangeAttribute ranAttr = (RangeAttribute)attr;
RangeValidator ranVal = new RangeValidator();

ranVal.ErrorMessage = ranAttr.ErrorMessage;
ranVal.Text = emptyVal;
ranVal.ControlToValidate = this.ControlToValidate;
ranVal.ValidationGroup = this.ValidationGroup;
ranVal.ID = String.Format("ranv_{0}", PropertyName);
ranVal.EnableClientScript = true;
ranVal.MinimumValue = ranAttr.Minimum.ToString();
ranVal.MaximumValue = ranAttr.Maximum.ToString();


switch (ranAttr.OperandType.Name) {
case "Int32":
ranVal.Type = ValidationDataType.Integer;
break;
case "Decimal":
ranVal.Type = ValidationDataType.Currency;
break;
case "Double":
ranVal.Type = ValidationDataType.Double;
break;
case "DateTime":
ranVal.Type = ValidationDataType.Date;
break;
default:
ranVal.Type = ValidationDataType.String;
break;
}

this.Controls.Add(ranVal);

}

}

}

base.OnPreRender(e);
}

 

Con este código automáticamente agregamos los controles necesarios para tener validaciones del lado del cliente incluyendo los validadores de: Requerido, Rango, RegularExpression y adicional a esto controlamos el máximo de caracteres que puede recibir un textbox con el atributo “StringLengthAttribute”.  Al final el formulario mantiene el mismo aspecto pero llevando las validaciones al lado del cliente para evitar los molestos postback.

 

 VC[1]

Puede descargar el website completo desde Aquí, aunque está hecho en VS2010, ASP.NET 4.0 el código es totalmente compatible con VS2008 y .NET Framework 3.5 SP1.

Subiendo archivos asíncrono en asp.net con el control “AsyncFileUpload”

Recientemente se liberó una nueva versión del famoso “Ajax Control Toolkit”, adicional a los arreglos y estabilidad que exhibe el release, este incluye dos nuevos controles: SEADRAGON y ASYNCFILEUPLOAD de este ultimo dedicaré este post.

Para nadie es un secreto que uno de los dolores de cabeza de los desarrolladores que usan ASP.NET AJAX, específicamente los “UpdatePanels” es la limitación de poder incluir dentro de este, un control de “FileUpload” para la carga de archivos. En los buscadores y foros te daras cuenta que un gran numero de desarrolladores ha tenido que hacer implementaciones complejas, comprar control o desistir de hacer una carga de archivo asíncronas dentro del update panel. Para este problema los chicos del AJAX Control Toolkit desarrollaron el control “AsyncFileUpload” que es un control bien sencillo de implementar y además mantiene la características de los ya conocidos controles del toolkit.

Basicamente el control se define así:

<toolkit:AsyncFileUpload ID="AsyncFileUpload1" runat="server" 
OnClientUploadError="uploadError"
OnClientUploadComplete="uploadComplete"
UploaderStyle="Modern"
ThrobberID="Throbber" UploadingBackColor="#CCFFFF"
CompleteBackColor="Aqua" />

Este control está compuesto por los siguientes:

Eventos

  • UploadedComplete: evento que ocurre en el servidor cuando la cargar del archivo ha sido satisfactorio.
  • UploadedFileError: evento que ocurre en el servidor cuando la carga del archivo ha generado algún error.

 

Propiedades

  • CompleteBackColor: El color de fondo del control cuando la carga ha sido completada.
  • ContentType: Se obtiene el tipo de contenido (MIME Content Type) del archivo cargado.
  • ErrorBackColor: el color de fondo del control cuando la carga ha genrado un error.
  • Filename: se obtiene el nombre del archivo.
  • Hasfile: un boleano que indica si el control tiene archivo o no.
  • OnClientUploadError: el nombre de la funcion de Javascript que se ejecutará si falla la carga.
  • OnClientUploadComplete: el nombre de la funcion de Javascript que se ejecutará cuando se complete la carga.
  • PostedFile: se obtiene un objeto HttpPostedFile con acceso al archivo cargado.
  • ThrobberID: (debió ser ProgressImage) Es el ID del control que mostrará el progreso.
  • UploaderStyle: define la apariencia del control (Tradicional o Moderno).
  • UploadingBackColor: color de fondo del control cuando está cargando el archivo.
  • Width: define el largo del control.

 

Metodos

  • SaveAS(archivo as string): Guarda el archivo pasandole como parametro la ruta y el nombre del archivo.

 

En la implementación que anexo en este post el HTML se observa de esta forma:

<form id="form1" runat="server">
<
asp:ScriptManager ID="sm" runat="server" />
<
h1>
Carga de archivo asíncrona</h1>
<
div id="demoTitle">
Demostración Control "AsyncFileUpload"
</div>
<
div id="uploadArea">
<
toolkit:AsyncFileUpload ID="AsyncFU"
runat="server"
OnClientUploadError="uploadError"
OnClientUploadComplete="uploadComplete"
UploaderStyle="Modern"
ThrobberID="Throbber"
UploadingBackColor="#CCFFFF"
CompleteBackColor="AliceBlue" />
<
div id="Throbber" runat="server"
style="display: none;">
<
img align="middle" alt="" src="indicator.gif" />
</
div>
</
div>
<
br />
<
br />
<
div>
<
strong>Ultimo evento del lado del servidor:</strong></div>
<
div id="msgServerSide" runat="server">
</
div>
<
br />
<
br />
<
div>
<
strong>Eventos del lado del cliente:</strong></div>
<
div id="msgClientSide" runat="server" style="display: none">
</
div>
</
form>

 

Estas funciones de javascript le permiten al control crear comportamientos y funcionalidades directamente en el cliente:

<script type="text/javascript">
function
uploadError(sender, args) {
var divmsg = $get("<%= msgClientSide.ClientID %>");
divmsg.className = "error";
divmsg.style.display = 'block';
divmsg.innerHTML = 'File: ' + args.get_fileName() +
'<br/>' + 'Error: '
+ args.get_errorMessage();

}
function uploadComplete(sender, args) {
var divmsg = $get("<%= msgClientSide.ClientID %>");
divmsg.className = "success";
divmsg.style.display = 'block';
divmsg.innerHTML = 'File: ' + args.get_fileName() + '<br/>'
+ 'Length: ' + args.get_length() + 'bytes';
}

</script>

Del lado del cliente manejamos los eventos inyectando scripts a través del scriptmanager.

Protected Sub AsyncFU_UploadedComplete(ByVal sender As Object, _
ByVal e As AjaxControlToolkit.AsyncFileUploadEventArgs) _
Handles AsyncFU.UploadedComplete

Dim myScript = "top.$get('" & msgServerSide.ClientID & _
"').innerHTML = 'Estatus: Satisfactorio <br/> Archivo: " & e.filename & _
"<br/> Tamaño: " & AsyncFU.FileBytes.Length.ToString() & "';"
ScriptManager.RegisterClientScriptBlock(Me, Me.GetType(), "size", myScript, True)

'AsyncFU.SaveAs("AQUI VA LA RUTA PARA GRABAR EL ARCHIVO")

End Sub

Protected Sub
AsyncFU_UploadedFileError(ByVal sender As Object, _
ByVal e As AjaxControlToolkit.AsyncFileUploadEventArgs) _
Handles AsyncFU.UploadedFileError

Dim myScript = "top.$get('" & msgServerSide.ClientID & _
"').innerHTML = 'Error: " & e.statusMessage & "';"
ScriptManager.RegisterClientScriptBlock(Me, Me.GetType(), "error", myScript, True)

End Sub

 

Desde aquí puedes descargar el proyecto que utiliza el control.

 

Conclusiones

Pros:

  • Permite usar el control dentro de un Updatepanel.
  • Se pueden manejar funcionalidades del lado del cliente.
  • Soluciona en gran parte el problema de cargar de archivo asíncrono en asp.net.
  • Si ocurre un error la ruta del archivo seleccionado persiste en el control.
  • Permite tener acceso a diferente estado cuando se carga el archivo.

Contra:

  • No tiene la capacidad para múltiples archivo.
  • Por alguna razón cuando seleccionas el archivo la carga se hace automática.

Configurando SQL Server 2008 para enviar emails (paso a paso)

Hoy en día la mayorías de las aplicaciones hacen uso de los servicios de Exchange o SMTP para enviar correos electrónicos a los usuarios, en muchas ocasiones el envío del correo lo hacemos a través de la aplicación misma pero existen escenarios en donde es preferible hacer el envío de correos desde nuestro repositorio de datos.

A continuación mostraré paso a paso como configurar el servicio de correos en SQL Server 2008, como asignar permisos a usuarios de base de datos para que utilicen el profile que hemos creado para el envío de correos.

Paso 1: Creación del “Profile” y el “Account”, en el “Managment Studio” click derecho sobre “Database Mail

0[1]
Paso 2
2[1]
Si es la primera vez que configura el servicio, entonces debes activarlo dando click en la opción “yes”3[1]
4[1]
5[1]
6[1]
7[1]
8[1]
9[1]

 

 

 

 

 

 

 

 

 

 

Paso 2: Enviar un Email, despues que la configuracion esta hecha existen dos formas de probar nuestro servicio, el primero es desde la ventana “Send Test Email”  o ejecutando el procedure “sp_send_dbmail” veamos los ejemplos:

10[1]
El envio desde T-SQL es:

EXEC msdb.dbo.sp_send_dbmail @profile_name='BlogProfile',
    @recipients= 'prueba@dominio.com',
    @subject= 'Mensaje de Prueba',
    @body= 'Este es el cuerpo del mensaje y escribo un texto de prueba.'

La lista completa de parametros que recibe este “Store Procedure” puedes conseguirlo desde aquí.

 

Paso 3: Asingación de Permisos, Sucede que esta configuración y la prueba ls hice con un usuario “sysadmin”, pero ni necesitamos que cualquier usuario en nuestra base de datos utilice este “Profile” para enviar email debemos de otorgarle el permiso ejecutando este script:

USE msdb
GO
EXEC sp_adduser @loginame='AQUI VA EL USERNAME', 
@grpname='DatabaseMailUserRole' GO

El administrador de base de datos puede monitorear los mensajes enviados a traves de las siguientes vistas o tablas que estan en la base de datos “MSDB”

  • sysmail_allitems : verifica todos los items enviados.
  • sysmail_faileditems:  los correos que han fallado.
  • sysmail_event_log: El log de eventos de los emails.
  • sysmail_mailattachments: la vista de los attachments.
  • entre otros.

 

** Puedes seguirme en twitter

Subiendo y tocando videos en ASP.NET

Hace unos días un compañero me pidió que le ayudara a incluir la funcionalidad de cargar y ver video en un portal de venta de vehículo, los requerimientos eran los siguientes:

  • Permitir al usuario cargar al portal diferentes tipos de video, específicamente los más populares AVI, WMV, MPG, MP4.
  • Hacer encoding de los videos cargados para reducir su tamaño considerablemente a fin de que usuarios con poco ancho de banda puedan ver los videos.
  • Una vez cargado el video, permitir al usuario ver el video convertido.
  • El video cargado por el usuario no puede exceder los 50MB.
  • El típico requerimiento, que los componentes involucrados no alteren los costos del proyecto.

Haciendo una vista rápida de los requerimientos no parece difícil desarrollar este feature, pero la realidad es que aunque es muy popular ver video en los website no es tan fácil como parece. Primero porque hay pocos componentes gratuitos para estos fines, segundo la documentación para hacer esta tarea no es tan abundante en internet (por eso me anime a publicar este articulo) y tercero hacer el encoding en línea hace la tare un poco mas difícil.

Para desarrollar estos requerimientos utilicé las siguientes herramientas:

  1. Visual Studio 2008 (tambien puedes usar Visual Web Developer 2008).
  2. ASP.NET
  3. FFmpeg (para hacer encoding de los videos) la documentación la puede encontrar Aquí
  4. Flowplayer (para ver los videos convertidos a flv) la documentacion la puede encontrar Aquí

 

El “Website Project” creado contiene los directorios:

  • Player: contiene los archivos utilizados para visualizar un video.
  • Videos: almacena los videos, tanto el original cargado por el usuario, asi como tambien el convertido a flv.
  • ffmpeg.exe: el ejecutable utilizado para hacer el encoding a los videos.
  • Dos paginas que detallaremos a continuacion.

 

La primera página “UploadVideo.aspx” se encarga de permitirle al usuario cargar su propio video, esta se compone del HTML especificado más abajo.

 

<form id="form1" runat="server">
    <h1>
        Video Website - Upload Videos</h1>
    <div>
        <asp:FileUpload ID="videoFile" runat="server" />
        &nbsp;<asp:Button ID="btnUpload" runat="server" Text="Upload video" OnClick="btnUpload_Click" />
        <br />
    </div>
    <asp:Label ID="lblErrorVideo" runat="server" EnableViewState="False" CssClass="redbold"></asp:Label>
</form>

 

Si tiene experiencia cargando archivo desde ASP.NET sabrás que por defecto no se pueden cargar archivos que excedan los 4MB por lo que debemos de modificar el web.config de nuestro web.config, específicamente debajo del tag <system.web> de esta forma:

<system.web>
    <httpRuntime maxRequestLength="51200" />

 

El atributo “maxRequestLength” se especifica en KB.

Lo interesante de esta página ocurre en su code behind, observemos:

Variables globales utilzadas en el codigo (esto puede venir del web.config o del cualquier otra configuración).

    //Ruta en donde se van a guardar los videos.
    string videoOriginalPath = "~/Videos/Original/";
    string videoConvertedPath = "~/Videos/Converted/";
 
    //Variables utilizadas para manejar los nombres.
    string videoTmpName = string.Empty;
    string flv = ".flv";
    string videoConvertedName = string.Empty;

 

El código que ejecuta el evento Click del button Upload se encarga de validar la extensiones permitidas (línea 6), que el archivo no exceda los 50MB (línea 13)  y en la línea 26 se hace el encoding y si todo resulta bien, entonces direccionamos a la página de visualización de videos.

 

   1:   protected void btnUpload_Click(object sender, EventArgs e)
   2:      {
   3:          HttpPostedFile file = videoFile.PostedFile;
   4:   
   5:          //Validamnos la extension del archivo
   6:          if (!ValidateVideoExtension(file.FileName))
   7:          {
   8:              lblErrorVideo.Text = "La extension del archivo no es permitido.";
   9:              return;
  10:          }
  11:   
  12:          //Verificamos el tamano del archivo de que no exceda los 50MB.
  13:          if (file.InputStream.Length > 52428800)
  14:          {
  15:              lblErrorVideo.Text = "El video no puede exceder los 50MB";
  16:              return;
  17:          }
  18:   
  19:          //Guardamos el video
  20:          string saveAs = Server.MapPath(videoOriginalPath);
  21:          videoTmpName = Guid.NewGuid().ToString();
  22:          string originalVideo = saveAs + videoTmpName + new FileInfo(file.FileName).Extension;
  23:          file.SaveAs(originalVideo);
  24:   
  25:          //Hacemos el Encondding del video
  26:          if (EncodingVideo(originalVideo)){
  27:              Response.Redirect("MyVideos.aspx?Id=" + videoConvertedName);
  28:          }
  29:          else {
  30:              lblErrorVideo.Text = "Error convirtiendo el video, intente nuevamente";
  31:          }
  32:      }

 

La funcion “ValidateVideoExtension” se límita a verificar la extensión del archivo cargado:

 

   1:   private bool ValidateVideoExtension(string filename)
   2:      {        
   3:          FileInfo info = new FileInfo(filename);
   4:          switch (info.Extension.ToLower())
   5:          {
   6:              case ".mpg":
   7:              case ".wmv":
   8:              case ".avi":
   9:              case ".mp4":
  10:                  return true;
  11:              default:
  12:                  return false;
  13:          }
  14:      }

 

En la función “EncodingVideo” hacemos uso de la Clase “Process” bajo el namespace “System.Diagsnotics”, esta clase nos permite hacer ejecucion de procesos locales o remotos, en este caso la ejecución del ffmpeg.exe.  En la línea 8 se específican los parametros utilizados para el encoding,  la definicion de estos parámetros se encuentran en la documentación del ffmpeg,  un metodo que es imprescindible para este proceso en linea es “encoding.WaitForExit()” el cual espera a que el proceso concluya.  debajo el codigo de esta función.

 

   1:   private bool EncodingVideo(string originalVideo)
   2:      {
   3:          bool value = false;        
   4:          string saveAs = Server.MapPath(videoConvertedPath);
   5:          videoConvertedName = videoTmpName + flv;
   6:   
   7:          //Parametros que se le pasaran al ejecutable para fines de encoding.
   8:          string args = @" -i " + originalVideo + " -b 200 -r 24 -s 320x240 -deinterlace -ab 64k " + saveAs + videoConvertedName;
   9:   
  10:          //Hacemos uso de la clase proxy la cual nos provee acceso directo al ejecutable.
  11:          using (Process enconding = new Process())
  12:          {            
  13:              enconding.StartInfo.WorkingDirectory = Server.MapPath("~/");
  14:              enconding.StartInfo.FileName = Server.MapPath("ffmpeg.exe");
  15:              enconding.StartInfo.Arguments = args;
  16:              enconding.StartInfo.UseShellExecute = false;
  17:              enconding.StartInfo.CreateNoWindow = true;
  18:              enconding.StartInfo.RedirectStandardOutput = false;
  19:              enconding.Start();
  20:              //Como es un proceso en linea debemos esperar a que termine para mostrar el video sino el player dará un error de FileNotFound.
  21:              enconding.WaitForExit();
  22:              value = true;
  23:          }
  24:   
  25:          return value;
  26:   
  27:        }

 

Una vez concluido el proceso de “Encoding” tendremos en la carpeta /Videos/Converted/ el video flv, el cual mostraremos en la segunda página llamada “MyVideo.aspx”, el cual llamaremos pasandole por Querystrings el nombre del video a mostrar.  El HTML es este:

   1:  <head runat="server">
   2:      <title>My Videos Zone</title>
   3:      <!-- Hacemos referencia de la libreria que contiene el flowPlayer -->
   4:      <script src="Player/flowplayer-3.1.3.min.js" type="text/javascript"></script>
   5:  </head>
   6:  <body>
   7:    <h1>Video Website - My Video Zone</h1>
   8:      <form id="frmMain" runat="server">
   9:      <div>
  10:          <script type="text/javascript">
  11:              flowplayer("player", "player/flowplayer-3.1.3.swf");
  12:          </script>
  13:          <!-- player container-->
  14:          <a  id="player" runat="server" style="display: block; width: 320px;>
  15:              height: 240px;"
  16:              
  17:              <!-- Utilizado para colocar una mascara y evitar que el player toque el video automatico. -->
  18:              <img src="Player/flow_eye.jpg" alt="My Video Player" /> 
  19:          </a>
  20:          
  21:      </div>
  22:      </form>
  23:  </body>

 

En la línea 4 se hace referencia a la libreria de FlowPlayer, línea 10 se coloca el player, línea 14 el link sobre cual video hace referencia el player, este se asignará en el code behind de la siguiente manera:

 

   1:   protected void Page_Load(object sender, EventArgs e)
   2:      {
   3:          if (Request["Id"] != string.Empty)
   4:          {
   5:              string video = "~/Videos/Converted/" + Request["Id"].ToString();
   6:              player.HRef = video;
   7:          }
   8:      }

 

El resultado es genial un archivo WMV de 25MB puede ser reducido a 666KB, el proyecto en ejecución se veria

de esta forma

Upload[1] ViewVideo[1]

El codigo fuente puede ser descardo desde Aquí:

Technorati Tags: ,,,