2009-12-03 23 views
10

Tengo varias vistas ASP.NET MVC simples para operaciones CRUD que funcionan bien por sí mismas como una simple página web. Ahora los voy a integrar en el sitio web (en el contenido) y tengo, por ejemplo, enlaces como "Crear nueva publicación" que dispararía la vista en un clon de Lightbox elegido (aún no sé cuál, tal vez Colorbox o Thickbox pero eso no importa).Simple ASP.NET MVC CRUD vistas de apertura/cierre en el diálogo de la IU de JavaScript

Lo que quiero lograr es que la vista de alguna manera detecte que se abrió en un diálogo de interfaz de usuario de JavaScript para que la acción Formulario (más comúnmente POST usando un simple botón Enviar) se represente con una lógica que cerraría el Diálogo UI después de que la acción se haya realizado.

El modo en que las vistas funcionan ahora es POST/Redirect/GET. La vista aún debería admitir este patrón simple cuando se abre directamente a través de la URL en un navegador web, pero debería generar cierta lógica adicional cuando se abre a través del cuadro de diálogo de JavaScript.

Espero que entiendas mi pregunta. Cualquier ayuda apreciada

Respuesta

11

Tu suerte, he hecho esto!

Así que lo primero que necesita es un nuevo ViewEngine para manejar la representación de una página sin todas las cosas normales de encabezado/pie de página que se interpondrán en el camino de sus ventanas modales. La forma más sencilla de hacerlo es utilizar una página maestra en su mayoría vacía para sus ventanas modales. Desea que la página maestra cambie la lógica fuera del camino y en un ViewEngine personalizado porque, de lo contrario, cada método del controlador tendrá que tener if() else() en todo el lugar detectando IsAjaxRequest(). Me gusta seco, sáhara seco.

Con esta técnica también tengo la ventaja de degradar con mucha gracia. Mi sitio funciona sin javascript perfectamente. Los enlaces están bien, el trabajo de formularios, cambios en el código cero para pasar de un "sitio sensible a los modos" a un simple formulario html antiguo.

único que hice fue subclase el motor por defecto y añadir algunos bits de selección MasterPage:

The View Motor:

public class ModalViewEngine : VirtualPathProviderViewEngine 
{ 
    public ModalViewEngine() 
    {     
    /* {0} = view name or master page name 
     * {1} = controller name  */ 

    MasterLocationFormats = new[] { 
     "~/Views/Shared/{0}.master" 
    }; 

    ViewLocationFormats = new[] { 
     "~/Views/{1}/{0}.aspx", 
     "~/Views/Shared/{0}.aspx" 
    }; 

    PartialViewLocationFormats = new[] { 
     "~/Views/{1}/{0}.ascx",    
     }; 
    } 

    protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath) 
    { 
     throw new NotImplementedException(); 
    } 

    protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath) 
    { 

     return new WebFormView(viewPath, masterPath); 
    } 

    public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) 
    { 
     //you might have to customize this bit 
     if (controllerContext.HttpContext.Request.IsAjaxRequest()) 
      return base.FindView(controllerContext, viewName, "Modal", useCache); 

     return base.FindView(controllerContext, viewName, "Site", useCache); 
    } 

    protected override bool FileExists(ControllerContext controllerContext, string virtualPath) 
    { 
     return base.FileExists(controllerContext, virtualPath); 
    }   
} 

Así que mi página Modal.Master es muy simple. Todo lo que tengo es un envoltorio div, así que sé cuándo algo se procesa dentro de la ventana modal. Esto será útil cuando necesite seleccionar ciertos elementos con jquery solo cuando los elementos estén en "modo modal".

Modal.Master

<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %> 
<div id="modalcontent"><asp:ContentPlaceHolder ID="MainContent" runat="server" /></div> 

El siguiente paso es crear el formulario. Utilizo el nombre de propiedad predeterminado = nombre de entrada para poder modelar el enlace fácilmente y mantener las cosas simples. Nada especial sobre la forma. Me parece que lo harías normalmente.(Tenga en cuenta que estoy usando MVC 2 y EditorFor() en mi código, pero eso no debería importar) Aquí está mi HTML final:

salida HTML

<div id="modalcontent"> 
    <h2>EditFood</h2> 
    <div id="form"> 
     <form method="post" action="/edit/food?Length=8"> 
      <input id="CommonName" class="text-box single-line" type="text" value="" name="CommonName"/> 
      <input class="button" type="submit" value="Edit Food"/> 
     </form> 
    </div> 
</div> 

Además de modelo de unión muy bien que pueda utilice también el Jquery.Form plugin para tener capacidades de ajax simples y fáciles de aplicar en capas en su aplicación con un código mínimo. Ahora he elegido ColorBox como script modal de mi ventana simplemente porque quería Facebookesque esquinas transparentes y me gustan los puntos de extensibilidad que el autor ha agregado.

Ahora con estos scripts combinados se obtiene una combinación realmente agradable que hace que esta técnica sea realmente estúpida, fácil de hacer en javascript. La única Javascript he tenido que añadir era (en el interior document.ready):

Javascript/jQuery

$("a.edit").colorbox({ maxWidth: "800px", opacity: 0.4, initialWidth: 50, initialHeight: 50 }); 

    $().bind('cbox_complete', function() { 
     $("#form form").ajaxForm(function() { $.fn.colorbox.close() }); 
    }); 

Aquí estoy contando ColorBox para abrir una ventana modal para mis enlaces de edición (Edit Alimentos) . A continuación, vincula el evento completo del colorbox para conectar tus elementos ajaxform con una devolución de llamada correcta para indicar a ColorBox que cierre la ventana modal. Eso es.

Este código fue todo hecho como una prueba de concepto y es por eso que el motor de visualización es realmente ligero y no hay validación u otra forma estándar bling. ColorBox y JQuery.Form tienen toneladas de compatibilidad de extensibilidad por lo que personalizar esto debería ser fácil.

Tenga en cuenta que todo esto se hizo en MVC 2, pero aquí está el código de mi controlador para mostrar lo fácil que es esto. Recuerda que mi objetivo de prueba de concepto era lograr que las ventanas modales funcionaran de tal forma que no tuviera que hacer ningún cambio de código más allá de configurar alguna infraestructura básica.

[UrlRoute(Path="edit/food")] 
    public ActionResult EditFood() 
    {    
     return View(new Food()); 
    } 

    [HttpPost][UrlRoute(Path = "edit/food")] 
    public ActionResult EditFood(Food food) 
    {   
     return View(food); 
    } 
+0

Wow, gracias por esta extensa respuesta. Se ve muy bien. – mare

+0

¿Cómo se conecta este nuevo ViewEngine a una vista existente? Tengo problemas para encontrar esa pieza de código. – mare

+0

No entiendo, el motor de vista hace el cableado, debe hacer cualquier trabajo para conectarlo. – jfar

0

Al construir la URL para jQuery para hacer un AJAX GET a, puede agregar un parámetro de cadena de consulta como & javascriptWindow = id, cuando esto se detecta en el controlador puede agregar la lógica necesaria al formulario para cerrar el diálogo después de la ejecución.

Cuestiones relacionadas