2010-11-24 42 views
12

Me pregunto cómo puede implementar varias acciones al enviar un formulario en asp.net mvc 3 RC.Cómo implementar mejor Guardar | Guardar y cerrar | Cancelar acciones de formulario en ASP.NET MVC 3 RC

Si estoy editando un usuario, por ejemplo, me gustaría tener una barra de acciones con los siguientes botones;

"Guardar" | "Guardar y cerrar" | "Cancelar"

Guardar - Envía el formulario y lo guarda, volviendo a la pantalla de edición. Podría implementarse fácilmente como un botón estándar de entrada/envío. Nada especial aquí.

código de controlador para este podría ser similar

public ActionResult Edit(UserViewModel model) 
{ 
    ... 
    return RedirectToAction("Edit", model.Id"); 
} 

Cancelar - Sólo le devuelve a la pantalla anterior. Estaba pensando en usar una etiqueta de anclaje para esto.

<a href="@Request.UrlReferrer" class="button">Cancel</a> 

Pero estoy confundido sobre cómo implementar "Guardar y cerrar" cuando es necesario presentar los mismos datos del formulario. Me preguntaba si tendrías un param cerrado parecido a nullable.

public ActionResult Edit(UserViewModel model, bool? close) 
{ 
    ... 
    return close.GetValueOrDefault(false) ? RedirectToAction("Index", model.Id" : RedirectToAction("Edit", model.Id"); 
} 

Pero, ¿cómo presento este parámetro extra junto con el formulario en este caso?

Si es posible, me gustaría tener una sola acción de formulario para manejar el envío como en la maqueta anterior.

También me interesa si alguien más ha presentado un buen modelo de interacción del usuario en torno a esta idea.

Solución

Terminé usando la sugerencia de Omar a continuación, pero en lugar de pasar de una cadena que tomó en una enumeración así que no tengo que hacer controles de cadena en todos mis controladores.

public ActionResult Edit(UserViewModel model, FormAction actionType) 
{ 
    // pre-check 
    if (actionType == FormAction.Cancel) 
    // just return user to previous view and don't save. 

    // Save code 

    if (actionType == FormAction.Save) 
    return ... 
    else if (actionType == FormAction.SaveAndClose) 
    .... 
} 

Porque quería un texto más amigable "Guardar y Cerrar" en el botón <input> pero quería utilizar una enumeración que implementó un ModelBinder personalizado para formAction que hizo el análisis.

No usé una etiqueta <button> porque la creación de temas ya estaba en su lugar para las etiquetas <input>.

Respuesta

18

Puede tener varios botones de envío en un formulario con el mismo atributo name pero diferentes atributos value. Cualquiera que sea el botón en el que se haga clic, el value asociado se publicará en el servidor.

Puede usar un enlace simple para Cancel pero lo incluiré como un botón de todos modos.

<input type="submit" name="actionType" value="Save" /> 
<input type="submit" name="actionType" value="Save and Close" /> 
<input type="submit" name="actionType" value="Cancel" /> 

Y en su acción, pruebe los valores.

public ActionResult Edit(string actionType) 
{ 
    if(actionType == "Save") 
    { 
     // Save action 
    } 
    else if (actionType == "Save and Close") 
    { 
     // Save and quit action 
    } 
    else 
    { 
     // Cancel action 
    } 
} 

Si no te gusta tener el largo texto en el atributo value, puede utilizar la etiqueta HTML estándar <button> que le permite definir un valor independiente y separada de texto.

+0

http://stackoverflow.com/questions/2423041/using-two- submit-buttons-inside-single-form/2426152 # 2426152 – takepara

+0

Gracias Omar. Eso fue exactamente lo que quería. ¡Aclamaciones! –

+0

Actualicé mi pregunta con una solución final basada en este enfoque. Muy similar, solo se limpió para usar una enumeración en lugar de cadenas. –

5

La sugerencia de @Omar es excelente. Así es como hice esto un poco más genérico en el caso en que quería una confirmación cuando se le solicita al usuario que elimine un objeto. ¡Nota! en HttpPost vuelvo a tirar el objeto en lugar de usar el elemento que se pasó al método. Puede reducir una llamada a DB al tener la vista conteniendo todas las propiedades para que se llene el "Artículo".

Aquí está el Modelo Vista

public class DeleteViewModel<T> { 
    public string ActionType { get; set; } 
    public T Item { get; set; } 
} 

controlador

public ActionResult Delete(int id) { 
     DeleteViewModel<Category> model = new DeleteViewModel<Category>() { 
      Item = categoryRepository.Categories.FirstOrDefault(x => x.CategoryID == id) 
     }; 
     return View(model); 
    } 

    [HttpPost] 
    public ActionResult Delete(DeleteViewModel<Category> model) { 
     if (model.ActionType == "Cancel") 
      return RedirectToAction("Index"); 
     else if (model.ActionType == "Delete") { 
      var cat = categoryRepository.Categories.FirstOrDefault(x => x.CategoryID == model.Item.CategoryID); 
      categoryRepository.Delete(cat); 
      return RedirectToAction("Index"); 
     }   
     //Unknown Action 
     return RedirectToAction("Index"); 
    } 

Ver

<div class="actions"> 
     <div class="actions-left"><input type="submit" value="Cancel" name="ActionType"/></div> 
     <div class="actions-right"><input type="submit" value="Delete" name="ActionType" /></div> 
    </div> 
+0

Me gusta más esta solución ya que le permite pasar el Modelo sobre el que se está actuando. – Buzzer

Cuestiones relacionadas