projects/wms-framework/src/lib/wcfserviceinvocationsupport/SoapMessage.ts
Properties |
|
Methods |
|
constructor(baseUrl: string, methodName: string, namespace: string, contract: string)
|
Creates an instance of SoapMessage that will be sent to the given baseUrl |
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. |
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
|
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;
}
}
}
}