File

projects/wms-framework/src/lib/wcfserviceinvocationsupport/SoapMessage.ts

Extends

Message

Index

Properties
Methods

Constructor

constructor(baseUrl: string, methodName: string, namespace: string, contract: string)

Creates an instance of SoapMessage that will be sent to the given baseUrl

Parameters :
Name Type Optional
baseUrl string No
methodName string No
namespace string No
contract string No

Properties

Public Namespace
Type : string

Namespace of the service being called

Public BaseUrl
Type : string
Inherited from Message
Defined in Message:36

The service base url. This message uses the base url to create the final url using message information such as end point suffic, post or get or method name

Public EndpointSuffix
Type : string
Default value : ''
Inherited from Message
Defined in Message:44

Specifies and addition suffix to be appended to the base url

Headers
Type : SimpleList<MessageHeader>
Default value : new SimpleList<MessageHeader>()
Inherited from Message
Defined in Message:61

List of Headers

methodName
Type : string
Default value : null
Inherited from Message
Defined in Message:69

Name of the method to call

requestArgs
Type : any[]
Default value : []
Inherited from Message
Defined in Message:77

Request arguments

responseType
Type : string
Default value : 'json'
Inherited from Message
Defined in Message:93

The expected response type from the request.

result
Type : any
Inherited from Message
Defined in Message:85

Service result

Public UsePost
Type : boolean
Default value : true
Inherited from Message
Defined in Message:53

Indicates whether this message must be sent using a POST called instead of the default GET method.

Methods

Public buildBody
buildBody()
Inherited from Message
Defined in Message:81

Builds the message body to be sent to the server side. The message is compliant with Soap Envelope

Returns : string
Public buildPostResult
buildPostResult(userData: any, result: any)
Inherited from Message
Defined in Message:92
Parameters :
Name Type Optional
userData any No
result any No
Returns : IAsyncResult
Public buildUrl
buildUrl()
Inherited from Message
Defined in Message:70

Builds the url of this SoapMessage by returning the base url only

Returns : string

{string}

import { SupportDateTime } from '../baseframework';
import { ObservableCollection } from '../baseframework/collections';
import { IAsyncResult } from './AsyncResultSupport';
import { Message } from './Message';
import { MessageHeader } from './MessageHeader';
import { SoapAsyncResult } from './soapAsyncResult';

export class SoapMessage extends Message {
  /**
   * Namespace of the service being called
   *
   * @type {string}
   * @memberof SoapMessage
   */
  public Namespace: string;

  /**
   * Creates an instance of SoapMessage that will be sent to the given baseUrl
   * @param {string} baseUrl
   * @memberof SoapMessage
   */
  constructor(
    baseUrl: string,
    methodName: string,
    namespace: string,
    contract: string
  ) {
    super();
    this.BaseUrl = baseUrl;
    this.methodName = methodName;
    this.Namespace = namespace;
    this.Headers.add(
      new MessageHeader('Accept', '', 'text/xml; charset=utf-8')
    );
    this.Headers.add(
      new MessageHeader('Content-Type', '', 'text/xml; charset=utf-8')
    );
    this.Headers.add(
      new MessageHeader(
        'SOAPAction',
        '',
        `${namespace}/${contract}/${methodName}`
      )
    );
    this.responseType = 'text';
  }

  /**
   * Builds the url of this SoapMessage by returning the base url only
   *
   * @return {*}  {string}
   * @memberof SoapMessage
   */
  public buildUrl(): string {
    return this.BaseUrl;
  }

  /**
   * Builds the message body to be sent to the server side.  The message is compliant with
   * Soap Envelope
   *
   * @return {*}
   * @memberof SoapMessage
   */
  public buildBody() {
    const bodyStart =
      '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body>';
    const bodyEnd = '</s:Body></s:Envelope>';

    let serializer: SoapMessageSerializer = new SoapMessageSerializer();
    let parameters = serializer.toXml(this.requestArgs);
    return `${bodyStart}<${this.methodName} xmlns="${this.Namespace}">${parameters}</${this.methodName}>${bodyEnd}`;
  }

  // inherited
  public buildPostResult(userData: any, result: any): IAsyncResult {
    let operationResult: SoapAsyncResult = new SoapAsyncResult();
    operationResult.AsyncState = userData;
    operationResult.IsCompleted = true;
    operationResult.resultData = {
      message: this,
      d: typeof result?.d !== 'undefined' ? result.d : result,
    };
    return operationResult;
  }
}

/**
 *  Defines an object that serializes elements to xml format understood by SOAP tehcnology.
 *
 * @class SoapMessageSerializer
 */
class SoapMessageSerializer {
  /**
   * Converts a collection of arguments to xml soap representation.
   *
   * @param {any[]} requestArgs  the objects to be converted as {name, value} object
   * @return {*}  {string} the xml representing the args serialized
   * @memberof SoapMessageSerializer
   */
  toXml(requestArgs: any[]): string {
    let parameters = '';
    for (const arg of requestArgs) {
      parameters = parameters + this.serializeParameter(arg.name, arg.value);
    }
    return parameters;
  }

  /**
   * Serializes a single parameter element.  A simple serialized parameter looks like
   * <param1>4</param1>
   *
   * @private
   * @param {string} paramName Name of the parameter to serialize
   * @param {*} paramValue value of the parameter to serialize
   * @return {*}
   * @memberof SoapMessageSerializer
   */
  private serializeParameter(paramName: string, paramValue: any) {
    if (paramValue instanceof ObservableCollection) {
      return this.serializeCollectionParam(
        paramName,
        paramValue as ObservableCollection<unknown>
      );
    }
    if (paramValue && paramValue.getName && paramValue.getScheme) {
      return this.serializeComplexParameter(paramName, paramValue);
    } else {
      let valueSerialized = this.serialize(paramValue);
      return `<${paramName}>${valueSerialized}</${paramName}>`;
    }
  }

  /**
   * Serializes a scalar value object.
   *
   * @private
   * @param {*} value  the object to serilize
   * @return {*}  {*}
   * @memberof SoapMessageSerializer
   */
  private serialize(value: any): any {
    switch (typeof value) {
      case 'string':
      case 'number':
      case 'boolean':
        return value;
      default:
        if (value instanceof Date) {
          return value.toISOString();
        }
    }
    return null;
  }

  private serializeCollectionParam(
    paramName: string,
    collection: ObservableCollection<unknown>
  ): string {
    if (collection.count > 0 && (collection.getItem(0) as any).getScheme) {
      let properties = '';
      collection.forEach(
        (entity) => (properties += this.serializeEntity(entity))
      );
      let scheme = (collection.getItem(0) as any).getScheme();
      return `<${paramName} xmlns:d4p1="${scheme}" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">${properties}</${paramName}>`;
    }
    return '';
  }
  /**
   * Serializes a complex value (an entity such as Employee).  Entities to be serilized must have the
   * getScheme and getName methods defined.
   *
   * @private
   * @param {string} paramName Name of the parameter to serialize
   * @param {*} entity the value of the paramter to serialize
   * @return {*}  {string}
   * @memberof SoapMessageSerializer
   */
  private serializeComplexParameter(paramName: string, entity: any): string {
    let properties = '';
    properties = this.serializeEntity(entity);
    return `<${paramName} xmlns:d4p1="${entity.getScheme()}" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">${properties}</${paramName}>`;
  }

  /**
   * Serializes a comple entity object by generating an xml tag for every entity property.
   * @param entity the object to serialize
   * @returns
   */
  private serializeEntity(entity: any): string {
    let properties: string = '';
    for (let propName of this.getEntityProperties(entity)) {
      let value: any = entity[propName];
      properties += this.serializeEntityProperty(propName, value);
    }
    return `<d4p1:${entity.getName()}>${properties}</d4p1:${entity.getName()}>`;
  }

  /**
   * Serializes and entity property
   *
   * @private
   * @param {string} propName name of the property to serializer
   * @param {*} value value to serialize
   * @return {*}
   * @memberof SoapMessageSerializer
   */
  private serializeEntityProperty(propName: string, value: any) {
    if (!this.mustSkipSerialization(value)) {
      if (value !== null) {
        let valueAsStr: string = this.serializeProperty(value);
        return `<d4p1:${propName}>${valueAsStr}</d4p1:${propName}>`;
      } else {
        return `<d4p1:${propName} i:nil="true" />`;
      }
    }
    return '';
  }

  /**
   * Indicates whether a property must be serialized or not.
   * For now Date set to null must not be serialized
   *
   * @private
   * @param {*} value the value to test for
   * @return {*}  {boolean} true if value must be serialized
   * @memberof SoapMessageSerializer
   */
  private mustSkipSerialization(value: any): boolean {
    return value instanceof Date && SupportDateTime.IsMinValue(value);
  }

  /**
   * Serializes a given property value.  Currently there is support of scalar values, ObserverableCollections objects
   * and other Entity objects.
   *
   * @private
   * @param {*} value
   * @return {*}  {string}
   * @memberof SoapMessageSerializer
   */
  private serializeProperty(value: any): string {
    let valueAsStr: string = '';
    if (value instanceof ObservableCollection) {
      valueAsStr = this.serializeCollection(
        value as ObservableCollection<unknown>
      );
    } else if (value && value.getName && value.getScheme) {
      valueAsStr = this.serializeEntity(value);
    } else {
      valueAsStr = this.serialize(value);
    }
    return valueAsStr;
  }

  /**
   * Serializes an { ObservableCollection } object by serializing everyone of its elements.
   *
   * @private
   * @param {ObservableCollection<unknown>} collection the collection to serialize
   * @return {*}  {string}
   * @memberof SoapMessageSerializer
   */
  private serializeCollection(
    collection: ObservableCollection<unknown>
  ): string {
    let valueAsString: string = '';
    for (const e of collection) {
      valueAsString += this.serializeEntity(e);
    }
    return valueAsString;
  }

  /**
   * Gets all the entity properties to serialize.  Because the entity must be decorated with the {@link Entity}
   * decorator it is required to look one level up
   *
   * @private
   * @param {*} entity the entity to extract properties for
   * @memberof SoapMessageSerializer
   */
  private *getEntityProperties(entity) {
    // go to prototype of up because of annotation
    let entityPrototype = Object.getPrototypeOf(Object.getPrototypeOf(entity));
    let descriptors = Object.getOwnPropertyDescriptors(entityPrototype);
    for (var propName in descriptors) {
      let propDefinition = descriptors[propName];
      if (propDefinition.get && propDefinition.set) {
        yield propName;
      }
    }
  }
}

result-matching ""

    No results matching ""