ASP.NET CoreとAngularでWebページを開発

# ASP.NET CoreとAngularでWebページを開発

Visual Studioを使用したASP.NET Core開発でAngularのページを作成する。サーバからデータを受信したり、ページに入力した値をPostする方法について記載する。

### 環境

Windows 10 ver 10.0.17134
Visual Studio Community 2017 ver 15.7.1
.NET Framework ver 4.7.03056
.NET Core Framework ver 2.0.7
Angular ver 4.2.5

## Getする

component.ts側は、http.getでASP側のコントローラ（クラス名＋メソッド名）に対応したURLを指定する。データはthis.productsに格納される。

```component.ts
http.get(this.baseUrl + 'api/OrderData/Stocks').subscribe(result => {
this.products= result.json() as Product[];
```

ASPのコントローラは、ルーティング属性がHttpGetで、クラス名＋メソッド名が一致するメソッドにマッピングされる。

```OrderDataController.cs
[Route("api/[controller]")]
public class OrderDataController : Controller
{
    [HttpGet("[action]")]
    public IEnumerable<Product> Stocks()
    {
        return new ProductDao().GetStocks();
    }
```

受け渡しするデータ（ここでは『 Product[] 』）は、ASP側とts側に同じものを入れる型を用意する。ASP側はgetter等を実装する予定のためクラスを作成する。ts側はJSONを受け取るときの型定義に使うだけなので、同名で内容は空のインタフェースを作成する。ts側の型でメソッドを実装したければクラスでも構わないし、Stock等の別名にしてもよい。

```ProductDto.cs
public class Product
{
    public int Id                       { get; set; }
    public string ProductName           { get; set; }
    public bool WithReport              { get; set; }
    public string TicketNo              { get; set; }
}
```

```component.ts
interface Product{
}
```

## データをtsとhtmlとの間で受け渡す

htmlではNgForOfディレクティブでデータの件数分ループし、テーブル行を作成する。インデックス（『i』）が振られるので、エレメントに『i』を含めたidを割り当てる。

```component.html
    <p *ngIf="!products"><em>Loading...</em></p>
    <table *ngIf="products">
        <thead>
            <tr>
                <th>品名</th>
                <th>レポート有り</th>
                <th>伝票No.</th>
            </tr>
        </thead>
        <tbody>
            <tr *ngFor="let product of products; index as i">
                <td><input type="text" id="product_name-{{ i }}" value="{{ product.productName }}" (blur)="GetStockInfo()" /></td>
                <td><input type="checkbox" id="with_report-{{ i }}" checked="{{ product.reportChecked }}" /></td>
                <td>{{ product.ticketNo }}</td>
            </tr>
        </tbody>
    </table>
```

ts側からは、行インデックスを含めたidによって、getElementById()メソッドで値が取得できる。

```component.ts
this.updateList= new Array();    
for (var i = 0; i < this.rowCount; i++) {
    var item = new Product();
    item.withReport = (<HTMLInputElement>document.getElementById("with_report-" + i.toString())).checked;
    item.productName = (<HTMLInputElement>document.getElementById("product_name-" + i.toString())).value;
    updateList.push(item);
}
```

## Postの場合

データ更新処理等でtsからPostするときは、パラメタを持って、http.postをする。Getと同じくASP側のコントローラに対応したURLを指定する。

```component.ts
public updateList: Array<Product> | undefined;

this.http.post(this.baseUrl + 'api/UpdateData/Stocks', updateList).subscribe(result => {
```

ASPのコントローラは、ルーティング属性がHttpPostのメソッドにマッピングされる。PostによってリクエストBodyに格納されているデータは[FromBody]属性を付けることにより、受け取りが可能となる。

```UpdateDataController.cs
[HttpPost("[action]")]
public void Stocks([FromBody] List<Product> updateList)
{
    new ProductsDao().InsertProduct(new ConvertProducts(updateList));
}
```

## 表示、非表示を切り替える

NgIfディレクティブで切り替える。値はboolean型ならtrueのとき表示する。配列型ならnullでないとき表示する。

```component.html
<div *ngIf="showBlock"></div>
<p *ngIf="!products"></p>
```

```component.ts
    public products: Product[] | undefined;
    public showBlock: boolean = true;
```

boolean型なら反転させるだけで切替できる。
`this.showBlock= !this.showBlock;`

ボタンに割り当てるならこんな感じ。

```component.html
<input type="submit" value="表示切替" (click) ="showBlock= !showBlock" />
```

## URLパラメタを受け渡す

URLパラメタを付けて遷移するにはrouter.navigateを使う。

```component.ts
    public router: Router | undefined;
    var param = "data";
    this.router.navigate(['proposal'], { queryParams: { id: param} });
```

受け取る側のtsは、コンストラクタでwindow.location.hrefを参照する。
` var url = window.location.href;`
下記のエラーが出る場合がある。
*ReferenceError: window is not defined*
以下のようにプラットフォームを調べてから実行すれば、エラーは出なくなる。

```component.ts
    public isBrowser: boolean;

    constructor(http: Http, @Inject('BASE_URL') baseUrl: string) {
        this.isBrowser = isPlatformBrowser(PLATFORM_ID);
        if (this.isBrowser) {
            var url = window.location.href;
```