Frage

Ich will eine Menge if Request.IsAjaxRequest() in meinem Controller vermeiden muß. Ich dachte, dass wenn ich diese Logik zu einem Action kondensieren könnte, es wäre leicht, eine Konvention in meiner Anwendung zu erlassen, eine zweite Aktion für jede Anforderung zur Verfügung zu stellen, dass kann verwendet Ajax, während einen Rückgang wieder anbieten, wenn JavaScript ist deaktiviert.

public ActionResult Details(int id)
{
  // called normally, show full page
}

public ActionResult Details_Ajax(int id)
{
  // called through ajax, return a partial view
}

Ich dachte zunächst, ich etwas tun könnte:

public class AjaxRenameAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.RouteData.Values["action"] = filterContext.RouteData.Values["action"] + "_Ajax";

    }

Aber das wird nicht funktionieren, weil die Aktion aufzurufen entschieden wird, und dann die Filter auf sie verarbeitet werden.

Ich will nicht wirklich eine RedirectResult jedes Mal, wenn jemand zurück eine Aktion aufruft, es scheint ein bisschen sinnlos, die Menge an Http-Anfragen zu verdoppeln.

Gibt es eine andere Art und Weise Weg durch die Anforderung an eine andere Aktion? Oder ist das, was ich tue unadvisable und ich soll für eine bessere Art und Weise, Dinge zu tun, was?

Prost

War es hilfreich?

Lösung

AcceptAjaxAttribute ist wahrscheinlich das, was hier gebraucht wird; aber ich möchte eine andere Art des Denkens über dieses Problem vorzuschlagen.

Nicht alle sind Ajax-Anfragen gleich. Ein Ajax-Anfrage könnte versuchen, eine der folgenden Dinge zu erreichen:

  • Binde JSON Daten auf ein fettes Gitter (wie jqGrid);
  • Parsing / Transformieren von XML-Daten, wie zum Beispiel eines RSS-Feed;
  • Laden teilweise HTML-Code in einen Bereich der Seite;
  • Asynchron ein Skript geladen (google.load kann dies tun);
  • Umgang mit einer Einweg Nachricht von dem Client;
  • Und wahrscheinlich ein paar mehr, dass ich vergessen.

Wenn Sie „Auswahl“ eine bestimmte „alternative Aktion“ basiert ausschließlich auf der IsAjaxRequest Methode, Sie binden etwas sehr allgemein - eine asynchrone Anforderung - auf spezifische Funktionalität auf dem Server. Es ist schließlich Ihr Design spröder gehen zu machen und auch Ihre Steuerung schwieriger zu Unit-Test machen (obwohl es gibt Möglichkeiten, es zu tun, können Sie den Kontext verspotten).

Eine gut gestaltete Aktion sollte konsistent , sollte es nur Pflege was die Anforderung war für und nicht wie wurde der Antrag gestellt. Man könnte Punkt auf andere Attribute wie AuthorizeAttribute als Ausnahmen, aber ich würde einen Unterschied für Filter machen, die die meiste Zeit Verhalten beschreiben, das geschehen hat entweder ein „vor“ oder „nach“ die Aktion stattfindet, nicht „statt. „

Auf den Punkt hier ist das Ziel in der Frage angegeben ist gut; Sie sollten auf jeden Fall haben verschiedene Methoden für das, was als unterschiedliche Aktionen richtig beschrieben:

public ActionResult Details(int id)
{
    return View("Details", GetDetails(id));
}

public ActionResult JsonDetails(int id)
{
    return Json(GetDetails(id));
}

public ActionResult PartialDetails(int id)
{
    return PartialView("DetailTable", GetDetails(id));
}

Und so weiter. Jedoch unter Verwendung eines Ajax Aktion Wähler zwischen diesen Methoden zu wählen, wird im Anschluss an die Praxis der "Graceful Degradation" , die im Wesentlichen abgelöst wurde (zumindest IMO) von Progressive Enhancement .

Aus diesem Grund, obwohl ich ASP.NET MVC lieben, ich meistens die AjaxHelper eschew, weil ich finde nicht, dass es dieses Konzept, das gut zum Ausdruck bringt; es versucht, von Ihnen zu viel zu verbergen. Statt das Konzept einer „Ajax Form“ zu haben oder ein „Ajax-Aktion“, lassen Sie uns tun, weg mit der Unterscheidung und Stick gerade HTML, dann injizieren, um die Ajax-Funktionalität getrennt, sobald wir sind uns sicher, dass der Kunde kann damit umgehen .

Hier ist ein Beispiel in jQuery - obwohl man auch diese in MS AJAX tun können:

$(function() {
    $("#showdetails").click(function() {
        $("#details").load("PartialDetails", { id: <%= Record.ID %> });
        return false;
    }
});

Das ist alles was man braucht Ajax in eine MVC-Seite zu injizieren. Beginnen Sie mit einem einfachen alten HTML-Link, und überschreibt ihn mit einem Ajax-Aufruf , die eine anderen Controller-Aktion geht .

Nun, wenn auf woanders auf Ihrer Website Sie sich entscheiden, Sie wollen stattdessen ein Gitter verwenden, aber nicht wollen, dass die Seiten mit Teil Rendering zu brechen, Sie so etwas schreiben können (sagen wir Sie einen einzigen Meister haben Detailseite mit einer Liste von „Aufträgen“ auf der linken Seite und ein Detail Tabelle rechts):

$(".detaillink").click(function() {
    $('#detailGrid').setGridParam({
        url: $(this).attr("href").replace(/\/order\/details/i,
            "/order/jsondetails")
    }); 
    $("#detailGrid").trigger("reloadGrid");  
});

Dieser Ansatz abkoppelt vollständig Client Verhalten von Serververhalten. Der Server sagt effektiv an den Client: Wenn Sie die JSON-Version möchten, fragen für die JSON-Version, und oh, übrigens, ist hier ein Skript Ihre Links zu konvertieren, wenn Sie wissen, wie Keine Aktion Selektoren und finagling mit Methode Überlastungen, um sie auszuführen. keine besonderen spöttisch die Sie zu tun haben, einen einfachen Test, keine Verwirrung über die Aktion laufen tun, was und wann. Nur ein paar Zeilen JavaScript. Die Controller-Aktionen sind kurz und süß, genau so, wie sie sein sollten.

Dies ist nicht der einzige Ansatz. Offensichtlich Klassen wie AcceptAjaxAttribute existieren, weil sie einige Entwickler erwartet, dass die Anfrage-Nachweisverfahren zu verwenden. Aber nachdem sowohl mit ziemlich viel experimentiert zu haben, finde ich diese Art und Weise viel einfachen Grund, über und daher leichter zu entwerfen / Code korrekt.

Andere Tipps

Wie wäre es AcceptAjaxAttribute in MvcFutures?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top