1

I have a problem consuming data from an ASP.NET Core 2.0 Web API with Angular 5+.

Here the steps i have done:

  1. I have built an ASP.NET Core 2.0 WebAPI and deployed it on a server. I can consume data from postman or swagger without any problems.
  2. Then i have created with NSwagStudio the client TypeScript service classes for my angular frontend app.

Now the problem: I can make a request to the wep api from the frontend app and i am also recieveing the correct data in JSON-Format. But while the mapping process to the poco object in the generated client service class, something doesnt work. I always get an object with empty attributes.

Here my code:

product.service.ts
export class ProductService {
  private http: { fetch(url: RequestInfo, init?: RequestInit): Promise<Response> };
  private baseUrl: string;
  protected jsonParseReviver: (key: string, value: any) => any = undefined;

  constructor() {
      this.http = <any>window;
      this.baseUrl =  "http://testweb01/FurnitureContractWebAPI";
  }

  getByProductId(productId: string): Promise<Product[]> {

      let url_ = this.baseUrl + "/api/Product/GetById?";
      if (productId === undefined)
          throw new Error("The parameter 'productId' must be defined.");
      else
          url_ += "productId=" + encodeURIComponent("" + productId) + "&"; 
      url_ = url_.replace(/[?&]$/, "");

      let options_ = <RequestInit>{
          method: "GET",
          headers: {
              "Content-Type": "application/json", 
              "Accept": "application/json"
          }
      };

      return this.http.fetch(url_, options_).then((_response: Response) => {
          return this.processGetByProductId(_response);
      });
  }

protected processGetByProductId(response: Response): Promise<Product[]> {
      const status = response.status;
      let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
      if (status === 200) {
          return response.text().then((_responseText) => {
          let result200: any = null;
          let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
          if (resultData200 && resultData200.constructor === Array) {
              result200 = [];
              for (let item of resultData200) {
                var x = Product.fromJS(item);
                //console.log(x);
                result200.push(Product.fromJS(item));
              }

          }
          //console.log(result200);
          return result200;
          });
      } else if (status !== 200 && status !== 204) {
          return response.text().then((_responseText) => {
          return throwException("An unexpected server error occurred.", status, _responseText, _headers);
          });
      }
      return Promise.resolve<Product[]>(<any>null);
  }

And here the methods from the Product-class:

init(data?: any) {
    console.log(data);
      if (data) {
          this.productId = data["ProductId"];
          this.productNameDe = data["ProductNameDe"];
          this.productNameFr = data["ProductNameFr"];
          this.productNameIt = data["ProductNameIt"];
          this.supplierProductId = data["SupplierProductId"];
          this.supplierProductVarId = data["SupplierProductVarId"];
          this.supplierProductVarName = data["SupplierProductVarName"];
          this.supplierId = data["SupplierId"];
          this.supplierName = data["SupplierName"];
          this.additionalText = data["AdditionalText"];
          this.installationCost = data["InstallationCost"];
          this.deliveryCost = data["DeliveryCost"];
          this.sectionId = data["SectionId"];
          this.categorieId = data["CategorieId"];
          this.price = data["Price"];
          this.ean = data["Ean"];
          this.brand = data["Brand"];
          this.modifiedDate = data["ModifiedDate"] ? new Date(data["ModifiedDate"].toString()) : <any>undefined;
          this.categorie = data["Categorie"] ? ProductCategory.fromJS(data["Categorie"]) : <any>undefined;
          this.section = data["Section"] ? ProductSection.fromJS(data["Section"]) : <any>undefined;
      }
  }

  static fromJS(data: any): Product {
      data = typeof data === 'object' ? data : {};
      let result = new Product();
      result.init(data);
      return result;
  }

In the init() method when i look at data, it contains all the values i need. But when i for example use data["ProductId"] the value is null/undefined.

Can anyone please help?

Thanks

Here is a screenshot of my console output of the data object: enter image description here

Leon
  • 443
  • 5
  • 19

2 Answers2

0

Now I could figure out, that i can cast the data object directly to Product:

  init(data?: any) {
    var p = <Product>data;

This works, but i am asking myself, why does the generated class have an init-method with manually setting of the attributes, when it is possible to cast the object directly?

Leon
  • 443
  • 5
  • 19
  • You should not change the generated output. We have the mapping to correctly convert property names and values (eg dates) – Rico Suter May 18 '18 at 17:38
0

NSwag is misconfigured, use DefaultPropertyNameHandling: CamelCase for ASP.NET Core

Or use the new asp.net core api explorer based swagger generator which automatically detects the contract resolver. (Experimental)

Rico Suter
  • 11,548
  • 6
  • 67
  • 93