BusinessEventsEndpointBase - send
This is the method where it trigger the logic.
--------------------------------------------------------------------------------------------------------
For sending the authentication we need to add new class for logic
using System.IO;
using System.Net;
using Microsoft.Dynamics.ApplicationPlatform.XppServices.Instrumentation;
/// <summary>
/// The <c>BusinessEventsHttpAdapter</c> sends the payload for business events to Http endpoint.
/// </summary>
/// <remarks>
/// There may be size restrictions in place for the target http end point. These size restrictions are not checked.
/// </remarks>
// This is a framework class. Customizing this class may cause problems with future upgrades to the software.
[BusinessEventsEndpoint(BusinessEventsEndpointType::HttpsWithHeaders)]
internal final class BusinessEventsHttpsWithHeadersAdapter extends BusinessEventsEndpointBase implements IBusinessEventsEndpoint
{
private str url;
private BusinessEventsId bussinessEventsId;
public void initialize(BusinessEventsEndpoint _endpoint, boolean _forceCreate)
{
this.endpoint = _endpoint;
if (!(_endpoint is BusinessEventsAzureEndpoint))
{
BusinessEventsEndpointManager::logUnknownEndpointRecord(tableStr(BusinessEventsAzureEndpoint), _endpoint.RecId);
}
bussinessEventsId = endpoint.KTBusinessEventId;
if(!bussinessEventsId)
{
throw warning(strFmt("@BusinessEvents:MissingAdapterConstructorParameter", classStr(BusinessEventsHttpAdapter), varStr(bussinessEventsId)));
}
this.parmBusinessEventId(endpoint.KTBusinessEventId);
BusinessEventsAzureEndpoint businessEventsHttpEndpoint = _endpoint as BusinessEventsAzureEndpoint;
str httpUrl = BusinessEventsEndpointManager::getAzureSecret(businessEventsHttpEndpoint, _forceCreate);
if (!httpUrl)
{
throw warning(strFmt("@BusinessEvents:MissingAdapterConstructorParameter", classStr(BusinessEventsHttpAdapter), varStr(httpUrl)));
}
this.parmUrl(httpUrl);
}
/// <summary>
/// Set and get the url
/// </summary>
/// <param name = "_url">Url</param>
/// <returns>Url</returns>
internal str parmUrl(str _url = url)
{
url = _url;
return url;
}
/// <summary>
/// Set and get the Business EventId
/// </summary>
/// <param name = "_businessEventId">businessEventId</param>
/// <returns>businessEventId</returns>
internal BusinessEventsId parmBusinessEventId(BusinessEventsId _businessEventsId = bussinessEventsId)
{
bussinessEventsId = _businessEventsId;
return bussinessEventsId;
}
/// <summary>
/// Send the payload to Http endpoint
/// </summary>
/// <param name = "_payload">Content of business event to be sent</param>
/// <param name = "_context">Context of the payload to be sent</param>
/// <exception>
/// NotSupportedException
/// The request scheme specified in requestUriString has not been registered.
/// ArgumentNullException
/// requestUriString is null.
/// SecurityException
/// The caller does not have WebPermissionAttribute permission to connect to the requested URI or a URI that the request is redirected to.
/// UriFormatException
/// In the .NET for Windows Store apps or the Portable Class Library, catch the base class exception, FormatException, instead.
/// The URI specified in requestUriString is not a valid URI.
/// NotImplementedException
/// Any attempt is made to access the method, when the method is not overridden in a descendant class.
/// ArgumentException
/// The sum of offset and count is greater than the buffer length.
/// ArgumentNullException
/// buffer is null.
/// ArgumentOutOfRangeException
/// offset or count is negative.
/// IOException
/// An I/O error occured, such as the specified file cannot be found.
/// NotSupportedException
/// The stream does not support writing.
/// ObjectDisposedException
/// Write(Byte[], Int32, Int32) was called after the stream was closed.
/// </exception>
[Hookable(false)]
protected void sendPayload(str _payload, BusinessEventsEndpointPayloadContext _context)
{
// convert payload string to byte array
var utf8 = System.Text.Encoding::get_UTF8();
var byteArrayPayload = utf8.GetBytes(_payload);
HttpWebRequest request;
if (_context is BusinessEventsCommitLogPayloadContext)
{
// Set Business Events properties
BusinessEventsCommitLogPayloadContext commitLogPayloadContext = _context as BusinessEventsCommitLogPayloadContext;
request = this.createHttpWebRequest(byteArrayPayload.get_Length(),commitLogPayloadContext.parmBusinessEventId());
}
else
{
BusinessEventsContract businessContract = FormJsonSerializer::deserializeObject(className2Id(classStr(BusinessEventsContractWithOnlyBaseFields)),_payload);
request = this.createHttpWebRequest(byteArrayPayload.get_Length(),businessContract.parmBusinessEventId());
}
int responseStatusCode = -1; //default to something obviously not a real status code
// send out the payload
using (System.IO.Stream dataStream = request.GetRequestStream())
{
dataStream.Write(byteArrayPayload, 0, byteArrayPayload.Length);
}
// request.GetResponse() may already result in an error if the request was e.g. a Bad Request(Status Code 400). This should be handled upstream via our global error handling.
using (HttpWebResponse response = request.GetResponse())
{
responseStatusCode = response.StatusCode;
}
// Narrowing it down. We support only response codes in the 200 range for the standard adapter. Redirects are not supported.
// Whereas some failures are handled via GetResponse() some other issues may not be. E.g. certain redirect codes where the target doesn't exist anymore.
if (responseStatusCode < 200 || responseStatusCode >= 300)
{
throw warning(strFmt("@BusinessEvents:BusinessEventsHttpResponseNotOK", classStr(BusinessEventsHttpAdapter), int2Str(responseStatusCode)));
}
}
/// <summary>
/// creates http web request
/// </summary>
/// <param name = "_contentLength">content length</param>
/// <param name = "businessEventId">Business EventId</param>
/// <returns>Http request</returns>
internal HttpWebRequest createHttpWebRequest(int _contentLength,BusinessEventsId businessEventId)
{
KTBusinessEventsHeaderDefinitionTable businessEventHeaders;
// create the request and set method, content type, and length
HttpWebRequest request = WebRequest::Create(url);
request.Method = 'POST';
request.ContentType = 'application/json';
request.ContentLength = _contentLength;
request.timeout = BusinessEventsParameters::getHttpTimeoutInMilliseconds();
// set RunId header on request
WebHeaderCollection headerCollection = request.Headers;
str runId = guid2Str(getCurrentThreadActivityId());
headerCollection.Set('x-ms-workflow-run-id', runId);
if(businessEventId == classStr(BusinessEventsTestEndpointContract))
{
businessEventId = bussinessEventsId;
}
// LogicApps logs this header which can then be used for correlation.
while select businessEventHeaders where businessEventHeaders.BusinessEventId == businessEventId
{
headerCollection.Set(businessEventHeaders.BusinessEventHeaderKey,businessEventHeaders.BusinessEventHeaderValue);
}
return request;
}
public boolean isTransient(System.Exception _exception)
{
if (_exception is System.ObjectDisposedException)
{
return true;
}
else if (_exception is System.IO.IOException)
{
return true;
}
else if (_exception is WebException)
{
WebException webException = _exception as WebException;
HttpWebResponse response = webException.Response;
if (webException.Message.Contains('The operation has timed out') ||
(response != null &&
(response.StatusCode == HttpStatusCode::ServiceUnavailable || response.StatusCode == 429)))
{
return true;
}
}
return false;
}
}
---------------------------------------------------------------
/// <summary>
/// Extension class for Business Event Endpoint Configuration for Custom Endpoint Type
/// </summary>
[ExtensionOf(formStr(BusinessEventsEndpointConfiguration))]
final class BTBusinessEventsEndpointConfiguration_Extension
{
/// <summary>
/// Method to get the concentrate Type Details
/// </summary>
/// <param name = "_endpointType">The Endpoint Object</param>
/// <returns>returns the Table that need to be displayed</returns>
public TableName getConcreteTableType(BusinessEventsEndpointType _endpointType)
{
TableName tableName = next getConcreteTableType(_endpointType);
if (_endpointType == BusinessEventsEndpointType::HttpsWithHeaders)
{
tableName = tableStr(BusinessEventsAzureEndpoint);
}
return tableName;
}
/// <summary>
/// Method to display Other Fields durin Custom Endpoint Type
/// </summary>
public void showOtherFields()
{
next showOtherFields();
this.control(this.controlId(formControlStr(BusinessEventsEndpointConfiguration,
HTTPWithHeadersEndpointFields))).visible(false);
BusinessEventsEndpointType selection =
any2Enum(EndpointTypeSelection.selection());
if (selection == BusinessEventsEndpointType::HttpsWithHeaders)
{
this.control(this.controlId(formControlStr(BusinessEventsEndpointConfiguration,
AzureEndpointFields))).visible(true);
this.control(this.controlId(formControlStr(BusinessEventsEndpointConfiguration,
HTTPWithHeadersEndpointFields))).visible(true);
}
}
}
---------------------------------------------------------------------------------
Extend the enum to add new additional element
BusinessEventsEndpointType.BTextension
--Add new Table(BTBusinessEventsHeaderDefinitionTable) form, menu item and menu, privilages
add fields on table
1.Header key
2.Header value,
3.BusinessEventId field and lookup
4.add relation BusinessEventTable and link the field BusinessEventId
on the form design header value control - set password style- YES
--------------------------------------------------------------------------------
Extend the table BusinessEventsEndpoint.BTextension
and add BTBusinessEventId field
and add Relation with BusinessEventsTable to link with business event id
No comments:
Post a Comment