2015-10-12 62 views
0

我在此項目中使用了Visual Studio 2015社區版和AngularJS 1.4.7。使用AngularJS 1.4.7服務調用ASP.NET Web API不起作用

ProductAPIController.cs

public class ProductAPIController : ApiController 
{ 
    [HttpGet] 
    public IQueryable<Product> MyProducts() 
    { 
     List<Product> p = new List<Product>() { new Product {ProductName ="abc", Id = 1, Description = "Desc 1" }, 
               new Product {ProductName ="def", Id = 2, Description = "Desc 2" }, 
               new Product {ProductName ="ghi", Id = 3, Description = "Desc 3" } }; 
     return p.AsQueryable(); 
    } 
} 

Product.cs

public class Product 
{ 
    public int Id { get; set; } 
    public string ProductName { get; set; } 
    public string Description { get; set; } 
} 

app.module.js 我用於應用程序模塊的單獨文件中的最佳實踐here建議

(function() { 
    'use strict'; 
    angular.module('app', ['ngCookies', 'ngRoute']) 
})(); 

homeCtrl.js

這裏我使用這兩種服務,並在同一個文件中的控制器。我甚至嘗試在一個單獨的文件中使用它,但它仍然無效。

(function() { 
    'use strict'; 
    angular.module('app') 
    .controller('homeCtrl', ['$scope', '$http', 'ProductService', '$location', function homeCtrl($scope, $http, ProductService, $location) { 
    $scope.products = []; 

    $scope.getProducts = function() { 
     ProductService.getProducts().then(function (response) { 
      $scope.products = response.data; 
     }, function (err) { 
      alert(err); 
     }); 
     }; 
    }]) 
    .service('ProductService', ['$http', function ($http) { 
     this.getProducts = function() { 
      return $http.get('/api/ProductAPI'); 
     }; 
    }]); 
})(); 

index.cshtml

這裏我用data-ng-repeat="item in products"

<div class="row" ng-app="app"> 
    <div class="col-md-12" ng-controller="homeCtrl"> 
     <div class="row"> 
      <div class="col-md-12"> 
       <form id="test"> 
        <div data-ng-repeat="item in products"> 
         <div class="col-sm-4 column productbox"> 
          <div class="producttitle">{{item.ProductName}}</div> <div class="action"></div> 
          <div class="productprice"> 
           <div class="pull-right"> 
            <div >{{item.Id}}</div> 

            <a href="" class="btn btn-danger btn-sm" role="button"><span class="glyphicon glyphicon-arrow-right"></span> Get Quote</a> 
           </div> 
           <div class="pricetext">{{item.Description}}</div> 
          </div> 
         </div> 
        </div> 
       </form> 
      </div> 
     </div> 
    </div> 
</div> 
@section scripts 
{ 
    @Scripts.Render("~/Scripts/angular.js") 
    @Scripts.Render("~/Scripts/angular-cookies.min.js") 
    @Scripts.Render("~/Scripts/angular-route.js") 
    @Scripts.Render("~/Ng/app.module.js") 
    @Scripts.Render("~/Ng/homeCtrl.js") 
} 

我嘗試了好幾種不同的方法,但都失敗了。我在這裏做錯了什麼?

編輯

我已經上傳了示例項目GitHub here。下載後,您可能需要重建項目以同步相關的軟件包。

編輯:答案

以供將來參考,在情況下,如果像我這樣的AngularJS初學者看這個問題,答案如下。 基於由@Miyuru Ratnayake給出accepted answer,只是改變了

$scope.getProducts = function() { 
...... 
} 

function getProducts() { 
    ... 
} 

,並把它稱爲before the function聲明。單獨的函數activate()不是必需的。

因此控制器是這樣的:

.controller('homeCtrl', ['$scope', '$cookies', '$http', 'ProductService', '$location', function homeCtrl($scope, $cookies, $http, ProductService, $location) { 
    $scope.products = []; 
    getProducts(); 
    function getProducts() { 
     ProductService.getProducts().then(function (response) { 
      $scope.products = response.data; 
     }, function (err) { 
      alert(err); 
     }); 
    }; 
}]) 
+1

你看到任何錯誤?當你從瀏覽器訪問yoursite/api/productapi時會發生什麼,你會得到什麼數據? –

+1

爲什麼要返回IQueryable?只需返回列表。 – Crowcoder

+1

查看瀏覽器網絡控制檯是否有錯誤。最有可能被擊中的端點不正確。 – Chandermani

回答

2

你應該調用的getProducts在控制()方法的地方......我沒有看到它獲取調用。

通常我創建如下一個激活方法並調用它的控制範圍內:

(function() { 
    'use strict'; 
    angular.module('app') 
    .controller('homeCtrl', ['$scope', '$cookies', '$http', 'ProductService', '$location', function homeCtrl($scope, $cookies, $http, ProductService, $location) { 
     $scope.products = []; 

     activate(); 

     function activate() { 
      getProducts(); 
     } 

     function getProducts() { 
      ProductService.getProducts().then(function (response) { 
       $scope.products = response.data; 
      }, function (err) { 
       alert(err); 
      }); 
     }; 
    }]) 
    .service('ProductService', ['$http', function ($http) { 
     this.getProducts = function() { 
      return $http.get('/api/ProductAPI'); 
     }; 
    }]); 
})(); 
+0

我試過你的代碼,仍然沒有結果。我會將我的完整項目上傳到GitHub。 – Dush

+0

我在GitHub中添加了完整的示例https://github.com/dush-a/WebApiAngular – Dush

+0

我已經更改了上面的代碼,現在它可以工作... –

0

你忘了定義API調用內部方法的名稱,試試這個:

.service('ProductService', ['$http', function ($http) { 
    this.getProducts = function() { 
     return $http.get('/api/ProductAPI/myProducts'); 
    }; 
}]); 
+0

方法名稱對於給定的控制器不是必需的,因爲它只有一個GET方法,並且它使用[HttpGet]屬性進行標記。 – Dush

+0

@Dush你是對的我已經完全忽略了這一點 –

0

默認ASP.NET Web API尋找「api/{controller}/{id}」這意味着它ProductAPIController應該有像GET,POST,PUT,DELETE等基於REST概念的方法來處理模型。

但在你ProductAPIController代碼的GetProducts()是定製的操作方法,飾以HTTPGET但即使是這樣的Web API路由不會明白這一點,直到你定義路由應該是「API/{控制器}/{行動}/{ id}「。

打開WebApiConfig.cs,如下更改路由模板並進行測試。 我已添加{action},以便Web API路由在API控制器中查找自定義操作。

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

只是一個建議 如果計劃使用自定義操作方法,比如「的GetProducts」,「GetProductsByName」等;使用這個路由模板。

在客戶端代碼中使用它們之前,請始終使用POSTMAN或Fiddler測試Web API。我附上了通過PostMan測試的GetProducts屏幕截圖。

GetProducts response in PostMan

+0

我想你錯過了OP說他可以成功地從瀏覽器打到端點的位置 - 這只是他角碼的一個問題。 –

+0

不錯的建議,但對於這個控制器方法名是可選的,因爲它具有[HttpGet]屬性,並且它只有一個GET方法。此外,我總是使用Fiddler測試Web服務,我在問題的評論中提到了它。 – Dush

0

如果你實際使用的代碼的當前版本,你在github上有看看瀏覽器控制檯,你會立即看到的問題是,該功能在聲明順序您控制器會導致您嘗試執行尚未定義的功能。

我重新排序控制器執行以下操作:

$scope.products = []; 

function activate() { 
    $scope.getProducts(); 
} 

$scope.getProducts = function() { 
    ProductService.getProducts().then(function (response) { 
     $scope.products = response.data; 
    }, function (err) { 
     alert(err); 
    }); 
}; 

activate(); 

此外,在您的index.cshtml你引用了錯誤的情況下,產品的詳細信息。

例如,你有這樣的:

{{item.ProductName}} 

當它應該是這樣的:

{{item.productName}} 
+0

之後不需要調用該函數:https://github.com/johnpapa/angular-styleguide#bindable-members-up-top。是的,關於變量productName的情況是一個很好的觀點。這是由於行config.Formatters.JsonFormatter.SerializerSettings.ContractResolver =新CamelCasePropertyNamesContractResolver();在WebApiConfig.cs中。這是我從另一個項目中剪切並粘貼到GitHub上的問題。我忘了刪除該行。 – Dush

+0

鏈接描述的內容和代碼不匹配(請注意代碼示例調用在控制器中聲明的函數,而您正在針對$ scope調用函數)。我從github下載了你的代碼並運行它。在瀏覽器控制檯中,對'activate()'的調用由於沒有定義'$ scope.getProducts()'而失敗。 –