# RemoteLaunch Development in .NET Framework

## Overview

The RemoteLaunch SDK is used to launch a WorkflowGen process from the outside of the WorkflowGen environment. This section will explain how to develop a RemoteLaunch SDK application using WorkflowGen.My v3.3. You'll need to create a new website for each RemoteLaunch SDK application you need.

{% hint style="warning" %}
This integration is not supported when using OpenID Connect authentication methods (Microsoft Entra ID, AD FS, Auth0, Okta). Alternative solutions would be to use a GraphQL API request with a server-side script or to use webhooks.

See the following documentation for instructions on how to configure each method for server-side scripts:

* [Microsoft Entra ID configuration for server-side scripts](https://docs.workflowgen.com/azure/azure-active-directory-configuration-for-server-side-scripts)
* [AD FS configuration for server-side scripts](https://docs.workflowgen.com/tech/adfs-integration/server-side-scripts)
* [Auth0 configuration for server-side scripts](https://docs.workflowgen.com/tech/auth0-integration/server-side-scripts)
* [Okta configuration for server-side scripts](https://docs.workflowgen.com/tech/okta-integration/server-side-scripts)
  {% endhint %}

## Creating the RemoteLaunch website

### Suggested development tools

* Visual Studio Standard or Professional 2013 or later

### Website installation directory

We strongly suggest that you put all of your RemoteLaunch SDKs in the `\wfgen\wfapps\sdk\MyRemoteLaunch` folder.

### Creating the application in IIS

The RemoteLaunch site directory must be declared as an IIS application in order to be recognized as a .NET website application. Follow these instructions to declare your website directory as an IIS application:

#### For IIS 7 and later

1. Open Internet Information Services (IIS) Manager.
2. Navigate to your web form location, which should be placed under the **Default Web Site** node, under `\wfgen\wfapps\sdk\MyRemoteLaunch`.
3. Right-click on **MyRemoteLaunch** and choose **Convert to Application**.
4. Select the application pool used by your site and another specific application pool.
5. Click **OK**.

## Creating the project with Visual Studio

### Creating the project

1. Open Visual Studio.
2. Choose **File > New Web Site**.
3. Select **ASP.NET Empty Web Site**.
4. Select **File system** from the **Location** drop-down list.
5. Click **Browse** and choose the location of your ASP.NET website.
6. Click **OK**.

### Obtaining detailed error messages

By default, you will have no `web.config` file in your web project if you are using C# as your development language in the Visual Studio IDE. In order to be able to see complete error messages when you want to debug, you have to have a `web.config` file.

In order to be able to see complete error messages, change the following properties in the `web.config` file:

1. Make sure this line is set to `"true"`:

   ```html
   <compilation debug="true" />
   ```
2. Make sure this is not commented and that the `mode="Off"`:

   ```html
   <customErrors mode="Off" defaultRedirect="GenericErrorPage.htm">
        <error statusCode="403" redirect="NoAccess.htm" />
        <error statusCode="404" redirect="FileNotFound.htm" />
   </customErrors>
   ```

## Basic implementation

### Overview

In order to demonstrate how to implement a RemoteLaunch application, we'll make a simple RemoteLaunch example that sends a context containing two parameters to a WorkflowGen process: `AMOUNT` and `NAME`. This process will be launched with these two parameters.

### Reference

You must add a reference to `WorkflowGen.My.dll` in your web project, then add a `using` statement for the `WorkflowGen.My.Data` namespace of the WorkflowGen.My assembly.

```csharp
using WorkflowGen.My.Data;
```

## Defining the `Page_Load` event

We'll use the `Page_Load` event to immediately start the remote process. Here is the basic code structure we are going to use for the RemoteLaunch SDK application:

```csharp
protected void Page_Load(object sender, EventArgs e)
{
    // Call the main function
    RemoteProcessLaunch();
}

/// <summary>
/// RemoteProcessLaunch
/// </summary>
private void RemoteProcessLaunch()
{
    ...
}
```

### Using the `web.config` to store your configurations

It is suggested to use the `web.config` file to store all the configurations, instead of hard coding them directly in your website's code-behind. The advantage to this is that if you modify the name of the process to launch, or the username of the launching user, or any other configurations, you will not have to change your code-behind files, only your `web.config` file, without recompiling the web application. Here are the `web.config` values that we'll use:

```html
<appSettings>
    <add key="WorkflowGenLaunchUrl" value="http://localhost/wfgen/show.aspx?QUERY=PROCESS_START_REMOTE"/>
    <add key="WorkflowGenUsername" value="wfgen_admin"/>
    <add key="WorkflowgenUserPassword" value="Advantys123"/>
    <add key="WorkflowGenUserDomain" value=""/>
    <add key="ProcessName" value="SDK_CS_REMOTE_LAUNCH"/>
    <add key="Language" value="en-US"/>
    <add key="RequesterUsername" value="wfgen_admin"/>
    <add key="Test" value="Y"/>
</appSettings>
```

The following code declares all the variables we need for the RemoteLaunch, then gets the `web.config` values to populate some of these variables.

```csharp
// Variables Declaration
System.Net.HttpWebRequest httpWebReq = null;            // Http web request object
System.Net.HttpWebResponse httpWebResp = null;            // Http web response object
System.Net.NetworkCredential myCred = null;            // To hold credential information
System.Net.CredentialCache myCache = null;            // credential cache
System.Text.ASCIIEncoding encoding = null;            // for encoding
System.IO.Stream myStream = null;            // To get request data
System.IO.StreamReader myReader = null;            // To read response stream
string respCode;            // string used to get response status code
string workflowContextXml;            // string to get the xml context data
string appUrl = string.Empty;            // string used to Approval URL
string postData = null;            // string used to put the data for request
string response = null;            // string used to display response
byte[] buffer;            // byte used to get the encoded data

// Get values into Configuration constants
// Get the Launch URL
workflowGenLaunchUrl = ConfigurationManager.AppSettings["WorkflowGenLaunchUrl"].ToString();

// Get the WorkflowGen user username
workflowGenUsername = ConfigurationManager.AppSettings["WorkflowGenUsername"].ToString();

// Get the WorkflowGen user password
workflowgenUserPassword = ConfigurationManager.AppSettings["WorkflowgenUserPassword"].ToString();

// Get the WorkflowGen user domain
workflowGenUserDomain = ConfigurationManager.AppSettings["WorkflowGenUserDomain"].ToString();

// Get the process name
processName = ConfigurationManager.AppSettings["ProcessName"].ToString();

// Get the culture information
language = ConfigurationManager.AppSettings["Language"].ToString();

// Get the requester name, default is wfgen_admin
requesterUsername = ConfigurationManager.AppSettings["RequesterUsername"].ToString();

// Get the launch test mode status
test = Convert.ToChar(ConfigurationManager.AppSettings["Test"].ToString());
```

### Building a context from scratch

We now need to build a new context to send to WorkflowGen, to start the new process that needs two parameters: `AMOUNT` and `NAME`, which are numeric and text parameters, respectively. Here is the necessary code to create a new context:

```csharp
// Create a new WorkflowGen object for context parameters
WorkflowGen.My.Data.ContextParameters myWorkflowContextParameters = new
WorkflowGen.My.Data.ContextParameters();

// Create a new AMOUNT context parameter object
WorkflowGen.My.Data.ContextParameter contextParamAmount = new
WorkflowGen.My.Data.ContextParameter();

// Set the parameter name
contextParamAmount.Name = "AMOUNT";

// Set the direction for the parameter
contextParamAmount.Direction = WorkflowGen.My.Data.ContextParameter.Directions.In;

// Set parameter type as double
contextParamAmount.Type = typeof(double);

// Set parameter value
contextParamAmount.Value = Convert.ToDouble(10000);

// Adding the parameter to the context parameters
myWorkflowContextParameters.Add(contextParamAmount);

// Updating the context parameters
myWorkflowContextParameters.Update();
WorkflowGen.My.Data.ContextParameter contextParamName = new
WorkflowGen.My.Data.ContextParameter();

// Set the parameter name
contextParamName.Name = "NAME";

// Set the direction for the parameter
contextParamName.Direction = WorkflowGen.My.Data.ContextParameter.Directions.In;

// Set parameter type as string
contextParamName.Type = typeof(string);

// Set parameter value
contextParamName.Value = "SDK SAMPLE TEXT";

// Adding the parameter to the context parameters
myWorkflowContextParameters.Add(contextParamName);

// Updating the context parameters
myWorkflowContextParameters.Update();

// Get the xml context data into variable
workflowContextXml = myWorkflowContextParameters.GetXml();
```

### Starting the process and sending the context

After having created the context, we need to make a web request to WorkflowGen to start the remote process, and we also need to post the context to the new process instance. Here is the necessary code:

```csharp
// Call WorkflowGen to instantiate the process
// Prepare the URL
appUrl = workflowGenLaunchUrl + "&L=" + language + "&PROCESS=" + processName + "&REQUESTER_USERNAME=" + requesterUsername + "&TEST=" + test;

// Submit the parameters
myCred = new System.Net.NetworkCredential(workflowGenUsername,workflowgenUserPassword, workflowGenUserDomain);
myCache = new System.Net.CredentialCache();
myCache.Add(new Uri(workflowGenLaunchUrl), "Basic", myCred);

// Prepare a request
httpWebReq = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(appUrl);
httpWebReq.Method = "POST";

// Set authentication information
httpWebReq.Credentials = myCache;

// Set CONTEXT content
postData = "CONTEXT=" + HttpUtility.UrlEncode(workflowContextXml.ToString());
encoding = new System.Text.ASCIIEncoding();
buffer = encoding.GetBytes(postData);

// Set the content type of the data being posted.
httpWebReq.ContentType = "application/x-www-form-urlencoded";

// Set the content length of the string being posted.
httpWebReq.ContentLength = postData.Length;

// Send the CONTEXT
myStream = httpWebReq.GetRequestStream();
myStream.Write(buffer, 0, buffer.Length);

// Close the Stream object.
myStream.Close();
```

### Managing errors

After starting the process, you might receive errors from WorkflowGen if something is not working as expected. Here is the necessary code to display the WorkflowGen error so that you can debug your RemoteLaunch application:

```csharp
// Try block to handle exception
try
{
    // Check the WorkflowGen response status
    httpWebResp = (System.Net.HttpWebResponse)httpWebReq.GetResponse();
}
// Catch the exception
catch (WebException e)
{
    // Display the error message
    Response.Write(e.ToString());
    return;
}

respCode = "OK"; // response code variable

// Check the response status code is OK
if (respCode != httpWebResp.StatusCode.ToString())
{
    // Display the Error details
    Response.Write("Error:" + httpWebResp.StatusCode);
}
else
{
    // Gets the stream associated with the response
    httpWebResp = (System.Net.HttpWebResponse)httpWebReq.GetResponse();
    myReader = new System.IO.StreamReader(httpWebResp.GetResponseStream());
    response = myReader.ReadToEnd();
    httpWebResp.Close();

    // Display response message
    Response.Write(response);
}
```
