jueves, febrero 20, 2014

ASP.NET MVC | Obtener controlador actual desde una vista (Tips)

posterHoy os traigo un pequeño Tip que a priori puede ser un poco tonto pero que a más de uno le puede salvar de horas de modificar código o de buscar la aguja en el pajar.

Escenario

Tenemos una aplicación ASP.NET MVC que tiene, dentro de las vistas, llamadas “Ajax” a acciones de la propia aplicación MVC, lo que implicará que tengamos puesto “a fuego” el controlador que queremos llamar.

Ejemplo:

$.ajax({
url: "/MyController/MyAction",
data: { id: myId },
type: "GET"
}).done(function(){
alert('DONE!!');
});
 



NOTA: Siempre hay otras formas de hacerlo más elegante.


 


Problema


Qué ocurriría si:



  • Cambiamos la acción a otro controlador
  • Cambiamos el nombre del controlador
  • Usamos la gran herramienta de todo developer “Copy/Paste” y ponemos este método en otras vistas de otros controladores

Bueno, para todas las opciones, lo que ocurre es que tendremos que estar atentos de cambiar el controlador en la “url” que estamos usando en la llamada “ajax” y esto a veces se nos puede pasar por alto y tenernos un buen rato buscando la solución al problema de que de repente no nos funcione nuestra llamada.


 


Solución


Puede haber muchas soluciones, unas más elegantes que otras como por ejemplo he visto el tener un fichero de recursos con las acciones y sus “url” correctas lo que nos permitiría tener centralizadas todas las posibles llamadas que hagamos y tan sólo tendríamos que pasarle desde el controller las acciones que va a llamar la vista. Pero no es eso lo que yo voy a exponer, sino que en este caso quiero explicar cómo hacer referencia al controlador actual desde la propia vista, con lo que nos ahorraríamos los problemas de un cambio en el controlador.


¿Y cómo conseguimos saber el controlador actual? Pues con una sencilla línea de código.

@HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString()



 


Con esto, nuestra llamada Ajax podría quedar de la siguiente forma:

$.ajax({
url: '@Url.Action(“MyAction”, HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString())’,
data: { id: myId },
type: "GET"
}).done(function(){
alert('DONE!!');
});



 


NOTA: A algunos os podrá extrañar ver el código “razor” dentro de un bloque JavaScript… ¿funcionará? La respuesta es que sí, puesto que razor es capaz de identificar casi siempre el código de que le corresponde después de una @, lo que nos permite hacer cosas tan “fascinantes” y productivas como esta. Pero tened cuidado con no abusar que al final puede ser peor el remedio que la enfermedad.

viernes, enero 31, 2014

Windows Phone 8 | Cómo enviar correos con Email Compose Task

Este es el segundo artículo de la serie que empecé explicando cómo enviar SMS en Windows Phone. En esta ocasión le toca el turno al envío de correo electrónico.

Escenario

Supongamos que tenemos una aplicación de Windows Phone en la que que queremos compartir un contenido por medio del correo electrónico.

 

Solución

Windows Phone dispone de EmailComposeTask que se encuentra dentro del espacio de nombres Microsoft.Phone.Tasks y que nos va a permitir realizar el envío de un correo electrónico de forma simple y rápida.

Para el ejemplo, he puesto un botón al que hay que asignar el evento Click o Tap (Para lo que necesitamos hacer da lo mismo el que usemos).

Email-Compose-Task-Sample-Aplication

 

Dentro del evento click, habrá que hacer uso de la clase EmailComposeTask para realizar la tarea de envío de correo.

   1:          private void btnEmail_Click(object sender, RoutedEventArgs e)
   2:          {
   3:              EmailComposeTask email = new EmailComposeTask();
   4:   
   5:              email.Subject = "Email subject";
   6:              email.Body = "Email body";
   7:              email.To = "johndoe@example.com";
   8:              email.Cc = "copyto@example.com";
   9:              email.Bcc = "hiddencopyto@example.com";
  10:   
  11:              email.Show();
  12:          }



 


Como se puede observar, lo único que se hace es crear una instancia de la clase EmailComposeTask y establecer un valor para las propiedades que tiene. Finalmente se realiza una llamada al método Show que lanzará la aplicación del envío de correo electrónico del sistema.


NOTA: En el emulador se mostrará un error por lo que habrá que realizar la prueba en un dispositivo.


Si probamos la aplicación, veremos que al presionar el botón se abrirá la aplicación de envío de correo del sistema, donde podremos modificar los datos del correo, adjuntar archivos, cancelarlo y enviarlo.


Email-Compose-Task-Send-Email



NOTA: Si no se tiene ninguna cuenta de correo configurada, el sistema mostrará un mensaje al usuario indicándole que debe configurarla.


 


Ha sido realmente sencillo y espero que os sea útil. Podéis descargaros el proyecto de ejemplo (Email) desde aquí donde además tenéis el resto de ejemplos que vaya publicando.


download-code


 


Artículos de la serie













Banner-SMS[6]
Banner-Email[8]
Banner-ShareLink[5]
Banner-Status
Banner-Media

Windows Phone 8 | Cómo enviar mensajes SMS con SMS Compose Task

Todos aquellos que desarrollen aplicaciones para móviles sabrán que algo muy importante en prácticamente cualquier aplicación es disponer de opciones para compartir algo, un contenido, un logro, una imagen, … ya que permite que la aplicación esté más viva y que anime a otros usuarios a descargarla y usarla. Con este artículo, en el que explicaré cómo enviar un SMS desde una aplicación para Windows Phone, quiero iniciar una serie de artículos en los que iré mostrando diferentes formas de compartir contenido acompañándolos de su código fuente.

Escenario

Supongamos que tenemos una aplicación de Windows Phone en la que que queremos compartir un contenido, en este caso un texto, con otra persona vía SMS.

Solución

Una de las grandes características de Windows Phone es la facilidad para hacer cualquier tarea y, para los desarrolladores no iba a ser menos, de hecho, es extremadamente sencillo.

Dentro del espacio de nombres Microsoft.Phone.Tasks, disponemos de un gran número de tareas relacionadas con funcionalidades como enviar SMS’s a la que le corresponde la clase SmsComposeTask que será la que necesitaremos usar para alcanzar nuestro objetivo.

Para establecer un ejemplo, comenzaré por crear un botón al que asignaremos el evento Click o Tap (Para lo que necesitamos hacer da lo mismo el que usemos).

SMS-Compose-Task-Sample-Aplication

 

Dentro del evento, tenemos que escribir el siguiente y complejísimo código.

1: private void btnSendSMS_Click(object sender, RoutedEventArgs e)
2: { 
3: SmsComposeTask sms = new SmsComposeTask(); 
4: sms.To = "600123456"; 
5: sms.Body = "Testing SMS compose Task"; 
6: sms.Show(); 
7: } 




 


Como podéis observar, lo que hacemos es crear una instancia de la clase SmsComposeTask y le asignamos un receptor “To”, el cuerpo del SMS “Body” y finalmente realizamos la llamada al método “Show” que será el encargado de abrir la tarea de envío de SMS’s


Una vez hecho, ejecutamos la aplicación y, al presionar el botón se abrirá la tarea de envío de SMS del sistema, lo que nos permitirá cambiar el receptor, editar el mensaje, enviarlo, añadir elementos como imágenes, vídeos, sonido, etc…



 


Ha sido realmente sencillo y espero que os sea útil. Podéis descargaros el proyecto desde aquí, además, progresivamente le iré añadiendo los nuevos ejemplos que vaya realizando.


download-code


 


NOTA: En el emulador el mensaje siempre aparecerá como enviado correctamente aunque realmente no se haya realizado el envío. Esto se debe a que el emulador simula GSM y la SIM. En un terminal, si el mensaje no se envía correctamente, aparecerá una notificación indicándolo.


 


Artículos de la serie













Banner-SMS
Banner-Email
Banner-ShareLink
Banner-Status
Banner-Media

Windows Phone | Diferentes plantillas de elementos en LongListSelector con DataTemplateSelector

Escenario

Puede darse el caso en el que tengamos que aplicar diferentes plantillas a los elementos de una misma lista, en este artículo un LongListSelector. Para ello, tenemos varios métodos como por ejemplo usar Converters e ir aplicando distintos valores de propiedades según convenga (Lo explicaré en un próximo artículo), pero esto tiene un inconveniente y es que tendríamos que crear tantos converters como propiedades distintas queramos cambiar.

TemplateSelector

 

Solución

Bueno, ¿y cuál es la solución? Pues no es otra que hacer un uso un poco más avanzado de las herramientas de las que disponemos y crear un DataTemplateSelector que no es más que un “control” que nos permite crear un selector. Así pues, comencemos a ver cómo irlo creando paso a paso.

NOTA: En WPF y en Windows 8 se puede usar sin necesidad de este Workaround

 

Los datos

Bueno, para empezar debemos definir los datos con los que vamos a trabajar para poder determinar cuál va a ser el elemento diferenciador entre ellos. En este caso, he usado la lista de Speakers de las “Christmas Windows Phone Sessions” y les he añadido una propiedad “Type” que define el área a la que pertenecen entre Business, Developer y Designer. Así pues, tenemos a Alejandro Campos Magencio en el área Business, a mi como Designer y el resto como Developer. Y lo que quiero es diferenciarlos por el color de fondo de su nombre tal y como se muestra en la imagen de “resultado”.

El modelo que he creado es el siguiente:

public class SpeakerViewModel
{
    public int Id { get; set; }
    public string Type { get; set; }
    public string Title { get; set; }
    public string ProfilePhoto { get; set; }
}

 


Todos los Speakers los estoy recogiendo en una ObservableCollection<SpeakerViewModel> que tengo en mi ViewModel principal para, de esta forma, fácilmente pasárselo a la página de detalles (en la que no vamos a entrar ahora)



public void LoadSpeakers()
{
    this.Speakers.Add(new SpeakerViewModel() { Id = 1, Title = "Alejandro Campos Magencio", Type = "Business", ProfilePhoto = "/Assets/Speakers/Alejandro.jpg" });
    this.Speakers.Add(new SpeakerViewModel() { Id = 2, Title = "Josué Yeray", Type = "Developer", ProfilePhoto = "/Assets/Speakers/JosueYeray.jpg" });
    this.Speakers.Add(new SpeakerViewModel() { Id = 3, Title = "Roberto Luis Bisbé", Type = "Developer", ProfilePhoto = "/Assets/Speakers/RobertoLuisBisbe.jpg" });
    this.Speakers.Add(new SpeakerViewModel() { Id = 4, Title = "Javier Suárez Ruiz", Type = "Developer", ProfilePhoto = "/Assets/Speakers/JavierSuarez.jpg" });
    this.Speakers.Add(new SpeakerViewModel() { Id = 5, Title = "Rafa Serna", Type = "Developer", ProfilePhoto = "/Assets/Speakers/RafaSerna.jpg" });
    this.Speakers.Add(new SpeakerViewModel() { Id = 6, Title = "Santiago Porras", Type = "Designer", ProfilePhoto = "/Assets/Speakers/SantiagoPorras.jpg" });
 
}

 


Además de estos datos, que son los que se muestran al ejecutar la aplicación, como estamos diseñando cómo se verán los elementos querremos verlos en tiempo de edición, así que nos crearemos los Mockups dentro de un fichero XAML que referenciaremos en nuestra poniendo en la cabecera su referencia.


Referencia en la vista



d:DataContext="{d:DesignData SampleData/MainViewModelSampleData.xaml}"

 


Datos de ejemplo



<vm:MainViewModel.Speakers>
    <vm:SpeakerViewModel Id="1" Title="Alejandro Campos Magencio"   Type="Business" ProfilePhoto="/Assets/Speakers/Alejandro.jpg"/>
    <vm:SpeakerViewModel Id="2" Title="Josué Yeray"   Type="Developer" ProfilePhoto="/Assets/Speakers/JosueYeray.jpg"/>
    <vm:SpeakerViewModel Id="3" Title="Roberto Luis Bisbé" Type="Developer" ProfilePhoto="/Assets/Speakers/RobertoLuisBisbe.jpg"/>
    <vm:SpeakerViewModel Id="4" Title="Javier Suárez Ruiz"  Type="Developer" ProfilePhoto="/Assets/Speakers/JavierSuarez.jpg"/>
    <vm:SpeakerViewModel Id="5" Title="Rafa Serna"  Type="Developer" ProfilePhoto="/Assets/Speakers/RafaSerna.jpg"/>
    <vm:SpeakerViewModel Id="6" Title="Santiago Porras"   Type="Designer" ProfilePhoto="/Assets/Speakers/SantiagoPorras.jpg"/>
</vm:MainViewModel.Speakers>

NOTA: Si hemos usado una plantilla con datos al crear la aplicación (Windows Phone Databound App, Windows Phone Pivot App o Windows Phone Panorama App) dispondremos de un archivo “SampleData/MainViewModelSampleData” que ya está asociado a la vista MainPage.xaml y que podremos usar para realizar esta acción.


 


Una vez hayamos hecho esto y teniendo un LongListSelector enlazado a los datos, podremos ver que nos aparecen elementos en la Vista Diseño, con lo que podremos darle color a los elementos.


 


Implementar la clase DataTemplateSelector


Ahora que ya tenemos los datos, debemos crear la base del selector de plantillas que debe heredar de “ContentControl” que se encuentra dentro del espacio de nombres “System.Windows.Controls”.



public abstract class DataTemplateSelector : ContentControl
{
    public virtual DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        return null;
    }
 
    protected override void OnContentChanged(object oldContent, object newContent)
    {
        base.OnContentChanged(oldContent, newContent);
 
        ContentTemplate = SelectTemplate(newContent, this);
    }
}

Como se puede apreciar, hay dos métodos virtuales que debemos implementar al heredar de ContentControl



  • SelectTemplate: Selecciona una plantilla (De momento lo dejamos como null porque lo implementaremos más adelante en otra clase).
  • OnContentChanged: Define la plantilla que se muestra al cambiar el contenido, cosa que sucede cuando se rellenan los datos con el Binding. Esta es la que usaremos para nuestro ejemplo.

 


Implementar la clase que gestione los elementos, ItemDataTemplateSelector


Continuamos con el trabajo creando la clase que realmente va a realizar el cambio de plantilla atendiendo al campo “Type” del modelo SpeakerViewModel.


Esta clase, que he llamado ItemDataTemplateSelector, hereda de DataTemplateSelector y contiene, una propiedad por cada diferente plantilla y la sobreescritura del método SelectTemplate que atiende al campo “Type” para definir la plantilla que se ha de mostrar.



public class ItemDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate Designer
    {
        get;
        set;
    }
 
    public DataTemplate Developer
    {
        get;
        set;
    }
 
    public DataTemplate Business
    {
        get;
        set;
    }
 
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        SpeakerViewModel speaker = item as SpeakerViewModel;
        if (speaker != null)
        {
            if (speaker.Type == "Designer")
                return Designer;
            else if (speaker.Type == "Developer")
                return Developer;
            else 
                return Business;
        }
 
        return base.SelectTemplate(item, container);
    }
}

 


Usar las diferentes plantillas gestionadas por ItemDataTemplateSelector


Ya sólo nos queda crear las plantillas e indicarle al LongListSelector que haga uso de ellas.


En primer lugar, tenemos que definir el espacio de nombres en el que hemos incluido el selector de plantillas ItemDataTemplateSelector que, en mi caso, he puesto en una carpeta Helpers. Así pues, en la cabecera de la vista donde tengamos el LongListSelector, debemos añadir la siguiente línea:



xmlns:local="clr-namespace:Sample_2.Helpers"
Nótese que “local” puede ser sustituido por lo que queráis, pero tenéis que tenerlo en cuenta más adelante.

El siguiente paso, es crear las plantillas dentro del LongListSelector, haciendo referencia a las propiedades correspondientes a cada una de las plantillas que definimos en ItemDataTemplateSelector, como por ejemplo “local:ItemDataTemplateSelector.Developer”.



<phone:LongListSelector Grid.Row="1" ItemsSource="{Binding Speakers}" LayoutMode="Grid" GridCellSize="180,180">
    <phone:LongListSelector.ItemTemplate>
        <DataTemplate>
            <local:ItemDataTemplateSelector Content="{Binding}" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
                <local:ItemDataTemplateSelector.Developer>
                    <DataTemplate>
                        <Grid Height="180" Margin="5" Width="180" Background="#FFE00109">
                            <Border BorderBrush="Black" Height="50" VerticalAlignment="Bottom" Background="#FFE00109">
                                <TextBlock Text="{Binding Title}" Style="{StaticResource PhoneTextExtraLargeStyle}" Foreground="White" FontSize="24" VerticalAlignment="Center"/>
                            </Border>
                        </Grid>
                    </DataTemplate>
                </local:ItemDataTemplateSelector.Developer>
 
                <local:ItemDataTemplateSelector.Designer>
                    <DataTemplate>
                        <Grid Height="180" Margin="5" Width="180" Background="#FF009045">
                            <Border BorderBrush="Black" Height="50" VerticalAlignment="Bottom" Background="#FF009045">
                                <TextBlock Text="{Binding Title}" Style="{StaticResource PhoneTextExtraLargeStyle}" Foreground="White" FontSize="24" VerticalAlignment="Center"/>
                            </Border>
                        </Grid>
                    </DataTemplate>
                </local:ItemDataTemplateSelector.Designer>
                <local:ItemDataTemplateSelector.Business>
                    <DataTemplate>
                        <Grid Height="180" Margin="5" Width="180" Background="#FF7b057e">
                            <Border BorderBrush="Black" Height="50" VerticalAlignment="Bottom" Background="#FF7b057e">
                                <TextBlock Text="{Binding Title}" Style="{StaticResource PhoneTextExtraLargeStyle}" Foreground="White" FontSize="24" VerticalAlignment="Center"/>
                            </Border>
                        </Grid>
                    </DataTemplate>
                </local:ItemDataTemplateSelector.Business>
            </local:ItemDataTemplateSelector>
        </DataTemplate>
    </phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>

Llegados a este punto, ya tenemos todo preparado para ejecutar el proyecto y ver el resultado.


TemplateSelector


 


Estructura final del proyecto


La estructura final del proyecto, debería contener algo como lo que muestro a continuación, con las dos clases que hemos creado para la selección de la plantilla, los ViewModel necesarios, los datos de ejemplo y la vista principal MainPage.xaml.


Solution


 


Código


Lo pondré en un próximo artículo con los recursos del Webcast en el que hablé de esto, siendo la solución que colgaré, más avanzada y con un aspecto algo diferente…


result-enhanced


 


Enjoy it!