├── CSScript ├── Global.asax ├── Metadata │ └── deploymentTemplates │ │ └── apiappconfig.azureresource.json ├── apiapp.json ├── Global.asax.cs ├── App_Start │ ├── WebApiConfig.cs │ └── SwaggerConfig.cs ├── packages.config ├── Web.Debug.config ├── Web.Release.config ├── Properties │ └── AssemblyInfo.cs ├── Web.config ├── Controllers │ └── CompileController.cs └── CSScript.csproj ├── CSScript.sln ├── LICENSE ├── .gitattributes ├── README.md ├── .gitignore └── azuredeploy.json /CSScript/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="CSScript.WebApiApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /CSScript/Metadata/deploymentTemplates/apiappconfig.azureresource.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schemas.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "$system": { 6 | "type": "Object" 7 | } 8 | }, 9 | "resources": [] 10 | } -------------------------------------------------------------------------------- /CSScript/apiapp.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schemas/2014-11-01/apiapp.json#", 3 | "id": "CSharpAPI", 4 | "namespace": "logicappsio.com", 5 | "gateway": "2015-01-14", 6 | "version": "1.0.0", 7 | "title": "CSharp API", 8 | "summary": "Compiles C# Scripts", 9 | "author": "Jeff Hollan", 10 | "endpoints": { 11 | "apiDefinition": "/swagger/docs/v1", 12 | "status": null 13 | } 14 | } -------------------------------------------------------------------------------- /CSScript/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Http; 6 | using System.Web.Routing; 7 | 8 | namespace CSScript 9 | { 10 | public class WebApiApplication : System.Web.HttpApplication 11 | { 12 | protected void Application_Start() 13 | { 14 | GlobalConfiguration.Configure(WebApiConfig.Register); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CSScript/App_Start/WebApiConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web.Http; 5 | 6 | namespace CSScript 7 | { 8 | public static class WebApiConfig 9 | { 10 | public static void Register(HttpConfiguration config) 11 | { 12 | // Web API configuration and services 13 | 14 | // Web API routes 15 | config.MapHttpAttributeRoutes(); 16 | 17 | config.Routes.MapHttpRoute( 18 | name: "CSScriptAPI", 19 | routeTemplate: "api/{controller}/{action}", 20 | defaults: new { id = RouteParameter.Optional } 21 | ); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /CSScript.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.22823.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSScript", "CSScript\CSScript.csproj", "{8DAA99D2-C633-44F4-AFFF-A2C571FCF5FF}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {8DAA99D2-C633-44F4-AFFF-A2C571FCF5FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {8DAA99D2-C633-44F4-AFFF-A2C571FCF5FF}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {8DAA99D2-C633-44F4-AFFF-A2C571FCF5FF}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {8DAA99D2-C633-44F4-AFFF-A2C571FCF5FF}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /CSScript/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Azure Logic Apps 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /CSScript/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /CSScript/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /CSScript/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("CSScript")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("CSScript")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("8daa99d2-c633-44f4-afff-a2c571fcf5ff")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /CSScript/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # C# Scripting API 2 | [![Deploy to Azure](http://azuredeploy.net/deploybutton.png)](https://azuredeploy.net/) 3 | 4 | ## Deploying ## 5 | Click the "Deploy to Azure" button above. You can create new resources or reference existing ones (resource group, gateway, service plan, etc.) **Site Name and Gateway must be unique URL hostnames.** The deployment script will deploy the following: 6 | * Resource Group (optional) 7 | * Service Plan (if you don't reference exisiting one) 8 | * Gateway (if you don't reference existing one) 9 | * API App (CSharpAPI) 10 | * API App Host (this is the site behind the api app that this github code deploys to) 11 | 12 | ## API Documentation ## 13 | The API app has one action - Execute Script - which returns a JToken based on what the script returns. 14 | 15 | The action has three input parameters: 16 | 17 | | Input | Description | 18 | | ----- | ----- | 19 | | Script | C# script syntax | 20 | | Context Object *(optional)* | Objects to reference in the script. Can pass in multiple objects, but base must be a single JObject { .. }. Can be accessed in script by object key (as a JToken). | 21 | | Libraries *(optional)* | Array of libraries to pass in and compile with script. Works from Blob/FTP Connector output of .dll files. See structure [below](#libraries-array-structure). Default libraries can be found [here](#compiler-information) | 22 | 23 | #### Context Object Structure #### 24 | ```javascript 25 | { "object1": { ... }, "object2": "value" } 26 | ``` 27 | In script could then reference object1 and object2 - both passed in as a JToken. 28 | 29 | #### Libraries Array Structure #### 30 | ```javascript 31 | [{"filename": "name.dll", "assembly": {Base64StringFromConnector}, "usingstatment": "using Library.Reference;"}, { ... } ] 32 | ``` 33 | 34 | ####AppDomain #### 35 | 36 | The script executes inside of an AppDomain that includes some standard System assemblies as well as Newtonsoft.Json. The full list can be found [here](#compiler-information) 37 | 38 | ###Trigger### 39 | You can use the C# Script API as a trigger. It takes a single input of "script" and will trigger the logic app (and pass result) whenever the script returns anything but `false`. You set the frequency in which the script runs. 40 | 41 | ## Example ## 42 | | Step | Info | 43 | |----|----| 44 | | Action | Execute Script | 45 | | C# Script | `return message;` | 46 | | Context Object | `{"message": {"Hello": "World"}}` | 47 | | Output | `{"Hello": "World"}` | 48 | 49 | You can also perform more complex scripts like the following: 50 | ####Context Object#### 51 | ```javascript 52 | { "tax": 0.06, "orders": [{"order": "order1", "subtotal": 100}] } 53 | ``` 54 | #### C\# Script #### 55 | ```csharp 56 | foreach (var order in orders) 57 | { 58 | order["total"] = (double)order["subtotal"] * (1 + (double)tax); 59 | } 60 | return orders; 61 | ``` 62 | 63 | #### Result #### 64 | ```javascript 65 | [ {"order": "order1", "subtotal": 100, "total": 106.0 } ] 66 | ``` 67 | 68 | ## Compiler Information ## 69 | 70 | The following assemblies are included by default in the script: 71 | 72 | ```csharp 73 | using System; 74 | using Newtonsoft.Json; 75 | using Newtonsoft.Json.Linq; 76 | using System.Linq; 77 | using System.Collections.Generic; 78 | using System.Net; 79 | using System.Net.Http; 80 | using System.Xml; 81 | ``` 82 | 83 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | PublishProfiles/ 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | build/ 23 | bld/ 24 | [Bb]in/ 25 | [Oo]bj/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opensdf 80 | *.sdf 81 | *.cachefile 82 | 83 | # Visual Studio profiler 84 | *.psess 85 | *.vsp 86 | *.vspx 87 | 88 | # TFS 2012 Local Workspace 89 | $tf/ 90 | 91 | # Guidance Automation Toolkit 92 | *.gpState 93 | 94 | # ReSharper is a .NET coding add-in 95 | _ReSharper*/ 96 | *.[Rr]e[Ss]harper 97 | *.DotSettings.user 98 | 99 | # JustCode is a .NET coding add-in 100 | .JustCode 101 | 102 | # TeamCity is a build add-in 103 | _TeamCity* 104 | 105 | # DotCover is a Code Coverage Tool 106 | *.dotCover 107 | 108 | # NCrunch 109 | _NCrunch_* 110 | .*crunch*.local.xml 111 | 112 | # MightyMoose 113 | *.mm.* 114 | AutoTest.Net/ 115 | 116 | # Web workbench (sass) 117 | .sass-cache/ 118 | 119 | # Installshield output folder 120 | [Ee]xpress/ 121 | 122 | # Publish Profiles 123 | Properties/PublishProfiles 124 | # DocProject is a documentation generator add-in 125 | DocProject/buildhelp/ 126 | DocProject/Help/*.HxT 127 | DocProject/Help/*.HxC 128 | DocProject/Help/*.hhc 129 | DocProject/Help/*.hhk 130 | DocProject/Help/*.hhp 131 | DocProject/Help/Html2 132 | DocProject/Help/html 133 | 134 | # Click-Once directory 135 | publish/ 136 | 137 | # Publish Web Output 138 | *.[Pp]ublish.xml 139 | *.azurePubxml 140 | ## TODO: Comment the next line if you want to checkin your 141 | ## web deploy settings but do note that will include unencrypted 142 | ## passwords 143 | #*.pubxml 144 | 145 | *.publishproj 146 | 147 | # NuGet Packages 148 | *.nupkg 149 | # The packages folder can be ignored because of Package Restore 150 | **/packages/* 151 | # except build/, which is used as an MSBuild target. 152 | !**/packages/build/ 153 | # Uncomment if necessary however generally it will be regenerated when needed 154 | #!**/packages/repositories.config 155 | 156 | # Windows Azure Build Output 157 | csx/ 158 | *.build.csdef 159 | 160 | # Windows Store app package directory 161 | AppPackages/ 162 | 163 | # Visual Studio cache files 164 | # files ending in .cache can be ignored 165 | *.[Cc]ache 166 | # but keep track of directories ending in .cache 167 | !*.[Cc]ache/ 168 | 169 | # Others 170 | ClientBin/ 171 | [Ss]tyle[Cc]op.* 172 | ~$* 173 | *~ 174 | *.dbmdl 175 | *.dbproj.schemaview 176 | *.pfx 177 | *.publishsettings 178 | node_modules/ 179 | orleans.codegen.cs 180 | 181 | # RIA/Silverlight projects 182 | Generated_Code/ 183 | 184 | # Backup & report files from converting an old project file 185 | # to a newer Visual Studio version. Backup files are not needed, 186 | # because we have git ;-) 187 | _UpgradeReport_Files/ 188 | Backup*/ 189 | UpgradeLog*.XML 190 | UpgradeLog*.htm 191 | 192 | # SQL Server files 193 | *.mdf 194 | *.ldf 195 | 196 | # Business Intelligence projects 197 | *.rdl.data 198 | *.bim.layout 199 | *.bim_*.settings 200 | 201 | # Microsoft Fakes 202 | FakesAssemblies/ 203 | 204 | # Node.js Tools for Visual Studio 205 | .ntvs_analysis.dat 206 | 207 | # Visual Studio 6 build log 208 | *.plg 209 | 210 | # Visual Studio 6 workspace options file 211 | *.opt 212 | 213 | # LightSwitch generated files 214 | GeneratedArtifacts/ 215 | _Pvt_Extensions/ 216 | ModelManifest.xml 217 | -------------------------------------------------------------------------------- /CSScript/Controllers/CompileController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.CodeDom.Compiler; 6 | using System.Web.Http; 7 | using Newtonsoft.Json.Linq; 8 | using TRex.Metadata; 9 | using System.Net.Http; 10 | using Microsoft.Azure.AppService.ApiApps.Service; 11 | using System.Diagnostics; 12 | using System.Collections.ObjectModel; 13 | using System.Web; 14 | using System.IO; 15 | 16 | namespace CSScript.Controllers 17 | { 18 | public class CompileController : ApiController 19 | { 20 | private bool compiled; 21 | //The imports that will be included when executing the script. Must be System or Newtonsoft (or you would need to change where the assemblies are referenced to include more) 22 | private const string scriptIncludes = @" 23 | using System; 24 | using Newtonsoft.Json; 25 | using Newtonsoft.Json.Linq; 26 | using System.Linq; 27 | using System.Collections.Generic; 28 | using System.Net; 29 | using System.Net.Http; 30 | using System.Xml;"; 31 | 32 | List args; 33 | 34 | private string contextTokens = ""; 35 | 36 | [HttpPost] 37 | [Metadata(friendlyName: "Execute Script")] 38 | public JToken Execute([FromBody] Body body) 39 | { 40 | if (body.context != null) 41 | GenerateArgs(body.context); 42 | 43 | if (body.libraries != null) 44 | readAttachments(body.libraries); 45 | var result = (JToken)RunScript(body.script, "JToken", body.libraries); 46 | if (compiled) 47 | return result; 48 | else 49 | { 50 | var resp = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest) 51 | { 52 | Content = new StringContent(result.ToString()), 53 | ReasonPhrase = "Compiler Error" 54 | }; 55 | throw new HttpResponseException(resp); 56 | } 57 | 58 | } 59 | 60 | 61 | [HttpGet] 62 | [Metadata(friendlyName: "Execute Script Trigger", description: "When the script returns anything but false, the Logic App will fire")] 63 | [Trigger(TriggerType.Poll)] 64 | public HttpResponseMessage ExecutePollTrigger([FromUri] string script) 65 | { 66 | 67 | JToken result = RunScript(script, "JToken", null); 68 | Debug.WriteLine(result.ToString()); 69 | if (result.ToString() == "False") 70 | return Request.EventWaitPoll(); 71 | else if (compiled) 72 | return Request.EventTriggered(result); 73 | else 74 | return Request.CreateErrorResponse(System.Net.HttpStatusCode.BadRequest, result.ToString()); 75 | } 76 | 77 | /// 78 | /// Generates variables within the script matching to the Key/Values of the context object 79 | /// 80 | /// JSON Context passed through 81 | private void GenerateArgs(JObject json) 82 | { 83 | args = new List(); 84 | foreach(var param in json) 85 | { 86 | contextTokens += "JToken " + param.Key +", "; 87 | args.Add(param.Value); 88 | } 89 | contextTokens = contextTokens.Remove(contextTokens.Length - 2, 2); 90 | } 91 | private JToken RunScript(string input, string type, Collection libraries) 92 | { 93 | compiled = false; 94 | var sourceCode = scriptIncludes + "namespace Script { public class ScriptClass { public " + type + " RunScript(" + contextTokens + ") { " + input + " } } }"; 95 | 96 | // Get a reference to the CSharp code provider 97 | using (var codeDomProvider = CodeDomProvider.CreateProvider("csharp")) 98 | { 99 | // Set compile options (we want to compile in memory) 100 | var compileParameters = new CompilerParameters() { GenerateInMemory = true }; 101 | compileParameters.GenerateExecutable = false; 102 | 103 | //Include library references, only when library contains System or Newtonsoft 104 | foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) 105 | { 106 | if (!asm.IsDynamic && ( asm.FullName.Contains("System") || asm.FullName.Contains("Newtonsoft"))) 107 | compileParameters.ReferencedAssemblies.Add(asm.Location); 108 | } 109 | if (libraries != null) 110 | { 111 | foreach (var attachment in libraries) 112 | { 113 | compileParameters.ReferencedAssemblies.Add(HttpRuntime.AppDomainAppPath + @"\" + attachment.filename); 114 | sourceCode = attachment.usingstatement + sourceCode; 115 | } 116 | } 117 | 118 | // Now compile the supplied source code and compile it. 119 | var compileResult = codeDomProvider.CompileAssemblyFromSource(compileParameters, sourceCode); 120 | 121 | if (libraries != null) 122 | { 123 | foreach (var attachment in libraries) 124 | { 125 | File.Delete(HttpRuntime.AppDomainAppPath + @"\" + attachment.filename); 126 | } 127 | } 128 | 129 | // Check for compile errors 130 | if (compileResult.Errors.Count > 0) 131 | { 132 | var errorArray = new JArray(); 133 | foreach (var error in compileResult.Errors) 134 | { 135 | errorArray.Add(error.ToString()); 136 | } 137 | return errorArray; 138 | } 139 | // If everything goes well we get a reference to the compiled assembly. 140 | var compiledAssembly = compileResult.CompiledAssembly; 141 | 142 | // Now, using reflection we can create an instance of our class 143 | var inst = compiledAssembly.CreateInstance("Script.ScriptClass"); 144 | // ... and call a method on it! 145 | object callResult; 146 | if(args != null) 147 | callResult = inst.GetType().InvokeMember("RunScript", BindingFlags.InvokeMethod, null, inst, args.ToArray()); 148 | else 149 | callResult = inst.GetType().InvokeMember("RunScript", BindingFlags.InvokeMethod, null, inst, null); 150 | compiled = true; 151 | 152 | 153 | return (JToken)callResult; 154 | } 155 | } 156 | 157 | /// 158 | /// Loop through the attachements write the .dll from the Base64String 159 | /// 160 | /// Array of libraries 161 | private void readAttachments(Collection libraries) 162 | { 163 | foreach (var library in libraries) 164 | { 165 | var file = System.Convert.FromBase64String(library.assembly); 166 | File.WriteAllBytes(HttpRuntime.AppDomainAppPath + @"\" + library.filename, file); 167 | } 168 | } 169 | 170 | 171 | public class Body 172 | { 173 | [Metadata(friendlyName:"C# Script", Visibility = VisibilityType.Default)] 174 | public string script { get; set; } 175 | 176 | [Metadata(friendlyName: "Context Object(s)", description: "JSON Object(s) to be passed into script argument. Can pass in multiple items, but base object must be single object { .. }. Can be referenced in scripted as object names")] 177 | public JObject context {get; set;} 178 | 179 | [Metadata(friendlyName: "Libraries", description: "Libraries to be included in execution of script. Array of this format [{\"filename\": , \"assembly\": , \"usingstatement\": }, ..]", Visibility = VisibilityType.Advanced)] 180 | public Collection libraries { get; set; } 181 | 182 | 183 | } 184 | 185 | public class Library 186 | { 187 | public string filename; 188 | public string assembly; 189 | public string usingstatement; 190 | } 191 | 192 | } 193 | 194 | 195 | } 196 | -------------------------------------------------------------------------------- /azuredeploy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "siteName": { 6 | "type": "string" 7 | }, 8 | "apiAppName": { 9 | "type": "string", 10 | "defaultValue": "CSharpAPI" 11 | }, 12 | "gatewayName": { 13 | "type": "string" 14 | }, 15 | "repoURL": { 16 | "type": "string" 17 | }, 18 | "branch": { 19 | "type": "string" 20 | }, 21 | "svcPlanName": { 22 | "type": "string" 23 | }, 24 | "sku": { 25 | "type": "string", 26 | "defaultValue": "Standard", 27 | "allowedValues": [ 28 | "Free", 29 | "Basic", 30 | "Standard", 31 | "Premium" 32 | ] 33 | }, 34 | "svcPlanSize": { 35 | "defaultValue": "0", 36 | "type": "string", 37 | "allowedValues": [ 38 | "0", 39 | "1", 40 | "2" 41 | ] 42 | }, 43 | "gatewayToApiAppSecret": { 44 | "defaultValue": "Y3NzY3JpcHRpbmdhcGk=", 45 | "type": "securestring" 46 | } 47 | }, 48 | "variables": { 49 | "$packageId": "Microsoft.ApiApp", 50 | "$nugetFeed": "http://apiapps-preview.nuget.org/api/v2/" 51 | }, 52 | "resources": [ 53 | { 54 | "type": "Microsoft.Web/serverfarms", 55 | "apiVersion": "2015-04-01", 56 | "name": "[parameters('svcPlanName')]", 57 | "location": "[resourceGroup().location]", 58 | "tags": { 59 | "displayName": "AppServicePlan" 60 | }, 61 | "properties": { 62 | "name": "[parameters('svcPlanName')]", 63 | "sku": "[parameters('sku')]", 64 | "workerSize": "[parameters('svcPlanSize')]", 65 | "numberOfWorkers": 1 66 | } 67 | }, 68 | { 69 | "type": "Microsoft.Web/sites", 70 | "apiVersion": "2015-04-01", 71 | "name": "[parameters('gatewayName')]", 72 | "location": "[resourceGroup().location]", 73 | "kind": "gateway", 74 | "tags": { 75 | "displayName": "GatewayHost" 76 | }, 77 | "resources": [ 78 | { 79 | "type": "providers/links", 80 | "apiVersion": "2015-01-01", 81 | "name": "Microsoft.Resources/gateway", 82 | "dependsOn": [ 83 | "[resourceId('Microsoft.Web/sites',parameters('gatewayName'))]" 84 | ], 85 | "properties": { 86 | "targetId": "[resourceId('Microsoft.AppService/gateways', parameters('gatewayName'))]" 87 | } 88 | } 89 | ], 90 | "dependsOn": [ 91 | "[concat(resourceGroup().id, '/providers/Microsoft.Web/serverfarms/',parameters('svcPlanName'))]" 92 | ], 93 | "properties": { 94 | "name": "[parameters('gatewayName')]", 95 | "gatewaySiteName": "[parameters('gatewayName')]", 96 | "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('svcPlanName'))]", 97 | "siteConfig": { 98 | "appSettings": [ 99 | { 100 | "name": "ApiAppsGateway_EXTENSION_VERSION", 101 | "value": "latest" 102 | }, 103 | { 104 | "name": "EmaStorage", 105 | "value": "D:\\home\\data\\apiapps" 106 | }, 107 | { 108 | "name": "WEBSITE_START_SCM_ON_SITE_CREATION", 109 | "value": "1" 110 | } 111 | ] 112 | } 113 | } 114 | }, 115 | { 116 | "type": "Microsoft.AppService/gateways", 117 | "apiVersion": "2015-03-01-preview", 118 | "name": "[parameters('gatewayName')]", 119 | "location": "[resourceGroup().location]", 120 | "tags": { 121 | "displayName": "Gateway" 122 | }, 123 | "resources": [ 124 | { 125 | "type": "providers/links", 126 | "apiVersion": "2015-01-01", 127 | "name": "Microsoft.Resources/gatewaySite", 128 | "dependsOn": [ 129 | "[resourceId('Microsoft.AppService/gateways',parameters('gatewayName'))]" 130 | ], 131 | "properties": { 132 | "targetId": "[resourceId('Microsoft.Web/sites',parameters('gatewayName'))]" 133 | } 134 | }, 135 | { 136 | "type": "tokens", 137 | "apiVersion": "2015-03-01-preview", 138 | "location": "[resourceGroup().location]", 139 | "name": "[parameters('apiAppName')]", 140 | "tags": { 141 | "displayName": "AuthenticationToken" 142 | }, 143 | "dependsOn": [ 144 | "[resourceId('Microsoft.AppService/gateways', parameters('gatewayName'))]" 145 | ] 146 | } 147 | 148 | ], 149 | "dependsOn": [ 150 | "[resourceId('Microsoft.Web/sites', parameters('gatewayName'))]" 151 | ], 152 | "properties": { 153 | "host": { 154 | "resourceName": "[parameters('gatewayName')]" 155 | } 156 | } 157 | }, 158 | { 159 | "type": "Microsoft.Web/sites", 160 | "apiVersion": "2015-04-01", 161 | 162 | "name": "[parameters('siteName')]", 163 | "location": "[resourceGroup().location]", 164 | "kind": "apiApp", 165 | "tags": { 166 | "displayName": "APIAppHost" 167 | }, 168 | "dependsOn": [ 169 | "[resourceId('Microsoft.AppService/gateways', parameters('gatewayName'))]" 170 | ], 171 | "resources": [ 172 | { 173 | "type": "siteextensions", 174 | "tags": { 175 | "displayName": "APIAppExtension" 176 | }, 177 | "apiVersion": "2015-04-01", 178 | "name": "[variables('$packageId')]", 179 | "dependsOn": [ 180 | 181 | "[resourceId('Microsoft.Web/sites', parameters('siteName'))]" 182 | ], 183 | "properties": { 184 | "type": "WebRoot", 185 | "feed_url": "[variables('$nugetFeed')]" 186 | } 187 | }, 188 | { 189 | "type": "providers/links", 190 | "apiVersion": "2015-01-01", 191 | "name": "Microsoft.Resources/apiApp", 192 | "dependsOn": [ 193 | "[resourceId('Microsoft.Web/sites', parameters('siteName'))]" 194 | ], 195 | "properties": { 196 | "targetId": "[resourceId('Microsoft.AppService/apiapps', parameters('apiAppName'))]" 197 | } 198 | }, 199 | 200 | { 201 | "apiVersion": "2015-04-01", 202 | "name": "web", 203 | "type": "sourcecontrols", 204 | "dependsOn": [ 205 | "[resourceId('Microsoft.Web/Sites', parameters('siteName'))]" 206 | ], 207 | "properties": { 208 | "RepoUrl": "[parameters('repoURL')]", 209 | "branch": "[parameters('branch')]", 210 | "IsManualIntegration": true 211 | } 212 | } 213 | 214 | 215 | ], 216 | "properties": { 217 | "name": "[parameters('siteName')]", 218 | "gatewaySiteName": "[parameters('gatewayName')]", 219 | "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('svcPlanName'))]", 220 | "siteConfig": { 221 | "appSettings": [ 222 | { 223 | "name": "EMA_MicroserviceId", 224 | "value": "[parameters('apiAppName')]" 225 | }, 226 | { 227 | "name": "EMA_Secret", 228 | "value": "[parameters('gatewayToAPIappSecret')]" 229 | }, 230 | { 231 | "name": "EMA_RuntimeUrl", 232 | "value": "[concat('https://', reference(resourceId('Microsoft.Web/sites', parameters('gatewayName'))).hostNames[0])]" 233 | }, 234 | { 235 | "name": "WEBSITE_START_SCM_ON_SITE_CREATION", 236 | "value": "1" 237 | } 238 | ] 239 | } 240 | } 241 | }, 242 | { 243 | "type": "Microsoft.AppService/apiapps", 244 | "apiVersion": "2015-03-01-preview", 245 | "name": "[parameters('apiAppName')]", 246 | "location": "[resourceGroup().location]", 247 | "tags": { 248 | "displayName": "APIApp" 249 | }, 250 | "resources": [ 251 | { 252 | "type": "providers/links", 253 | "apiVersion": "2015-01-01", 254 | "name": "Microsoft.Resources/apiAppSite", 255 | "dependsOn": [ 256 | "[resourceId('Microsoft.AppService/apiapps', parameters('apiAppName'))]" 257 | ], 258 | "properties": { 259 | 260 | "targetId": "[resourceId('Microsoft.Web/sites', parameters('siteName'))]" 261 | } 262 | } 263 | ], 264 | "dependsOn": [ 265 | 266 | "[resourceId('Microsoft.Web/sites/siteextensions', parameters('siteName'), 'Microsoft.ApiApp')]" 267 | ], 268 | "properties": { 269 | "package": { 270 | "id": "Microsoft.ApiApp" 271 | }, 272 | "accessLevel" : "PublicAnonymous", 273 | "host": { 274 | 275 | "resourceName": "[parameters('siteName')]" 276 | }, 277 | "gateway": { 278 | "resourceName": "[parameters('gatewayName')]" 279 | }, 280 | "dependencies": [ ] 281 | } 282 | } 283 | 284 | ] 285 | } 286 | -------------------------------------------------------------------------------- /CSScript/CSScript.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | 8 | 9 | 2.0 10 | {8DAA99D2-C633-44F4-AFFF-A2C571FCF5FF} 11 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 12 | Library 13 | Properties 14 | CSScript 15 | CSScript 16 | v4.5.2 17 | true 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | /subscriptions/80d4fe69-c95b-4dd2-a938-9250f1c8ab03/resourcegroups/Default-ApplicationInsights-CentralUS/providers/microsoft.insights/components/WebApplication2 26 | 27 | 28 | true 29 | full 30 | false 31 | bin\ 32 | DEBUG;TRACE 33 | prompt 34 | 4 35 | 36 | 37 | pdbonly 38 | true 39 | bin\ 40 | TRACE 41 | prompt 42 | 4 43 | 44 | 45 | 46 | ..\packages\Microsoft.Azure.AppService.ApiApps.Service.0.9.64\lib\net45\Microsoft.Azure.AppService.ApiApps.Service.dll 47 | True 48 | 49 | 50 | 51 | ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll 52 | True 53 | 54 | 55 | ..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll 56 | True 57 | 58 | 59 | ..\packages\Swashbuckle.Core.5.2.1\lib\net40\Swashbuckle.Core.dll 60 | True 61 | 62 | 63 | ..\packages\System.IdentityModel.Tokens.Jwt.4.0.2.206221351\lib\net45\System.IdentityModel.Tokens.Jwt.dll 64 | True 65 | 66 | 67 | 68 | ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll 69 | True 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll 82 | True 83 | 84 | 85 | ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll 86 | True 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | ..\packages\TRex.0.1.4.0\lib\net45\TRex.Metadata.dll 97 | True 98 | 99 | 100 | ..\packages\WebActivatorEx.2.0.6\lib\net40\WebActivatorEx.dll 101 | True 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | Global.asax 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | Web.config 123 | 124 | 125 | Web.config 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 10.0 138 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | True 148 | True 149 | 54281 150 | / 151 | http://localhost:54281/ 152 | False 153 | False 154 | 155 | 156 | False 157 | 158 | 159 | 160 | 161 | 162 | 163 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 164 | 165 | 166 | 173 | -------------------------------------------------------------------------------- /CSScript/App_Start/SwaggerConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web.Http; 2 | using WebActivatorEx; 3 | using CSScript; 4 | using Swashbuckle.Application; 5 | using TRex.Metadata; 6 | using Swashbuckle.Swagger; 7 | using System; 8 | using System.Web.Http.Description; 9 | 10 | [assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")] 11 | 12 | namespace CSScript 13 | { 14 | public class SwaggerConfig 15 | { 16 | public static void Register() 17 | { 18 | var thisAssembly = typeof(SwaggerConfig).Assembly; 19 | 20 | GlobalConfiguration.Configuration 21 | .EnableSwagger(c => 22 | { 23 | // By default, the service root url is inferred from the request used to access the docs. 24 | // However, there may be situations (e.g. proxy and load-balanced environments) where this does not 25 | // resolve correctly. You can workaround this by providing your own code to determine the root URL. 26 | // 27 | //c.RootUrl(req => GetRootUrlFromAppConfig()); 28 | 29 | // If schemes are not explicitly provided in a Swagger 2.0 document, then the scheme used to access 30 | // the docs is taken as the default. If your API supports multiple schemes and you want to be explicit 31 | // about them, you can use the "Schemes" option as shown below. 32 | // 33 | //c.Schemes(new[] { "http", "https" }); 34 | 35 | // Use "SingleApiVersion" to describe a single version API. Swagger 2.0 includes an "Info" object to 36 | // hold additional metadata for an API. Version and title are required but you can also provide 37 | // additional fields by chaining methods off SingleApiVersion. 38 | // 39 | c.SingleApiVersion("v1", "CSScript"); 40 | c.ReleaseTheTRex(); 41 | c.DocumentFilter(); 42 | 43 | // If your API has multiple versions, use "MultipleApiVersions" instead of "SingleApiVersion". 44 | // In this case, you must provide a lambda that tells Swashbuckle which actions should be 45 | // included in the docs for a given API version. Like "SingleApiVersion", each call to "Version" 46 | // returns an "Info" builder so you can provide additional metadata per API version. 47 | // 48 | //c.MultipleApiVersions( 49 | // (apiDesc, targetApiVersion) => ResolveVersionSupportByRouteConstraint(apiDesc, targetApiVersion), 50 | // (vc) => 51 | // { 52 | // vc.Version("v2", "Swashbuckle Dummy API V2"); 53 | // vc.Version("v1", "Swashbuckle Dummy API V1"); 54 | // }); 55 | 56 | // You can use "BasicAuth", "ApiKey" or "OAuth2" options to describe security schemes for the API. 57 | // See https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md for more details. 58 | // NOTE: These only define the schemes and need to be coupled with a corresponding "security" property 59 | // at the document or operation level to indicate which schemes are required for an operation. To do this, 60 | // you'll need to implement a custom IDocumentFilter and/or IOperationFilter to set these properties 61 | // according to your specific authorization implementation 62 | // 63 | //c.BasicAuth("basic") 64 | // .Description("Basic HTTP Authentication"); 65 | // 66 | //c.ApiKey("apiKey") 67 | // .Description("API Key Authentication") 68 | // .Name("apiKey") 69 | // .In("header"); 70 | // 71 | //c.OAuth2("oauth2") 72 | // .Description("OAuth2 Implicit Grant") 73 | // .Flow("implicit") 74 | // .AuthorizationUrl("http://petstore.swagger.wordnik.com/api/oauth/dialog") 75 | // //.TokenUrl("https://tempuri.org/token") 76 | // .Scopes(scopes => 77 | // { 78 | // scopes.Add("read", "Read access to protected resources"); 79 | // scopes.Add("write", "Write access to protected resources"); 80 | // }); 81 | 82 | // Set this flag to omit descriptions for any actions decorated with the Obsolete attribute 83 | //c.IgnoreObsoleteActions(); 84 | 85 | // Each operation be assigned one or more tags which are then used by consumers for various reasons. 86 | // For example, the swagger-ui groups operations according to the first tag of each operation. 87 | // By default, this will be controller name but you can use the "GroupActionsBy" option to 88 | // override with any value. 89 | // 90 | //c.GroupActionsBy(apiDesc => apiDesc.HttpMethod.ToString()); 91 | 92 | // You can also specify a custom sort order for groups (as defined by "GroupActionsBy") to dictate 93 | // the order in which operations are listed. For example, if the default grouping is in place 94 | // (controller name) and you specify a descending alphabetic sort order, then actions from a 95 | // ProductsController will be listed before those from a CustomersController. This is typically 96 | // used to customize the order of groupings in the swagger-ui. 97 | // 98 | //c.OrderActionGroupsBy(new DescendingAlphabeticComparer()); 99 | 100 | // Swashbuckle makes a best attempt at generating Swagger compliant context schemas for the various types 101 | // exposed in your API. However, there may be occasions when more control of the output is needed. 102 | // This is supported through the "MapType" and "SchemaFilter" options: 103 | // 104 | // Use the "MapType" option to override the Schema generation for a specific type. 105 | // It should be noted that the resulting Schema will be placed "inline" for any applicable Operations. 106 | // While Swagger 2.0 supports inline definitions for "all" Schema types, the swagger-ui tool does not. 107 | // It expects "complex" Schemas to be defined separately and referenced. For this reason, you should only 108 | // use the "MapType" option when the resulting Schema is a primitive or array type. If you need to alter a 109 | // complex Schema, use a Schema filter. 110 | // 111 | //c.MapType(() => new Schema { type = "integer", format = "int32" }); 112 | // 113 | // If you want to post-modify "complex" Schemas once they've been generated, across the board or for a 114 | // specific type, you can wire up one or more Schema filters. 115 | // 116 | //c.SchemaFilter(); 117 | 118 | // Set this flag to omit schema property descriptions for any type properties decorated with the 119 | // Obsolete attribute 120 | //c.IgnoreObsoleteProperties(); 121 | 122 | // In a Swagger 2.0 document, complex types are typically declared globally and referenced by unique 123 | // Schema Id. By default, Swashbuckle does NOT use the full type name in Schema Ids. In most cases, this 124 | // works well because it prevents the "implementation detail" of type namespaces from leaking into your 125 | // Swagger docs and UI. However, if you have multiple types in your API with the same class name, you'll 126 | // need to opt out of this behavior to avoid Schema Id conflicts. 127 | // 128 | //c.UseFullTypeNameInSchemaIds(); 129 | 130 | // In accordance with the built in JsonSerializer, Swashbuckle will, by default, describe enums as integers. 131 | // You can change the serializer behavior by configuring the StringToEnumConverter globally or for a given 132 | // enum type. Swashbuckle will honor this change out-of-the-box. However, if you use a different 133 | // approach to serialize enums as strings, you can also force Swashbuckle to describe them as strings. 134 | // 135 | //c.DescribeAllEnumsAsStrings(); 136 | 137 | // Similar to Schema filters, Swashbuckle also supports Operation and Document filters: 138 | // 139 | // Post-modify Operation descriptions once they've been generated by wiring up one or more 140 | // Operation filters. 141 | // 142 | //c.OperationFilter(); 143 | // 144 | // If you've defined an OAuth2 flow as described above, you could use a custom filter 145 | // to inspect some attribute on each action and infer which (if any) OAuth2 scopes are required 146 | // to execute the operation 147 | // 148 | //c.OperationFilter(); 149 | 150 | // Post-modify the entire Swagger document by wiring up one or more Document filters. 151 | // This gives full control to modify the final SwaggerDocument. You should have a good understanding of 152 | // the Swagger 2.0 spec. - https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md 153 | // before using this option. 154 | // 155 | //c.DocumentFilter(); 156 | 157 | // If you annonate Controllers and API Types with 158 | // Xml comments (http://msdn.microsoft.com/en-us/library/b2s063f7(v=vs.110).aspx), you can incorporate 159 | // those comments into the generated docs and UI. You can enable this by providing the path to one or 160 | // more Xml comment files. 161 | // 162 | //c.IncludeXmlComments(GetXmlCommentsPath()); 163 | 164 | // In contrast to WebApi, Swagger 2.0 does not include the query string component when mapping a URL 165 | // to an action. As a result, Swashbuckle will raise an exception if it encounters multiple actions 166 | // with the same path (sans query string) and HTTP method. You can workaround this by providing a 167 | // custom strategy to pick a winner or merge the descriptions for the purposes of the Swagger docs 168 | // 169 | //c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First()); 170 | }) 171 | .EnableSwaggerUi(c => 172 | { 173 | // Use the "InjectStylesheet" option to enrich the UI with one or more additional CSS stylesheets. 174 | // The file must be included in your project as an "Embedded Resource", and then the resource's 175 | // "Logical Name" is passed to the method as shown below. 176 | // 177 | //c.InjectStylesheet(containingAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testStyles1.css"); 178 | 179 | // Use the "InjectJavaScript" option to invoke one or more custom JavaScripts after the swagger-ui 180 | // has loaded. The file must be included in your project as an "Embedded Resource", and then the resource's 181 | // "Logical Name" is passed to the method as shown above. 182 | // 183 | //c.InjectJavaScript(thisAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testScript1.js"); 184 | 185 | // The swagger-ui renders boolean data types as a dropdown. By default, it provides "true" and "false" 186 | // strings as the possible choices. You can use this option to change these to something else, 187 | // for example 0 and 1. 188 | // 189 | //c.BooleanValues(new[] { "0", "1" }); 190 | 191 | // By default, swagger-ui will validate specs against swagger.io's online validator and display the result 192 | // in a badge at the bottom of the page. Use these options to set a different validator URL or to disable the 193 | // feature entirely. 194 | //c.SetValidatorUrl("http://localhost/validator"); 195 | //c.DisableValidator(); 196 | 197 | // Use this option to control how the Operation listing is displayed. 198 | // It can be set to "None" (default), "List" (shows operations for each resource), 199 | // or "Full" (fully expanded: shows operations and their details). 200 | // 201 | //c.DocExpansion(DocExpansion.List); 202 | 203 | // Use the CustomAsset option to provide your own version of assets used in the swagger-ui. 204 | // It's typically used to instruct Swashbuckle to return your version instead of the default 205 | // when a request is made for "index.html". As with all custom content, the file must be included 206 | // in your project as an "Embedded Resource", and then the resource's "Logical Name" is passed to 207 | // the method as shown below. 208 | // 209 | //c.CustomAsset("index", containingAssembly, "YourWebApiProject.SwaggerExtensions.index.html"); 210 | 211 | // If your API has multiple versions and you've applied the MultipleApiVersions setting 212 | // as described above, you can also enable a select box in the swagger-ui, that displays 213 | // a discovery URL for each version. This provides a convenient way for users to browse documentation 214 | // for different API versions. 215 | // 216 | //c.EnableDiscoveryUrlSelector(); 217 | 218 | // If your API supports the OAuth2 Implicit flow, and you've described it correctly, according to 219 | // the Swagger 2.0 specification, you can enable UI support as shown below. 220 | // 221 | //c.EnableOAuth2Support("test-client-id", "test-realm", "Swagger UI"); 222 | }); 223 | } 224 | internal class CustomDocumentFilter : IDocumentFilter 225 | { 226 | public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer) 227 | { 228 | swaggerDoc.definitions["Object"].vendorExtensions["additionalProperties"] = true; 229 | 230 | } 231 | } 232 | } 233 | } --------------------------------------------------------------------------------