Skip to content

Creating Plugins

CorbinDallas edited this page Feb 11, 2013 · 6 revisions

#Getting Started# Oda plugins are .Net assemblies. So step one of creating any Oda plugin is to create a new .Net library in your favorite IDE. I'll be referring to Visual Studio 2012 and C# a lot because that's what I'm using. The next step is to add the Oda.Core.dll assembly as a reference. If you don't have it yet, download Oda.Core from the Oda.Core Repository and build it. Once you've made a reference to this assembly (the DLL file you built from the repository) then you're ready to start writing your plugin.

##Making your assembly an Oda Plugin## Oda plugins are public, non-static classes that inherit the abstract class Oda.Plugin. That means your "Main" class or whatever you want to call your plugin's main class should look sort of like this:

public class MyPluginClass : Plugin { }

And that's it! Now you've created an Oda plugin! You just need to build it and place it in the /bin directory next to Oda.Core.dll on the web site you want to run Oda from. Because your class inherits the abstract class Oda.Plugin Oda will automatically pick up your plugin from the /bin directory and do "stuff" with it. What stuff it does is up to you and we'll cover that in a minute. Information about your Plugin will be shown to users and other plugins, this information is stored in the /Properties/AssemblyInfo.cs file in your project. You can access this information (if you're using Visual Studio) by right clicking on the project file and choosing "Properties". But that's not so important to the functionality of your program.

##Subscribing to Events## There are a lot of events you can subscribe to in the Oda.Core class, but perhaps the most important for a plugin is Oda.Core.Initialize. This event occurs when Oda turns on for the first time. Inside the constructor method for your class you can subscribe to this event. To subscribe to this event add a line like this in your constructor method:

Oda.Core.Initialize += new EventHandler(Core_Initialize);

This will look for a method called Core_Initialize method in your class. The signature (and the rest of the first line) of this method must look like this:

void Core_Initialize(object sender, EventArgs e) {

Inside of this method you can do whatever it is your plugin does when it turns on. Connects to a database? Load up files from the file system or embedded resources, launch nukes etc..

##Plugin Dependency## Sometimes you'll want your plugin to require that another plugin is present and loaded before your plugin. For example, if you want to access a Microsoft SQL Server, you might want to use the Oda.Sql plugin as a dependency. To declare dependencies use the following attribute above your class definition.

[PluginDependencies(typeof(<dependent plugin type>))]

Where is the name of the dependent plugin. For example:

[PluginDependencies(typeof(Oda.Sql))]

You can add up to 10 plugins to the list by separating them with commas.

[PluginDependencies(typeof(<dependent plugin type 1>), typeof(<dependent plugin type 2>), typeof(<dependent plugin type 3>))]

For example:

[PluginDependencies(typeof(Oda.Sql), typeof(Oda.UI), typeof(Oda.Authentication))]

In the unlikely event that you have more than 10 dependent plugins, or you just want to use an array, you can use an array with the PluginDependencies class constructor.

[PluginDependencies(new Type[<array bounds>]{<array of types>})]

For Example:

[PluginDependencies(new Type[2]{typeof(Oda.Sql), typeof(Oda.UI)})]

Where exactly do I place this again? What's a class definition?

That's the place where you declare you class in your code. For example:

[PluginDependencies(typeof(Oda.Sql))]

public class MyOdaPlugin: Plugin {

##Mapping Methods## Methods that will be available to people making requests to a web site need to follow a few easy rules.

  1. They must belong to a class that inherits the abstract class Oda.JsonMethods.
  2. They must be public and static.
  3. They must return Oda.JsonReponse.
  4. They must only accept parameters of the following types: Dictionary<string, object>, List, Primitive types Int64, Decimal, String or Boolean.

The abstract class JsonResponse is full of goodies, but we'll just concentrate on the important members for now.

Note: The base class of Oda.JsonResponse is a System.Collections.Generic.Dictionary so you might be familiar with how this class works.

###Error### This property is a signed integer (which means it can be positive or negative number) that when there is no error should be 0. When there is an error is should be anything but 0. The number that you set it to is up to you, but the number should identify to your users what sort of error occurred. This doesn't have to be unique to the error that occurred, but it would be nice if it was unique.

###Message### This is a message returned from your method to the calling (usually JavaScript) function letting it know how everything went, and if there was an error what the human readable nature of the error was.

###void Add(string Key, object Value)### This is perhaps the most important member. It allows you to add new key/value pairs to your response. You can add any JSON compatible objects to your JsonResponse and they will be returned as JSON to the calling function.

###Status Code and Status### Here you can set the Status Code (200 by default) and Status (OK by default) to let the browser know in the header what to do. You can issue any HTTP status codes, like 404, 500, 302 etc.. Google status codes to learn more about them.

###ContentDisposition### The Content disposition is usually a JSON response, but you might want to return another type of content. Perhaps you want to return a file, like an image or a PDF. Or maybe you want to return a HTML or XML page. Note: if your ContentDisposition is anything but JSON, then only this response will be returned, although the other responses will still be invoked.

If you're changing the ContentDisposition you'll also want to change the ContentType to match whatever content you're sending the client. ContentType is a standard MIME content type string that will appear in the HTTP header. If you're sending a file to be saved it's also a good idea to set the AttachmentFileName property.

#Utilities in the Oda.Plugin abstract class# We're not just going to leave you hanging when it comes to working in Oda. To help work with your plugin, a few methods are included in the Oda.Plugin class to help you out.

###object GetPlugin(Type) and object GetPlugin(string)### This will return the instance of a plugin that has been loaded by Oda. This will allow you to interact with other plugins in Oda by fetching the instance that was loaded during start up.

##Embedded Resource Helpers## An embedded resource is any file (or other object?) that has the build action in its properties set to "Embedded resource". The file will be added to the assembly on build and can be easily accessed with the following methods. Each of the methods accepts a string, the string is the relative path to the embedded file in your assembly.

###Overriding Embedded Files### Any embedded file looked up using the following methods can be "overridden" during run time by adding a file with the same name to a folder with your namespace, class and path in the root directory of your web site. For example, if you have a plugin called Tonys.MyPlugin and you've embedded the file /img/MyPicture.gif, adding the file and directory Tonys.MyPlugin/img/MyPicture.gif to the root directory of the host web site will override and replace the file embedded in your plugin assembly. This is useful for altering implementations of your plugin without having to recompile the plugin.

###string GetResourseString### This method will get a string by fetching a embedded file.

###Bitmap GetResourceImage### This method will get a System.Drawing.Bitmap from a embedded image.

###stream GetResource(String)### This method will get a System.IO.Stream embedded in your assembly. This is raw way of getting embedded files out of your assembly and useful if you're embedding unusual files like audio or zip files or anything that's not plain text or an image.

#Recommendations For Plugins That Use SQL# If you plan on using SQL in your plugin, we recommend you use the Oda.Sql plugin. Also we recommend you embed your SQL queries as separate .SQL files in your assembly so they can be override at run-time by people who use your plugin. We also recommend you check for the presence of and create any tables required for your plugin during the Oda.Core initialization event or during your plugins initialization procedure so a separate installation procedure isn't necessary. These are just recommendations, you're welcome to ignore them of course. For examples, check out Oda.Authentication.

Clone this wiki locally