2014-01-22 8 views
5

Ich habe erreicht, das WebApi selbst zu schaffen, und ich kann es vom Browser durchsuchen und die Ausgabe erhalten.Wie man WebApi in Asp.net MVC hinzufügt und dann die WebAPI in der gleichen Anwendung verbraucht

Die Sache, die nicht funktioniert für mich ist, dass ich versuche, die WebAPI von einem MVC-Controller zu konsumieren, und ich habe den Code zum Aufruf der WebAPI in meiner "cshtml" Ansicht geschrieben.

Aber es funktioniert nicht, da ich den Fehler beim Laden der Seite bekomme, verstehe ich, dass ich etwas falsch mache. Die erste Frage lautet also: Mache ich das richtig oder ist es völlig falsch, einen WebAPI-Teil in einem MVC-Projekt zu erstellen und dann im selben MVC-Projekt vom Controller zu konsumieren?

+0

Post Fehler. Warum möchten Sie jedoch die Web-API aus derselben Anwendung konsumieren, in der ich davon ausgehe, dass die Anwendung bereits Zugriff auf den gesamten Code hat, den der Service kapselt? Warum den zusätzlichen Overhead ausgeben, wenn Sie das nicht brauchen? – Maess

+1

Ich stimme Ihnen vollkommen zu, aber gibt es irgendeinen technischen Grund, warum ich es nicht tun kann oder es ist nur eine falsche Art, es zu implementieren? – user1570094

+1

@Maess, MVC und WebAPI wurden entwickelt, um in der gleichen Anwendung zu leben. Sie können Ihre spezifischen API-Controller in einen separaten Ordner senden, z. B. "API" im Stammverzeichnis, um sie zu trennen, wenn Sie möchten. Aus diesem Grund haben Sie eine 'RouteConfig.cs' und eine' WebApiConfig.cs' im gleichen 'App_Start'-Ordner - da erwartet wird, dass beide im selben Projekt genutzt werden. Es ist jedoch nicht erforderlich. –

Antwort

2

Um Ihre Frage zu beantworten, ist es tatsächlich "wie geplant" und empfohlen, Ihren WebAPI- und MVC-Client im selben Projekt zu haben. Deshalb haben Sie sowohl ein RouteConfig.cs als auch ein WebApiConfig.cs in Ihrem MVC-Projekt. RouteConfig.cs ist für Ihre MVC-Controller und WebApiConfig.cs ist offensichtlich für Ihre Api-Controller.

Um beide im selben Projekt zu haben ist einfach. Ich füge einen Ordner namens "API" in meinen Stammordner ein und platziere alle meine WebAPI-Controller dort. Denken Sie daran, und der einzige Unterschied zwischen einem WebAPI-Controller und einem MVC-Controller besteht darin, dass ein WebAPI-Controller erbt, was Teil von System.Web.Http ist (ich glaube), während ein MVC-Controller Controller erbt System.Web.MVC.

Unten ist der richtige Weg, GET/PUT/DELETE/POST-Anfragen TO Ihre WebAPI VON ein MVC vorderen Ende zu machen. Es spielt keine Rolle, ob es im selben Projekt ist oder nicht, da Sie die WebAPI-URL im Konstruktor Ihres Controllers angeben. Wenn sich Ihre WebAPI auf einem anderen Server als Ihre Front-End-MVC-Anwendung befindet, müssen Sie die CORS-Unterstützung aktivieren, die in der WebAPI-Version 2 und höher verfügbar ist.

Dies ist der richtige Weg, um eine WebAPI von Ihrem Front-End-MVC-Client aus aufzurufen.

In Ihrem Controller Seite, entfernen Sie alles, was mit DbContext, Entity Framework usw. Der Grund ist standardmäßig zu tun hat, wird der Controller CRUD-Operationen durchgeführt werden soll, indem die DbContext Aufruf, und wir tun dies nicht wollen. Wir möchten stattdessen die WebAPI aufrufen. Wenn ich mich auf "Controller" beziehe, beziehe ich mich auf den MVC-Controller, nicht auf den WebAPI-Controller.

In erster Linie deklarieren Sie einige Mitgliedsvariablen in Ihrem MVC-Controller. Der Rest Ihrer MVC-Controller werden diese nutzen:

HttpClient client = new HttpClient(); 
    HttpResponseMessage response = new HttpResponseMessage(); 
    Uri contactUri = null; 
  1. In Ihrem MVC-Controller, einen Konstruktor für Ihren Controller erstellen, wie zum Beispiel:

    public ContactController() 
    { 
        // set base address of WebAPI depending on your current environment 
        // the URL below, if the API is in the same project, will be something 
        // like "http://server/YourProjectName" - replace server with either 
        // "localhost", etc. 
        client.BaseAddress = new Uri("http://server/YourAPI/"); 
    
        // Add an Accept header for JSON format. 
        client.DefaultRequestHeaders.Accept.Add(
         new MediaTypeWithQualityHeaderValue("application/json")); 
    } 
    
  2. Ersetzen Sie den Code des Index Aktion mit etwas wie das folgende. Beachten Sie, dass die einzigen relevanten Teile der client.GetAsync() Aufruf und die var contacts Zuweisung sind. Alles andere ist für den Kontext dieses Problems nicht notwendig. Der Wert innerhalb der client.GetAsync() sollte der Name Ihres Controllers sein, der von einem benutzerdefinierten Routing, das Sie in Ihrer WebApiConfig eingerichtet haben, vorangestellt wird.cs - in meinem Fall, habe ich den api Teil meiner Strecke zwischen API-Aufrufen und normalen Anrufen zu unterscheiden:

    public ActionResult Index() 
    { 
        response = client.GetAsync("api/contact").Result; 
        if (response.IsSuccessStatusCode) 
        { 
         var contacts = response.Content.ReadAsAsync<IEnumerable<Contact>>().Result; 
         return View(contacts); 
        } 
        else 
        { 
         // add something here to tell the user hey, something went wrong 
         return RedirectToAction("Index"); 
        } 
    } 
    
  3. die Aktion Erstellen ersetzen (die Httppost Aktion) mit etwas wie folgt aus. Auch hier ist das einzige wichtige Stück der client.PostAsJsonAsync() Teil - das ist, was der POST-Aktion des WebAPI ruft die Pflege, in meinem Fall nimmt, einen neuen Datensatz in die Datenbank einfügen:

    [HttpPost] 
    [ValidateAntiForgeryToken] 
    public ActionResult Create(Contact contact) 
    { 
        // Create a new product 
        response = client.PostAsJsonAsync("api/contact", contact).Result; 
        if (response.IsSuccessStatusCode) 
        { 
         return RedirectToAction("Index"); 
        } 
        else 
        { 
         // add something here to tell the user hey, something went wrong 
         return RedirectToAction("Index"); 
        } 
    } 
    
  4. Aktion bearbeiten ersetzen (die Nicht-HttpPost-Aktion) mit etwas wie dem Folgenden. Dies war ein wenig schwierig, weil Sie zum Bearbeiten zuerst den Datensatz abrufen mussten, also enthält die HttpPost-Version von Edit etwas ähnlichen Code mit einer zusätzlichen Codezeile, die den Bearbeitungs-POST (PUT) ausführt. Im Folgenden erhalten Sie die Antwort von der WebAPI, indem Sie eine bestimmte Datensatz-ID übergeben. Genau wie bei Index (GET) machen wir dasselbe, indem wir nur die ID übergeben, so dass wir nur einen Datensatz zurückbekommen. Dann werfen wir die Antwort auf ein reales Objekt, das in der Ansicht betrieben werden kann:

    public ActionResult Edit(int id = 0) 
    { 
        response = client.GetAsync(string.Format("api/contact/{0}", id)).Result; 
        Contact contact = response.Content.ReadAsAsync<Contact>().Result; 
        if (contact == null) 
        { 
         return HttpNotFound(); 
        } 
        return View(contact); 
    } 
    
  5. Ersetzen Sie die Aktion Bearbeiten (die Httppost Aktion) mit etwas wie folgt aus. Im Folgenden erhalten Sie, dass der Datensatz bearbeitet wird, indem Sie client.GetAsync() aufrufen und den Primärschlüssel als Parameter übergeben (contact_id). Dann erhalten wir die RequestUri von dieser Antwort und speichern sie. Dann rufen wir client.PutAsJsonAsync() an und übergeben die Uri.PathAndQuery (was wir gerade gespeichert haben) sowie das zu bearbeitende Objekt.

    [HttpPost] 
    [ValidateAntiForgeryToken] 
    public ActionResult Edit(Contact contact) 
    { 
        response = client.GetAsync(string.Format("api/contact/{0}", contact.contact_id)).Result; 
        contactUri = response.RequestMessage.RequestUri; 
        response = client.PutAsJsonAsync(contactUri.PathAndQuery, contact).Result; 
        if (response.IsSuccessStatusCode) 
        { 
         return RedirectToAction("Index"); 
        } 
        else 
        { 
         // add something here to tell the user hey, something went wrong 
         return RedirectToAction("Index"); 
        } 
    } 
    
  6. Ersetzen Sie die Löschaktion (die Nicht-Httppost Aktion) mit etwas wie folgt aus. Also, wieder, wir bekommen den Datensatz aus der Datenbank, indem wir einfach client.GetAsync() aufrufen und ihn auf ein tatsächliches Objekt umwandeln, das meine App kennt.

    public ActionResult Delete(int id = 0) 
    { 
        response = client.GetAsync(string.Format("api/contact/{0}", id)).Result; 
        Contact contact = response.Content.ReadAsAsync<Contact>().Result; 
    
        if (contact == null) 
        { 
         return HttpNotFound(); 
        } 
        return View(contact); 
    } 
    
  7. Schließlich ersetzen Sie die Löschaktion (die Httppost Aktion) mit etwas wie folgt aus. Auch hier machen wir etwas Ähnliches wie bei der Aktion Bearbeiten. Wir werden den Datensatz löschen, ihn in ein Objekt umwandeln und dann dieses Objekt in einen Aufruf übergeben, wie unten gezeigt.

    [HttpPost, ActionName("Delete")] 
    [ValidateAntiForgeryToken] 
    public ActionResult DeleteConfirmed(int id) 
    { 
        response = client.GetAsync(string.Format("api/contact/{0}", id)).Result; 
        contactUri = response.RequestMessage.RequestUri; 
        response = client.DeleteAsync(contactUri).Result; 
        return RedirectToAction("Index"); 
    } 
    
+0

Vielen Dank für diese detaillierte und großartige Erklärung und ich gehe ganz darauf ein. Aber kann ich in diesem ähnlichen Szenario, in dem ich einen WebApi- und MVC-Client im selben Projekt habe, auf den WebApi zugreifen, indem ich die jQuery in der Ansicht schreibe und diese Ansicht von einem MVC-Controller als ActionResult zurückgegeben wird? Bitte gib mir auch dafür eine Antwort, denn ich finde es sollte funktionieren. Ich habe es versucht, aber es hat nicht funktioniert. Vielen Dank. – user1570094

+0

Schöne Antwort, aber was ist mit einem Login?Wenn wir das [Authorize] -Attribut über den WebAPI-Controller verwenden, wie haben wir den Änderungscode? Bitte, klarstellen. Vielen Dank! –

+0

Ich stieß auf ein Problem mit Web-API-2 mit Ihrem Schritt 2 Hinzufügen von Action-Index-Code wie 'public ActionResult Index()'. Basierend auf dieser Frage (http://stackoverflow.com/questions/21758615/) gehe ich davon aus, dass für web-api-2 der Code in Schritt 2 sein muss geändert in 'public IHttpActionResult Index()'. Ist das richtig? – surfmuggle