Writing C# Functions
Creating Functions in C#Tutorial VideoThings you might want to knowCreating a FunctionEditing your functionSharing your functionTesting your functionWhat's next?Advanced Topics
Creating Functions in C#
By uploading a function to Hypar you can produce multiple options for a building problem in just a few seconds, and combine them with other people's functions to create rich, realistic designs. In this introduction to Hypar, we'll work with a much simpler function that generates masses of variable dimensions.
Tutorial Video

Pre-requisites
Pre-flight checkC# and Revit Prerequisites
Installing and Using the Hypar Command Line Interface (CLI)Things you might want to know
- It's helpful to review the short conceptual overview of Hypar Elements, Functions, and Workflows before beginning this tutorial.
- Basic familiarity with the C# programming language will help, but if you're not familiar with C# we'll do our best to walk you through making changes to the initial code you'll get by following the steps in this guide.
- If you want to share your Hypar functions, you have to explicitly make your work public, so don't worry that perfect strangers are judging your work. They will, but only if you decide to make them public.
- The procedures you'll use in this guide compile your code on your desktop and only upload the resulting binary file. No one at Hypar will examine your source code because we won't have it unless you make it public by some other means or if you send it to us so we can help you solve a problem.
- None of the Hypar libraries you'll use in this guide bind your code to Hypar web services. For example, if you'd like to use the Elements library for a desktop application, it's an open source project on GitHub and will always be free for anyone to use or extend. You don't even have to tell us you're using it.
Creating a Function
- Next, return to the Hypar web interface and sign in. Scroll down to see Your Functions, and click New Function followed by New C# Function.


- This wizard will take you through setting up your function. For consistency with the rest of this example, give your function the name Starter Function.

- Click Next to proceed to configuring your function's inputs. Click or drag three "Range" inputs and name them Width, Length, and Height, and set their minimum values to 1:

- You can also select "Preview" to visualize how the inputs will look in the function.
- Go on to the next step. We'll save the Connections section for another tutorial, so click next again so that Step 4: Outputs is highlighted at the top. Click the + to add a new output to report the box's volume, and configure it like so:

- Move on to the final step, Logic. Click "Publish Function," and then click the button to copy the terminal command.


- Now your function has been published (privately) to Hypar! Next, we'll write some code to define the logic for the function.
- Return to your command prompt. Decide where you want Hypar to save the code for your function on your computer, and use the
cd
command to set that location as the current working directory:
cd C:/users/yourUserName/repos
- Then paste the command you copied from the Hypar web interface, and run that (don't copy the one below, it won't have the right ID):
hypar new --function-id=96a0df70-2a7d-4612-9c0e-7f6d86830576
- A bunch of messages will go by as Hypar sets up your local project.

- Next, open VS Code and open the project folder we just created. It should be in the location you picked earlier, with the folder name "StarterFunction."
- The Hypar CLI just created a bunch of files for you. Here's what that looks like in VS Code:

- It may seem like a lot, but the good news is you rarely have to edit most of these files — Hypar takes care of all of that for you. Any file you see that ends with
.g.cs
is not meant to be edited by you.
The file we care about most is StarterFunction.cs in the
/src
directory — this contains the logic for your function. Let's open it up.The
Execute
method is the entry point into our function. It doesn't do anything very exciting right away; it creates an "Outputs" object, and returns it.
Note that the method has a few arguments. The one called
input
contains the inputs we defined earlier, like Width, Length, and Height. Let's use some of those inputs to create a rectangle. Add this line to your function, in between the two existing lines of the method:var rectangle = Polygon.Rectangle(input.Width, input.Length);

- Next we'll make a
Mass
Element to pass out to the Hypar 3d environment. Note that if you want something to show up in the 3d view, it has to be an Element of some kind. Add this line after the rectangle:
var mass = new Mass(rectangle, input.Height);

- We also have to put the mass we created in the output model, like so:
output.Model.AddElement(mass);

- Finally, we created an output called
Volume
to report the box's volume. These data outputs are provided to the constructor for theOutputs
object — so let's edit the first line of our method to look like this:
var output = new StarterFunctionOutputs(input.Width * input.Length * input.Height);
- Our function should look like this when we're all done. Be sure to save the file!
public static StarterFunctionOutputs Execute(Dictionary<string, Model> inputModels, StarterFunctionInputs input) { // create an outputs object and populate any output values var output = new StarterFunctionOutputs(input.Width * input.Length * input.Height); // create a rectangle var rectangle = Polygon.Rectangle(input.Width, input.Length); // create a mass from the rectangle var mass = new Mass(rectangle, input.Height); // add the mass to the output model output.Model.AddElement(mass); return output; }
- To publish our changes to the web, open up your command prompt again (or open VS Code's integrated terminal). Make sure your working directory is the one Hypar created for you — you might need to
cd StarterFunction
first. Then publish your function logic like this:
hypar publish

- Now your function logic has been added to your function on Hypar. Let's go test it out! Return to hypar.io and sign in.
- Create a new workflow by clicking New Workflow and selecting New Blank Workflow. Once it opens up, give it a name in the nav bar. Type in any name you want (perhaps "Starter workflow"). You'll see this screen:

- In the Function Library panel, search for "Starter Function" (or whatever you named your function).
- Now let's try out our function. Click Insert on Starter Function and hide the Function Library by clicking the "X" to close it. Your function will run automatically and you should see something like this:

You've just run a web application that you created!
- Click in the 3D view to zoom, pan, and rotate the result. Now click on Starter Function to open up its inputs. Try adjusting the sliders to see how the mass changes shape. Check the "Sample Range" checkbox under the height and width sliders. Then click the "Alternatives" button on your workflow to see the options that have been generated.

In the alternatives list, you can see that your function has actually run many times with different input values. Click different alternatives to view them in 3D. The range sliders on the left are set to allow all possible lengths and widths. You can shrink these ranges to generate just the options you want.

- This diagram summarizes the process we just went through to create, define, and publish our function:

Editing your function
While developing a function, you may need to add additional inputs or outputs and change function logic. In this section we'll see how to do this.

In your workflow, you should see an "About" link under the name of your function. Click it to open the function details. As the owner of this function, you have the ability to make changes here.

Switch to the Inputs tab and click Edit Function Details at the bottom of the window. This brings us to the same interface we used to create the inputs originally.

Let's add a new Color input by dragging "Color" to the top. We'll call it "Mass Color" and click the color swatch to set a different color as the default. Any value you set in this window will be the default value that shows up when your function is added to a workflow.

Switch to the Outputs tab so we can add an output for the base area of our mass. Click + to add it, and configure it like so:

Click Save Changes to register your changes to the function's configuration.
Next, we'll need to pull those changes into our local code files, so that we can use the new input and output. Switch to the Logic tab and copy the second command:
hypar pull && hypar init
hypar pull
pulls the changes we made in the web interface to our hypar.json
configuration file, and hypar init
generates new code files from that configuration. You are also welcome to run these commands independently — you don't need to copy them from the web every time.Let's return to VS Code, and take a closer look. If you select
hypar.json
in the righthand side, you can view the configuration that describes this function.
If you scroll down, you should see our new Color input and Area output reflected:

Advanced users may find it easier to edit
hypar.json
manually rather than editing the function in the web UI and running hypar pull
— it's completely up to you. Just remember to use hypar init
after any changes to hypar.json
to make sure the corresponding C# code gets regenerated.Returning to
StarterFunction.cs
, we can take advantage of our new inputs and outputs. We'll edit the first line to add the base area output:var output = new StarterFunctionOutputs(input.Width * input.Length * input.Height, input.Width * input.Length);
And create a new material before we create our mass:
var material = new Material("Box Color", input.MassColor);
And finally add the material to the mass.
var mass = new Mass(rectangle, input.Height, material);
Here's how the updated
Execute
method code should look now:public static StarterFunctionOutputs Execute(Dictionary<string, Model> inputModels, StarterFunctionInputs input) { // create an output objectvar output = new StarterFunctionOutputs(input.Width * input.Length * input.Height, input.Width * input.Length); // create a rectanglevar rectangle = Polygon.Rectangle(input.Width, input.Length); // create a new materialvar material = new Material("Box Color", input.MassColor); // create a mass from the rectanglevar mass = new Mass(rectangle, input.Height, material); // add the mass to the output model output.Model.AddElement(mass); return output; }
Be sure to save the file, and then publish these changes by running
hypar publish
again. Then we'll return to our workflow on Hypar, and reload the page to update the function. You may have to adjust a slider value to cause the function to recompute.

This diagram summarizes the steps we've taken to edit and update our function:

Sharing your function
Your function always starts out private to you: only you can see and use it in a workflow. Once you're happy with your function, you can share it with the world!
Click the "About" link under your function name again, and this time navigate to the Permissions tab.

Uncheck the Private checkbox to make your function public. You can also choose to share it in a more limited way, by sharing with specific email addresses or with a whole email domain (like
myfirm.com
).You may also want to add a thumbnail to your function so others can get a sense of what it does. To do this, go to the
Details
tab, click
Edit Function Details
, and drag-and-drop an image on the drop zone. Then click
Save Changes
to save the thumbnail.

Testing your function
There are two ways to test a function.
Testing with hypar runGenerating a local testhypar run
is a live, highly interactive method, that lets you see the results of your code changes in a workflow, nearly instantly.
hypar test generate
constructs a local test for in-depth debugging, or testing against multiple scenarios.
Here is a video that demonstrates both methods:

What's next?
Congratulations on creating your first Hypar function! There's more to learn, but you should start thinking about building a real, useful function. Here are a few tips for deciding what to make:
- Solve one small problem. Hypar Functions are easy to compose. No single function needs to do too much on its own.
- Take something you've done before and do it again on Hypar.
- Scratch an itch. What do you hate doing manually? What would look cool? What would look silly?
- You don't need to be original. Just get started. Feel free to make another version of something you've already seen.
Here are some other good resources:
- Hypar's Discord live chat. Lots of people should be there to answer questions or share ideas.
- Hypar's YouTube channel has walkthrough videos and livestreams.
- The Elements GitHub repository and the tabs on top of this page have more information about Hypar's data model.
- Hypar's Building Blocks repo has the source code for many Hypar functions. Read those to see how they work, and feel free to branch or improve any of them.
Advanced Topics
- Use Function Staging to safely test out new updates to your function without breaking anything for existing users:
- Learn about Overrides, to create richer, more intelligent interactions with your functions, in way that can balance automation with human design intervention:
- Learn about Element Instances, to efficiently create multiple copies of a piece of geometry as output from your function:
- Create detailed elements from GLTF models by utilizing Content Elements:
- Create model views for your users with View Scopes:
- Express relationships between elements:
- Use Queries to select elements and get data:
- Create custom model exporters to download different file types from a Hypar workflow: