Proper formatting of Stand Alone C# Script?

Hello there.
So, I’m looking into adding a C# script as part of a Step in a deployment process, but am having a really hard time finding a reference that show how to properly “format” the script for use by Octopus.

One thing I did find was that all references need to be explicit. So for instance, if the script makes use of HttpClient to make a GET request, you can’t rely on a using statements to shorten the reference, but instead have to use the “fully qualified namespace”.

So basically instead of being able to do this:
HttpClient client = new HttpClient();

You have to do it like this:
System.Net.Http.HttpClient client = new System.Net.HttpClient()

Okay, so I’ve modified my script to make explicit reference to any class or method within its given namespace.

Now, what happens if I have a custom class? How do I handle that? I’ll illustrate what I mean with an example. Say I have the following:

using System;

namespace MyOctoScript
{
      class Person
      {
             public string name { get; set; }
      }

     class Script
     {
          static System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
          static System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
          public const string endpoint = "some_valid_endpoint";

           static async System.Threading.Tasks.Task Main(string [] args)
           {
                 MyOctoScript.Person person = null;

                // Use Http Client to fetch JSON from a given endpoint
                System.Net.Http.HttpResponseMessage response = await client.GetAsync(endpoint);

               // Parse JSON from response
               string jsonString = await response.Content.ReadAsStringAsync();
              
              // Store object in variable of type Person
              person = serializer.Deserialize<MyOctoScript.Person>(jsonString);
           }
     }
}

Now, this script works as a console application. I want to ensure it works once I add it as a C# script that is part of a Step.

What changes do I need to make to the code above to achieve this?

Thanks to anyone in advance!

Hi Juan,

Thanks for reaching out. C# scripting is slightly different to regular C# code in the way certain things are declared, we can still use using statements, however we need to explicitly define and references in the script file, as we don’t have a project file to reference the assemblies. There is also no need for a Main method in the script.
I have converted your C# example into a working C# script example.

#r "System.Configuration"
#r "System.Collections"
#r "System.Runtime"
#r "System.Web"
#r "System.Web.Extensions"
#r "System.Net.Http"
#r "System.Net"

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Script.Serialization;

public class Person {
    public string name { get; set; }
}

var client = new HttpClient();
var serializer = new JavaScriptSerializer();
var endpoint = "some_valid_endpoint";

Person person = null;

// Use Http Client to fetch JSON from a given endpoint
var response = client.GetAsync(endpoint).Result;

// Parse JSON from response
string jsonString = response.Content.ReadAsStringAsync().Result;
              
// Store object in variable of type Person
person = serializer.Deserialize<Person>(jsonString);

It is indeed quite hard to find any good examples on writing C# scripts, I have found one article here that covers some of the basics.

I hope that helps, please let me know if you have any further questions.

Kind Regards,
Tom

Hello Tom.

Thank you very much for taking the time to post a helpful reply.
I do have a follow up question regarding the asynchronous operations in the script.

In a regular C# application, you would use the await keyword before an asynchronous expression.
In the example C# script you provided, I noticed that while asynchronous methods are still being used (GetAsync, ReadAsStringAsync) all uses of await have been removed.

Why is that and will this still work?

Thank you for the article as well; I’ll make sure to read through it.

Never mind Tom, I ran it in the C# command line and it worked!
Does that mean it will also work on Octopus? Does Octopus use the C# REPL Command-Line Interface in the background to run C# scripts?

Hi Juan,
I’m glad that helped. Regarding your question around the awaitkeyword, you can definetly use async code in C# scripts, its just there is not async entry point to the script. you would need to a create a Task to handle async code and get the results.
Behind the scenes Octopus uses scriptcs to run C# scripts.

I hope that helps, please let me know if you have any further questions.

Kind Regards,
Tom

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.