2011-06-20 19 views
8

Todavía un poco nuevo en C# y estoy en la necesidad de algunos punteros en la dirección correcta con este ..¿cómo podría crear una clase de notificación global?

Quiero construir un sistema de notificación en C#/Asp.net que permitirá a los diferentes métodos en todo el sitio para agregar mensajes y tipos de mensajes a alguna lista estática que se pueda enlazar en la carga de la página siguiente. Sería similar a cómo el desbordamiento de pila hace que las notificaciones de banner para logros en cada página carguen (por ejemplo, "ganaste x badge", ganaste y badge "). Alguna idea de cómo podría exponer algún método global que otros simplemente podrían enviar mensajes. añadir ('mensaje', 'tipo de mensaje') con

Editar:?.

Se ha sugerido que utilizo Session.Add("Notificiations", myList); para almacenar los mensajes

Cómo/dónde iría sobre la inicialización que "Notificaciones "list then do list.add() everywhere else?

Respuesta

6

Puedes escribir una clase como esta (no tengo ninguna I DE cerca de mí, así que espero que el código se compilará):

public class MessageHelper 
{ 
    protected const String sessionName = "messages_session"; 
    public List<String> Messages 
    { 
     get 
     { 
      List<string> list; 
      if (Session[sessionName] != null) 
      { 
       list = (List<string>)Session[sessionName]; 
      } 
      else 
      { 
       list = new List<string>(); 
      } 
      Session[sessionName] = list; 
      return list; 
     } 
     set 
     { 
      Session[sessionName] = value; 
     } 
    } 

    public void AddMessage(String message) 
    { 
     List<String> list = this.Messages; 
     list.Add(message); 
     this.Messages = list; 
    } 

} 

Para añadir un mensaje, puede hacer:

MessageHelper messageHelper = new MessageHelper(); 
messageHelper.AddMessage("hello world"); 

(Estos mensajes se almacenan en la sesión, lo que significa usuario específico);

Supongamos que usted tiene literal en su masterpage, donde desea visualizar sus mensajes:

<asp:Literal ID="litMessages" runat="server" /> 

En su MasterPage debe agregar la OnInit Eventhandler:

protected override void OnInit(EventArgs e) 
{ 
    MessageHelper messageHelper = new MessageHelper(); 
    String output = string.Empty; 
    foreach(String message in messageHelper.Messages) 
    { 
    output += String.Format("{0}<br />", message); 
    } 
    this.litMessages.Text = output; 

} 

Esto debería darle una básica descripción general, cómo puede almacenar y mostrar los mensajes. Por supuesto, puede ajustar este código, ya sea agregando un método para eliminar mensajes, o buenos efectos secundarios del cliente (como las notificaciones aquí en StackOverflow. Para saber cómo se hace esto, puede usar la búsqueda. Se ha discutido aquí varias veces). veces)

Espero que esto te ayude.

+0

http://msdn.microsoft.com/en-us/library/ms972429.aspx así como Session.Add ("Notificiations", myList); ¿Cómo voy a inicializar esa lista de "Notificaciones" y anexarla a todos lados? – tester

+0

@tester: Agregué un código a mi respuesta anterior – citronas

+0

impresionante. esto funcionó bien cuando hice 'Session'' HttpContext.Current.Session'. ¡Gracias! – tester

9

Mostrar pancartas emergentes en la parte superior de la página en las devoluciones es bastante claro, pero incluso más genial que eso es usar jQuery y ajax para realizar comprobaciones periódicas con el servidor para ver si el estado de algo ha cambiado o en su caso si el usuario tiene algún mensaje "nuevo".

Esto realmente funciona muy bien cuando tienes un proceso asíncrono ejecutándose en el servidor web y no sabes cuánto tiempo llevará (o sabes con certeza que te tomará un tiempo realmente largo) y entonces no quiero que el navegador de su cliente esté bloqueado esperando por él. Usando javascript y window.setInterval puede establecer que una función ocurra cada 30 segundos (o lo que quiera), y luego tiene dicha función hacer una publicación de AJAX contra el servidor para ver si el proceso asíncrono está completo. En su caso, la publicación de AJAX simplemente le preguntaría al servidor si el usuario tiene algún mensaje "nuevo". Si el usuario tiene mensajes nuevos, es una simple cuestión de usar jQuery para mostrar algún div oculto en la página e informar al usuario que tiene mensajes nuevos.

Es una solución un poco complicada y puede estar más allá de las habilidades de un aficionado, ¡pero las ganancias valen la pena!

  • hace que su aplicación web parecen más con estado y "consciente" de cambios en el servidor
  • prescinde de actualizaciones de página innecesarias que tienden a perturbar la experiencia del usuario

Y como ya se ha señalado, el mejor lugar para almacenar información "global" suele ser la Sesión (solo tenga en cuenta el alcance limitado de la Sesión). MSDN ASP.NET Session State

Sin embargo, si se trata de datos a los que debe acceder cada cliente, puede almacenarlos en la memoria caché de la aplicación. ASP.NET Caching

Por supuesto, tendrá que tener cuidado con la cantidad que está almacenando en la sesión o el caché. Es fácil pegarse un tiro en el pie.

1

Sugiero definir esto como un servicio que se puede implementar como un servicio wcf/web o una interfaz dentro de su aplicación web.

Tener esta característica como un servicio tiene un par de beneficios que incluyen escalabilidad, disponibilidad, etc. Como ejemplo, un cliente que usa su aplicación iphone envía el mensaje y otro cliente que usa su sitio web puede ver eso.

si prefiere el segundo enfoque, necesita usar un marco DI como Ninject y asegúrese de que los marcos DI/Ioc apliquen el patrón singleton en la instancia.

Puedo darle un código de muestra aquí, pero no puedo hacerlo hasta que vuelva a casa.

+0

me encantaría ver ejemplos! – tester

1

Creo que el siguiente código podría ser una buena combinación de varias respuestas. Utiliza un servicio web para recuperar nuevas notificaciones y jquery para extraer notificaciones en un intervalo. Almacena las notificaciones en la sesión de los usuarios.

Lo primero es lo primero, nuestra clase simple "Mensaje" que representa un solo mensaje. Me di cuenta en su pregunta que tendría múltiples tipos de mensajes, así que quería asegurarme de proporcionar una solución que cubriera estos. Mi clase de mensaje tiene solo dos propiedades: Texto y Tipo. Tipo, en mi demostración, se utiliza como el color de fondo del mensaje.

public class Message 
{ 
    public string Text { get; set; } 
    public string Type { get; set; } 
} 

Siguiente es nuestra clase UserMessages que se encarga de guardar y recuperar mensajes. Guarda todos los mensajes en la sesión de los usuarios.

public class UserMessages 
{ 
    protected static string _messageSessionID = "userMessages"; 

    public static List<Message> GetMessages() 
    { 
     var msg = HttpContext.Current.Session[_messageSessionID]; 

     if (msg == null) 
     { 
      return new List<Message>(); 
     } 

     //clear existing messages 
     HttpContext.Current.Session[_messageSessionID] = null; 

     //return messages 
     return (List<Message>)msg; 
    } 

    public static void AddMessage(Message message) 
    { 
     var msg = GetMessages(); 
     msg.Add(message); 

     HttpContext.Current.Session[_messageSessionID] = msg; 
    } 
} 

Para mi demo decidí leer los messaages utilizando AJAX mediante la combinación de un servicio web ASP.Net, ScriptManager y jQuery.Aquí está mi servicio web:

--ASMX File--

<%@ WebService Language="C#" CodeBehind="~/App_Code/MessageService.cs" Class="UserNotification.MessageService" %> 

--cs File--

namespace UserNotification 
{ 
    [WebService(Namespace = "http://tempuri.org/")] 
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 
    [System.Web.Script.Services.ScriptService] 
    public class MessageService : System.Web.Services.WebService 
    { 

     public MessageService() 
     { 
     } 

     [WebMethod(EnableSession = true)] 
     public List<Message> GetMessages() 
     { 
      return UserMessages.GetMessages(); 
     } 
    } 
} 

En mi página aspx he creado un scriptmanager con una referencia a mi servicio, un marcador de posición div para los mensajes y una interfaz de adición mensaje rápido y sucio:

<asp:ScriptManager runat="server"> 
     <Services> 
      <asp:ServiceReference Path="~/MessageService.asmx" /> 
     </Services> 
    </asp:ScriptManager> 
    <div> 
     <div id="msgArea"> 

     </div> 

     <span>Add Message</span> 
     Text: <asp:TextBox ID="txtMessage" runat="server" /> 
     <br /> 
     Type: <asp:TextBox ID="txtType" runat="server" Text="yellow" /> 
     <asp:Button ID="btnAdd" runat="server" Text="Add" onclick="btnAdd_Click" /> 
    </div> 
</form> 

para apoyar la creación de mensajes que añaden t El siguiente método en el código detrás para manejar el botón haga clic en evento:

protected void btnAdd_Click(object sender, EventArgs e) 
{ 
    UserMessages.AddMessage(new Message() {Text = txtMessage.Text, Type = txtType.Text}); 
} 

Ahora para la pieza importante. Para hacer la visualización real de los mensajes escribí el siguiente bloque de javascript (usando principalmente jquery, utilicé v1.4.1, pero puede usar la versión que desee). El temporizador se establece en un intervalo de 30 segundos. Esto significa que también espera 30 segundos antes de procesar la primera vez. Para procesar inmediatamente en la carga de la página, agregue CheckMessages(); justo antes de setInterval para realizar una verificación inmediata de la carga de la página. Dejar en el setInterval permitirá actualizaciones periódicas a los mensajes.

<script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script> 
<script type="text/javascript"> 
    $(function() { 
     setInterval('CheckMessages();', 30000); 
    }); 

    function CheckMessages() { 
     UserNotification.MessageService.GetMessages(function (result) { 
      //alert('found ' + result.length.toString() + ' messages.'); 
      $.each(result, function (i, e) { 
       var dv = $('<div />') 
          .css('background-color', e.Type) 
          .css('border', '4px solid white') 
          .css('color', 'white') 
          .css('text-align', 'center') 
          .append('<span>' + e.Text + '</span>') 
          .append(
           $('<button />') 
            .text('Close') 
            .click(function() { $(this).parent().remove(); })); 

       $('#msgArea').append(dv); 

      }); 

     }, function (e) { alert(e._message); }); 
    } 
</script> 

Nota en el bloque anterior de código que utilizo e.Text, que coincide con el nombre de nuestra propiedad en el código, y e.type. e.Type es nuestro color de fondo especificado aquí, pero probablemente se utilizaría para otra cosa en la vida real. Además, en la vida real, todos esos atributos CSS estarían en una clase de CSS (probablemente una única clase de CSS para cada tipo de mensaje). Agregué un botón de "cerrar", no lo mencionaste pero pensé que la gente querría poder cerrar las notificaciones.

Una cosa genial acerca de esta implementación es que si en el futuro se da cuenta de que necesita almacenar mensajes NO en la sesión sino en, por ejemplo, una base de datos, esta implementación lo manejará sin problemas. Simplemente modifique UserMessages.GetMessages para extraer desde una ubicación db/other y ya está configurado. Además, puede configurarlo para manejar mensajes globales leyéndolos desde la memoria caché además de leer mensajes de usuario de la sesión.

Cuestiones relacionadas