Ich bin auf diese Frage gestoßen, weil ich das Gleiche wissen wollte. Im Folgenden finden Sie eine ausführliche Beschreibung meiner Situation und der Lösung, die ich verwendet habe (die die anderen Antworten hier verwendet). Ursprünglich habe ich versucht, zwei getrennte Methoden zu verwenden, aber ich bin auf ein Problem gestoßen, als die Methodensignaturen dieser Methoden identisch wurden.
Ich habe eine Seite, die Berichtsdaten anzeigt. Oben auf der Seite befindet sich ein Formular mit einigen Feldern, in denen der Benutzer Berichtsparameter wie Startdatum, Enddatum usw. angeben kann.
Ursprünglich habe ich zwei getrennte Methoden für die Get- und die Post-Methode entwickelt, um dieses Problem zu lösen. Die Post-Methode würde den Browser an die Get-Methode weiterleiten, so dass alle angegebenen Parameter dem Query-String hinzugefügt würden und der Browser den Benutzer nicht mit einem Dialog auffordern würde, die eingegebenen Daten erneut zu senden, wenn er die Seite aktualisiert. Hinweis: Später habe ich festgestellt, dass ich dies erreichen könnte, indem ich das Methodenattribut meines Formularelements auf "Get" setze, aber ich denke, dass ein Controller idealerweise nicht wissen sollte, wie eine Ansicht implementiert ist, daher ist das meiner Meinung nach irrelevant.
Als ich diese beiden Methoden entwickelte, fand ich mich schließlich in einer Situation wieder, in der die Methodensignaturen identisch wurden. Außerdem wurde mein Code für diese beiden Methoden fast identisch, so dass ich beschloss, sie in einer einzigen Methode zusammenzufassen und nur das Anfrageverb zu prüfen, damit ich etwas anderes tun kann, wenn die Anfrage kein "Get" ist. Ein Beispiel für meine beiden Methoden ist unten dargestellt:
// this will not compile because the method signatures are the same
public ActionResult MyReport(DateRangeReportItem report)
{
// if there are no validation errors and the required report parameters are completed
if (ModelState.IsValid && report.ParametersAreComplete)
{
// retrieve report data and populate it on the report model
report.Result = GetReportData(report.CreateReportParameters());
}
return View(report);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult MyReport(DateRangeReportItem report)
{
if (ModelState.IsValid && report.ParametersAreComplete)
{
// redirect to the same action so that if the user refreshes the browser it will submit a get request instead of a post request
// this avoids the browser prompting the user with a dialog saying that their data will be resubmitted
return RedirectToAction("MyReport", new { StartDate = report.StartDate, EndDate = report.EndDate });
}
else
{
// there were validation errors, or the report parameters are not yet complete
return View(report);
}
}
Warum akzeptiere ich ein Modellobjekt als Parameter für meine get-Methode? Der Grund dafür ist, dass ich die bereits in das Modellobjekt integrierte Validierungslogik nutzen wollte. Wenn jemand direkt zu meiner Seite navigiert und alle Parameter bereits im Query-String angegeben sind, möchte ich die Berichtsdaten abrufen und auf der Seite anzeigen. Wenn jedoch die in der Abfragezeichenfolge angegebenen Parameter ungültig sind, sollen auf der Seite auch Überprüfungsfehler angezeigt werden. Indem ich mein Modellobjekt als Parameter einsetze, wird das MVC-Framework automatisch versuchen, es zu füllen, und wird alle Validierungsfehler ohne zusätzliche Arbeit meinerseits erfassen.
Ich habe die anderen Antworten für diese Frage veröffentlicht, um eine RequestHttpVerb-Eigenschaft auf eine Basis-Controller-Klasse in meinem Projekt zu erstellen:
public HttpVerbs RequestHttpVerb
{
get { return (HttpVerbs)Enum.Parse(typeof(HttpVerbs), this.Request.HttpMethod, true); }
}
Meine konsolidierte Methode sieht also wie folgt aus:
[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
public ActionResult MyReport(DateRangeReportItem report)
{
// check if there are any validation errors in the model
// and whether all required report parameters have been completed
if (ModelState.IsValid && report.ParametersAreComplete)
{
// this is unnecessary if the form method is set to "Get"
// but within the controller I do not know for sure if that will be the case in the view
if (HttpVerbs.Get != this.RequestHttpVerb)
{
// redirect to the same action so that if the user refreshes the browser it will submit a get request instead of a post request
// this avoids the browser prompting the user with a dialog saying that their data will be resubmitted
return RedirectToAction("MyReport", new { StartDate = report.StartDate, EndDate = report.EndDate });
}
// there were no validation errors and all required report parameters are complete
// retrieve report data and populate that data on the model
report.Result = GetReportData(report.CreateReportParameters());
}
// display the view with the report object
// Any model state errors that occurred while populating the model will result in validation errors being displayed
return View(report);
}
Das ist meine derzeitige Lösung für dieses Problem. Ich würde es vorziehen, die Request.HttpMethod-Eigenschaft nicht überprüfen zu müssen, um festzustellen, ob ich die Umleitung durchführen muss, aber ich habe keine andere Lösung für mein Problem gesehen. Ich hätte auch zwei getrennte Methoden für die Bearbeitung von Get- und Post-Anfragen verwenden können, aber die identische Methodensignatur verhinderte dies. Ich hätte es vorgezogen, meine Post-Action-Handler-Methode umzubenennen, um den Methodensignaturkonflikt zu vermeiden, und dem MVC-Framework mit einem Mechanismus zu signalisieren, dass meine umbenannte Methode weiterhin die Aktion "MyReport" verarbeiten sollte.