0
votes

Does anyone encounter this error before and could shed some light for me? I was stuck for days :(

Promise Error

I'm trying to call my Web API function using a Promise function in my typescript file. Basically I am trying to pass a list of keys(int or string) to my Web API and i encountered the error there. Does anyone know how to solve this issue with (must be instanceof Promise error) ?

Controller:

import { Injectable } from 'angular2/core';
import { Http, Headers, RequestOptions } from '@angular/http';
import 'rxjs/add/operator/toPromise';
import 'rxjs/add/operator/map';

export class WorkOrderService {
    private tasks: any;
    private taskItems: any;
    private woSummary: any;


    static get parameters() {
        return [[Http]];
    }

    public constructor(private http: Http) {
    }

public DownloadWO(ClientApiUrl, workOrders) {

    var headers = new Headers();
    headers.append('Content-Type', 'application/json');

    var workOrderKeys = new Array();

    for (let workOrder of workOrders) {
        if (workOrder.checked) {
            workOrderKeys.push(workOrder.WorkOrderKey);
        }
    }

    //ERROR CANT SOLVE
    return new Promise((resolve, reject) => {
        this.http.post(ClientApiUrl + "workorder/UpdateAndLockWorkOrders", workOrders, { headers: headers })
            .map(res => res.json())
            .subscribe(
            data => {
                resolve(data);
            },
            err => {
                reject(err);
            });
    });
}

}

Behind-code .ts

import { Component } from '@angular/core';
import { AlertController, ModalController, NavController, LoadingController } from 'ionic-angular';

import { Global } from '../../app/global';

import { LocationService } from '../../services/locationService';
import { DepartmentService } from '../../services/departmentService';
import { WorkOrderService } from '../../services/workOrderService';

import { HomePage } from '../home/home';
import { ModalPmTaskPage } from './modal-pmTask'

@Component({
    selector: 'page-downloadWO',
    templateUrl: 'downloadWO.html'
})

export class DownloadWOPage {
    private sites: any;
    private selectPLocID: string;
    private selectedSite: number;
    private parentLocations: any;
    private selectedPLocation: number;
    private locations: any;
    private selectedLocation: number;
    private departments: any;
    private selectedDepartment: number;
    private fromDate: Date;
    private toDate: Date;
    private workOrders: any;
    private isLock: number;
    private pmTaskItems: any;

    public constructor(
        private navCtrl: NavController,
        private workOrderService: WorkOrderService,
        private locationService: LocationService,
        private departmentService: DepartmentService,
        private global: Global,
        private alertCtrl: AlertController,
        private modalCtrl: ModalController,
        private loadingCtrl: LoadingController) {   
    }

public download() {
        let loader = this.loadingCtrl.create({
            content: "Please wait..."
        });

        //Download & Lock WorkOrders
        this.workOrderService.DownloadWO(this.global.getClientApiUrl(), this.workOrders).then(data => {
            loader.dismiss();
            let alert = this.alertCtrl.create({
                title: 'Success',
                subTitle: 'Work Orders has downloaded sucessfully',
                buttons: [{
                    text: 'OK',
                    handler: () => {
                        this.navCtrl.push(HomePage);
                    }
                }]
            });
            alert.present();
        }).catch(function (err) {
            loader.dismiss();
            let alert = this.alertCtrl.create({
                title: 'Error',
                subTitle: err,
                buttons: [{
                    text: 'OK'
                }]
            });
            alert.present();
        });
    }
}

HTML:

<ion-content>
...
    <ion-item-divider color="primary">Select Work Order</ion-item-divider>
    <ion-scroll scrollY="true" style="height:50vh;">
        <ion-list>
            <ion-item text-wrap *ngFor="let workOrder of workOrders;">
                <ion-checkbox [(ngModel)]="workOrder.checked" >{{workOrder.checked}}</ion-checkbox>
                <ion-label>
                    <h2>
                        <b>Work Order ID:</b> {{workOrder.WorkOrderID}}
                    </h2>
                    <h2>
                        <b>PM Task ID:</b> {{workOrder.TaskId}}
                    </h2>
                    <h2>
                        <b>Asset ID:</b> {{workOrder.AssetID}}
                    </h2>
                    <button ion-button color="secondary" (click)="viewTaskItemFromServer(workOrder.WorkOrderKey)">View PM Task Items</button>
                </ion-label>
            </ion-item>
        </ion-list>
    </ion-scroll>
    <button ion-button block (click)="download()">Download</button>
</ion-content>

C# Web API:

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using MaxPro_WebService.Interface.Controllers;
using MaxPro_WebService.Interface.Models;
using System.Net.Http.Headers;
using System.Web.Script.Serialization;
using CMMS.AssetsMaintMgmt_BLLAx;
using System.Transactions;
using System.IO;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;

namespace MaxPro_Client_WebService.Controllers
{
    [RoutePrefix("api/WorkOrder")]
    public class WorkOrderController : ApiController, IWorkOrderController
    {
        [Route("UpdateAndLockWorkOrders")]
        [HttpPost]
        public async Task<HttpResponseMessage> UpdateAndLockWorkOrders([FromBody]List<string> workOrderKeys)
        {
            string errorMsg, exMsg;
            errorMsg = exMsg = string.Empty;
            DateTime dtNow = DateTime.Now;

            errorMsg = exMsg = string.Empty;

            try
            {

                using (var client = new HttpClient())
                {
                    ////IL: TRY TO PASS IN CLASS
                    //client.BaseAddress = new Uri("http://localhost/MaxPro_WebService/");
                    //client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    //var response = await client.PostAsJsonAsync("api/WorkOrder/uploadWorkOrders", workOrders);
                    IEnumerable<WorkOrder> workorders = null;
                    client.BaseAddress = new Uri(ConfigurationManager.AppSettings["ServerBaseURLAddress"]); //Question how to get URL of web service
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                    var response = await client.PostAsJsonAsync("api/WorkOrder/GetWorkOrders", workOrderKeys);

                    if (response.IsSuccessStatusCode)
                    {
                        string responseString = response.Content.ReadAsStringAsync().Result;
                        //JSON Object TO Work Order class
                        workorders = response.Content.ReadAsAsync<IEnumerable<WorkOrder>>().Result;
                        if (InsertRecords(workorders, out errorMsg))
                        {
                            //IL: 3/2/2017 working for LockWorkOrder
                            //client.BaseAddress = new Uri(ConfigurationManager.AppSettings["ServerBaseURLAddress"]); //Question how to get URL of web service
                            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                            response = await client.PostAsJsonAsync("api/WorkOrder/LockWorkOrders", workOrderKeys);

                            if (response.IsSuccessStatusCode)
                            {
                                //LOCKING SUCCESSFUL
                                return Request.CreateResponse(HttpStatusCode.OK);
                            }
                            else
                            {
                                //LOCKING UNSUCCESSFUL
                                return Request.CreateErrorResponse((HttpStatusCode)422, new HttpError(exMsg));
                                //Something has gone wrong, handle it here
                            }
                        }
                        else
                        {
                            //SAVE WO UNSUCCESSFUL
                            return Request.CreateErrorResponse((HttpStatusCode)422, new HttpError(exMsg));
                            //Something has gone wrong, handle it here
                        }
                    }
                    else
                    {
                        //Something has gone wrong, handle it here
                        return Request.CreateErrorResponse((HttpStatusCode)422, new HttpError(exMsg));
                    } 
                }
            }
            catch (TransactionAbortedException ex)
            {
                exMsg = ex.Message;
                return Request.CreateErrorResponse((HttpStatusCode)422, new HttpError(exMsg));
            }
            catch (ApplicationException ex)
            {
                exMsg = ex.Message;
                return Request.CreateErrorResponse((HttpStatusCode)422, new HttpError(exMsg));
            }
            catch (Exception ex)
            {
                exMsg = ex.Message;
                return Request.CreateErrorResponse((HttpStatusCode)422, new HttpError(exMsg));
            }
        }
    }
}

Enviroments:

IDE: VS2015 Cordova CLI: 6.5.0

Ionic CLI Version: 2.2.1

Ionic App Lib Version: 2.2.0

OS: Windows 7

Node Version: v7.6.0

Xcode version: not installed

2
So what exactly is the problem?Robert Moskal
The promise function gave me an error (must be instanceof Promise error) during debugging. So i was trying to google search for lots of solutions but couldn't solve the issue.Irving Lee

2 Answers

2
votes

The http module of Angular 2 returns an Observable and not a promise.
You can convert it to a promise using Observable.toPromise() to use in your promise chain. Try:

 return new Promise((resolve, reject) => {
        this.http.post(ClientApiUrl + "workorder/UpdateAndLockWorkOrders", workOrders, { headers: headers })
            .map(res => res.json()).toPromise()//convert to promise
            .then(//call then instead of subscribe to form the promise chain.
            data => {
                resolve(data);
            },
            err => {
                reject(err);
            });
    });

Another way is simplifying without encapsulating with a new promise:

return this.http.post(ClientApiUrl + "workorder/UpdateAndLockWorkOrders", workOrders, { headers: headers })
                .map(res => res.json()).toPromise()//convert to promise

Your catch in the end will get the error from the chain.

0
votes

Try specifying type after promise, something like this :

return new Promise < any> ((resolve, reject).....