23 listopada 2008, 13:46
dario
Komentarze (0)
asp.net-mvc
tip
Budując aplikację przy użyciu ASP.NET MVC możemy trafić na następujący problem. Otóż standardowo jedna forma na stronie skojarzona jest z konkretną akcją kontrolera. Na przykład: <form action="User/Save" />
Często zdarza się jednak, że na takiej formie mamy więcej niż jeden input typu submit. Wciśnięcie któregoś z nich spowoduje wysłanie danych formy zawsze do tej samej metody "Save" zdefiniowanej w kontrolerze "User". W metodzie "Save" możemy w sumie sprawdzić z jakiego submita wyszła akcja i stosownym if'em zdecydować co ma się dziać dalej. Na szczęście możemy sobie nieco zautomatyzować korzystając z filtru typu "ActionSelectionAttribute". Poniżej prezentuję kod atrybutu "AcceptInputAttribute":
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Web.Mvc;
namespace Softio.Web.MVC.Filters
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class AcceptInputAttribute : ActionSelectionAttribute
{
public AcceptInputAttribute()
{
Names = new List();
}
public AcceptInputAttribute(string name)
: this()
{
Names.Add(name);
}
public AcceptInputAttribute(params string[] name)
: this()
{
Names.AddRange(name);
}
public List Names { get; private set; }
public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
{
if (controllerContext.HttpContext.Request.HttpMethod.Equals("POST", StringComparison.InvariantCultureIgnoreCase))
{
foreach (string n in Names)
{
if (!controllerContext.HttpContext.Request.Form[n].IsNullOrEmpty())
{
return true;
}
}
}
return false;
}
}
}
Atrybut ten nadany metodzie "Save" zbada, czy został przesłany zdefiniowany element formy.
[AcceptInput("Save", "SaveAndStay")]
public ActionResult Save(
int id,
string saveandstay)
{
// Zapisz dane
if (saveandstay != null)
{
return Edit(id);
}
return RedirectToAction("Index");
}
[AcceptInput("DeletePermanently")]
public ActionResult Save(int id)
{
// Usuń z bazy
return RedirectToAction("Index");
}
W powyższym kodzie mamy dwie metody Save, gdzie jedna z nich zapisuje dane użytkownika do bazy i w zależności od istnienia "SaveAndStay" wychodzi do listy lub zostaje w edycji. Druga metoda ma za zadanie usunięcie użytkownika z bazy. Do zadziałania potrzebne jest nadanie atrybutu "name" dla "submitów".
Odpowiednio dla powyższego przykładu:
<input name="Save" type="submit" value="Zapisz" />
<input name="SaveAndStay" type="submit" value="Zapisz i zostań" />
<input name="DeletePermanently" type="submit" value="Usuń" />
W ten oto prosty sposób uzyskaliśmy elastyczność i zarazem estetyczność kodu. Słyszałem i czytałem, że problemy takie ludzie rozwiązują za pomocą JavaScryptu i podmieniają atrybut "action". A Wy jak to robicie w swoich aplikacjach z wykorzystaniem MVC? :)
Errata:
W wersji Beta atrybut ten został przemianowany na ActionMethodSelectorAttribute.