2015-09-10 5 views
5

Ho un'applicazione MVC con poche pagine semplici che verranno eseguite principalmente su chiamate API Web. Per semplicità voglio includerli nello stesso progetto. Posso avviare e navigare nella mia pagina bene, ma quando provo a chiamare la mia API tramite Ajax continuo a ricevere un errore 404 - non riesce a trovare la funzione API.Impossibile chiamare il controller WebAPI tramite AJAX, quando è ospitato su MVC

Ecco il mio file javascript:

$(document).ready(function() { 
    //set the login button to call our test API function 
    document.getElementById("login_submit").addEventListener("click", GetUser); 

}); 

function GetUser() { 
    var response = $.ajax({   
     url: '/api/User', 
     method: 'GET', 
     contentType: 'application/json; charset=utf-8', 
     success: function (data) { 
      alert("Success!"); 
     }, 
     error: function (request, status, error) { 
      alert(error); 
     } 
    }); 
} 

e qui è il mio controller:

namespace MyProject.Controllers.API 
{ 
    public class UserController : ApiController 
    { 
     // GET api/<controller> 
     [HttpGet]   
     public IEnumerable<string> Get() 
     { 
      return new string[] { "value1", "value2" }; 
     } 

     // GET api/<controller>/5 
     [HttpGet]   
     public string Get(int id) 
     { 
      return "value"; 
     } 
    } 
} 

L'API controller sono nella propria cartella (chiamata "API") dentro la mia cartella Controllers nella mia progetto - ecco perché lo spazio dei nomi contiene "API" su questo controller di esempio.

Quando uso F12 sul browser per catturare la richiesta di ottenere inviato, mi rendo conto che la mia chiamata ha le seguenti informazioni:

Request URL: http://localhost:50035/api/User 
Request Method: GET 
Status Code: 404/Not Found 

Ora la mia comprensione è che questo dovrebbe trovare l'API con il nome UserController e trova la funzione con il tag [HttpGet] senza argomenti, quindi restituisce l'array di stringhe ("valore1", "valore2"). Invece non trova nulla.

Come nota finale, qui è il mio config di routing (e sì, è in fase di inizializzazione su Global.asax):

public static class WebApiConfig 
    { 
     public static void Register(HttpConfiguration config) 
     { 
      // Web API configuration and services 

      // Web API routes 
      config.MapHttpAttributeRoutes(); 

      config.Routes.MapHttpRoute(
       name: "DefaultApi", 
       routeTemplate: "api/{controller}/{id}", 
       defaults: new { id = RouteParameter.Optional } 
      ); 
     } 
    } 

UPDATE:

Sulla base del feedback che ho ricevuto finora, ho spostato la mia configurazione Global.asax in giro. E 'ora assomiglia a questo:

protected void Application_Start() 
    { 
     AreaRegistration.RegisterAllAreas(); 
     FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
     GlobalConfiguration.Configure(WebApiConfig.Register); 
     RouteConfig.RegisterRoutes(RouteTable.Routes); 
     BundleConfig.RegisterBundles(BundleTable.Bundles); 

    } 

Ora, quando io chiamo la mia funzione API, ho ... in sospeso. Non restituisce un messaggio di successo. Si blocca. Non ho il "successo!" mettere in guardia.

+2

Qual è l'ordine di registrazione dei percorsi nel metodo Global.asax Application_Start()? SE stai registrando percorsi MVC prima di WebAPI, allora le rotte API falliranno! –

+2

Riprodotto il problema registrando rotte MVC _prima_Ravole WebApi. –

+0

Se si inserisce un punto di interruzione nel metodo Get() del controller utente, viene colpito? –

risposta

2

Anche se non sono sicuro che sia lo stesso problema che ho indovinato nel mio commento, ma è un probabile motivo. Quindi chiunque abbia problemi simili, questo è il problema.

Il motore di routing MVC tenta di far corrispondere le richieste in arrivo con le route nello stesso ordine in cui sono state registrate.

  1. Quindi, se si registra percorso MVC prima - {Controller}/{action}/{id} id: optional
  2. E, quindi registrare il percorso WebAPI - api/{Controller}/{ id} ID: optional

richieste poi arrivo verranno abbinate con il percorso MVC e se non corrispondono a un modello percorso, solo allora saranno confrontati con il percorso WebAPI.

Ora, se si dispone di una richiesta come api/User, che corrisponderà con il pattern MVC percorso, e non sarà confrontato con il percorso WebAPI. Di conseguenza, MvcHandler tenterà di creare una classe di controller MVC ApiController e di richiamare il metodo User() su quello.Di conseguenza, il client riceverà 404 - risorsa non trovata!

Inoltre, se non si utilizza l'attributo di routing, si potrebbe desiderare di rimuovere/commentare questa linea

//config.MapHttpAttributeRoutes(); 

E per rendere più sicuri http-verbo-to-api-metodo di routing, è possibile aggiungere quanto segue in la tua api config.

routes.MapHttpRoute("RestApiRoute", "Api/{controller}/{id}", new { id = RouteParameter.Optional }, new { id = @"\d+" }); //this replaces your current api route 
routes.MapHttpRoute("ApiWithActionRoute", "Api/{controller}/{action}/{id}", new { id = RouteParameter.Optional }); 
routes.MapHttpRoute("DefaultApiGetRoute", "Api/{controller}", new { action = "Get" }, new { httpMethod = new HttpMethodConstraint(new string[] { "GET" }) }); 
routes.MapHttpRoute("DefaultApiPostRoute", "Api/{controller}", new { action = "Post" }, new { httpMethod = new HttpMethodConstraint(new string[] { "POST" }) }); 
routes.MapHttpRoute("DefaultApiPutRoute", "Api/{controller}", new { action = "Put" }, new { httpMethod = new HttpMethodConstraint(new string[] { "PUT" }) }); 
routes.MapHttpRoute("DefaultApiDeleteRoute", "Api/{controller}", new { action = "Delete" }, new { httpMethod = new HttpMethodConstraint(new string[] { "DELETE" }) }); 

I primi due percorsi permettono di chiamare i punti finali in [1] REST puro modo & per [2] chiamarli con nome del metodo (non allineate agli standard REST però!)

+0

Grazie - questo è stato molto utile. Ho spostato il mio codice e ora riesco a superare l'errore iniziale che stavo ottenendo, ma non riesco ancora a ottenere il mio "Successo!" mettere in guardia. Si prega di consultare la mia modifica per maggiori informazioni. – Max

+0

@ user2291983 Non vedo WebApiConfig.Register() nel metodo di avvio dell'app, mi manca qualcosa? E, puoi semplicemente premere http: // localhost: 50035/api/User (aggiustare il numero della porta se è cambiato) dalla barra degli indirizzi del tuo browser e vedere cosa succede? –

+1

WebApiConfig.Register è nella chiamata GlobalConfiguration.Configure(). Onestamente non so cosa faccia, ma tutti i miei libri lo hanno fatto in quel modo. La chiamata all'URL ha funzionato come previsto: ho ricevuto un oggetto JSON contenente l'array di stringhe. – Max

1

Prova

/api/User/Get 

anziché solo/api/utente. Se vuoi divertirti, dai un'occhiata allo [RoutePrefix] and [Route] così puoi gestire questa roba a mano.

+1

Questo ha funzionato, ma va contro quello che pensavo di aver capito delle chiamate API. L'utente è il nome del controller e sto cercando di chiamare la funzione GET senza parametri utilizzando una richiesta HTTP Get. – Max

+0

@ user2291983 segnalo come risposta giusta comunque? :) Lo so, MS non è così entusiasta di spiegare questa roba, specialmente quando mostra l'architettura di routing predefinita. È così, però. . ./{controllerName}/{actionName}/{parameter} o /? parameter = XXX. Una volta che inizierai a creare API personalizzate (con nomi diversi da "GET" e "POST"), avrà più senso. – codeMonkey