Last active
November 22, 2023 03:35
-
-
Save gistlyn/3008acbe218fbcfb8278853825cc7ea3 to your computer and use it in GitHub Desktop.
F# Empty .NET 6 ServiceStack App
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Project Sdk="Microsoft.NET.Sdk.Web"> | |
<PropertyGroup> | |
<TargetFramework>net8.0</TargetFramework> | |
<TypeScriptToolsVersion>latest</TypeScriptToolsVersion> | |
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked> | |
</PropertyGroup> | |
<ItemGroup> | |
<PackageReference Include="ServiceStack" Version="8.*" /> | |
</ItemGroup> | |
<ItemGroup> | |
<Compile Include="ServiceModel\Hello.fs" /> | |
<Compile Include="ServiceInterface\MyServices.fs" /> | |
<Compile Include="Startup.fs" /> | |
<Compile Include="Program.fs" /> | |
</ItemGroup> | |
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"scripts": { | |
"dtos": "x mjs" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace fsharp | |
open System | |
open System.Collections.Generic | |
open System.IO | |
open System.Linq | |
open System.Threading.Tasks | |
open Microsoft.AspNetCore | |
open Microsoft.AspNetCore.Hosting | |
open Microsoft.Extensions.Configuration | |
open Microsoft.Extensions.Hosting | |
open Microsoft.Extensions.Logging | |
open ServiceStack | |
module Program = | |
let exitCode = 0 | |
let CreateHostBuilder args = | |
Host.CreateDefaultBuilder(args) | |
.ConfigureWebHostDefaults(fun webBuilder -> | |
ModularExtensions.UseModularStartup<Startup>(webBuilder) | |
|> ignore) | |
[<EntryPoint>] | |
let main args = | |
CreateHostBuilder(args).Build().Run() | |
exitCode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"iisSettings": { | |
"windowsAuthentication": false, | |
"anonymousAuthentication": true, | |
"iisExpress": { | |
"applicationUrl": "https://localhost:5001/", | |
"sslPort": 0 | |
} | |
}, | |
"profiles": { | |
"IIS Express": { | |
"commandName": "IISExpress", | |
"launchBrowser": true, | |
"environmentVariables": { | |
"ASPNETCORE_ENVIRONMENT": "Development" | |
} | |
}, | |
"MyApp": { | |
"commandName": "Project", | |
"launchBrowser": true, | |
"environmentVariables": { | |
"ASPNETCORE_ENVIRONMENT": "Development" | |
}, | |
"applicationUrl": "https://localhost:5001/" | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace MyApp.ServiceInterface | |
open System | |
open ServiceStack | |
open MyApp.ServiceModel | |
type HelloService() = | |
inherit Service() | |
member this.Any (req:Hello) = | |
HelloResponse(Result = "Hello, " + req.Name) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace MyApp.ServiceModel | |
open System | |
open System.Collections | |
open System.Collections.Generic | |
open System.Runtime.Serialization | |
open ServiceStack | |
open ServiceStack.DataAnnotations | |
[<AllowNullLiteral>] | |
type HelloResponse() = | |
member val Result:String = null with get,set | |
[<Route("/hello")>] | |
[<Route("/hello/{Name}")>] | |
[<AllowNullLiteral>] | |
type Hello() = | |
interface IReturn<HelloResponse> | |
member val Name:String = null with get,set |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace fsharp | |
open System | |
open Microsoft.AspNetCore.Builder | |
open Microsoft.AspNetCore.Hosting | |
open Microsoft.AspNetCore.Http | |
open Microsoft.Extensions.DependencyInjection | |
open Microsoft.Extensions.Hosting | |
open Microsoft.Extensions.Configuration | |
open Funq | |
open ServiceStack | |
open ServiceStack.Configuration | |
open ServiceStack.Text | |
open MyApp.ServiceInterface | |
type AppHost = | |
inherit AppHostBase | |
new() = { inherit AppHostBase("My App", typeof<HelloService>.Assembly) } | |
override this.Configure(container: Container): unit = | |
base.SetConfig | |
(HostConfig(UseSameSiteCookies = Nullable true, DebugMode = base.HostingEnvironment.IsDevelopment())) | |
|> ignore | |
type Startup(Configuration: IConfiguration) = | |
inherit ModularStartup() | |
// This method gets called by the runtime. Use this method to add services to the container. | |
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 | |
member this.ConfigureServices(services: IServiceCollection) = () | |
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. | |
member this.Configure(app: IApplicationBuilder, env: IWebHostEnvironment) = | |
if env.IsDevelopment() | |
then app.UseDeveloperExceptionPage() |> ignore | |
app.UseServiceStack(new AppHost(AppSettings = NetCoreAppSettings(Configuration))) | |
|> ignore |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<title>My App</title> | |
<style> | |
body { padding: 1em 1em 5em 1em; } | |
body, input[type=text] { font: 20px/28px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif } | |
input { padding:.25em .5em; margin-right:.5em; } | |
a { color:#007bff; text-decoration:none } | |
a:hover { text-decoration:underline } | |
#result { display:inline-block; color:#28a745; font-size:28px } | |
pre { border-radius:10px; overflow:hidden } | |
h2, h3, strong { font-weight:500 } | |
</style> | |
<link rel="stylesheet" href="https://unpkg.com/@highlightjs/cdn-assets@11.7.0/styles/atom-one-dark.min.css"> | |
<script async src="https://ga.jspm.io/npm:es-module-shims@1.6.3/dist/es-module-shims.js"></script><!--safari polyfill--> | |
<script type="importmap"> | |
{ | |
"imports": { | |
"@servicestack/client": "https://unpkg.com/@servicestack/client@2/dist/servicestack-client.min.mjs" | |
} | |
} | |
</script> | |
</head> | |
<body> | |
<h2><a href="/ui/Hello">Hello</a> API</h2> | |
<input type="text" id="txtName"> | |
<div id="result"></div> | |
<script type="module"> | |
import { JsonApiClient, $1, on } from '@servicestack/client' | |
import { Hello } from '/types/mjs' | |
const client = JsonApiClient.create() | |
on('#txtName', { | |
/** @param {Event} el */ | |
async keyup(el) { | |
const api = await client.api(new Hello({ name:el.target.value })) | |
$1('#result').innerHTML = api.response.result | |
} | |
}) | |
$1('#txtName').value = 'World' | |
$1('#txtName').dispatchEvent(new KeyboardEvent('keyup')) | |
</script> | |
<div id="content" style="max-width:105ch"></div> | |
<template id="docs"> | |
## View in API Explorer | |
- [Call API](/ui/Hello) | |
- [View API Details](/ui/Hello?tab=details) | |
- [Browse API source code in different langauges](/ui/Hello?tab=code) | |
### Using JsonServiceClient in Web Pages | |
Easiest way to call APIs is to use [@servicestack/client](https://docs.servicestack.net/javascript-client) with | |
the built-in [/types/mjs](/types/mjs) which returns your APIs in annotated typed ES6 class DTOs where it can be | |
referenced directly from a [JavaScript Module](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules). | |
We recommend using an [importmap](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) | |
to specify where to load **@servicestack/client** from, e.g: | |
```html | |
<script type="importmap"> | |
{ | |
"imports": { | |
"@servicestack/client":"https://unpkg.com/@servicestack/client@2/dist/servicestack-client.mjs" | |
} | |
} | |
</script> | |
``` | |
This lets us reference the **@servicestack/client** package name in our source code instead of its physical location: | |
```html | |
<input type="text" id="txtName"> | |
<div id="result"></div> | |
``` | |
```html | |
<script type="module"> | |
import { JsonApiClient, $1, on } from '@servicestack/client' | |
import { Hello } from '/types/mjs' | |
const client = JsonApiClient.create() | |
on('#txtName', { | |
async keyup(el) { | |
const api = await client.api(new Hello({ name:el.target.value })) | |
$1('#result').innerHTML = api.response.result | |
} | |
}) | |
</script> | |
``` | |
### Enable static analysis and intelli-sense | |
For better IDE intelli-sense during development, save the annotated Typed DTOs to disk with the [x dotnet tool](https://docs.servicestack.net/dotnet-tool): | |
```bash | |
$ x mjs | |
``` | |
Then reference it instead to enable IDE static analysis when calling Typed APIs from JavaScript: | |
```js | |
import { Hello } from '/js/dtos.mjs' | |
client.api(new Hello({ name })) | |
``` | |
To also enable static analysis for **@servicestack/client**, install the dependency-free library as a dev dependency: | |
```bash | |
$ npm install -D @servicestack/client | |
``` | |
Where only its TypeScript definitions are used by the IDE during development to enable its type-checking and intelli-sense. | |
</template> | |
<script src="https://unpkg.com/@highlightjs/cdn-assets@11.7.0/highlight.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> | |
<script> | |
function decode(html) { | |
const txt = document.createElement("textarea") | |
txt.innerHTML = html | |
return txt.value | |
} | |
document.querySelector('#content').innerHTML = marked.parse(decode(document.querySelector('#docs').innerHTML)) | |
hljs.highlightAll() | |
</script> | |
</div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Options: | |
Date: 2023-02-09 18:15:17 | |
Version: 6.60 | |
Tip: To override a DTO option, remove "//" prefix before updating | |
BaseUrl: https://localhost:5001 | |
//AddServiceStackTypes: True | |
//AddDocAnnotations: True | |
//AddDescriptionAsComments: True | |
//IncludeTypes: | |
//ExcludeTypes: | |
//DefaultImports: | |
*/ | |
"use strict"; | |
export class HelloResponse { | |
/** @param {{result?:string}} [init] */ | |
constructor(init) { Object.assign(this, init) } | |
/** @type {?string} */ | |
result; | |
} | |
export class Hello { | |
/** @param {{name?:string}} [init] */ | |
constructor(init) { Object.assign(this, init) } | |
/** @type {?string} */ | |
name; | |
getTypeName() { return 'Hello' } | |
getMethod() { return 'POST' } | |
createResponse() { return new HelloResponse() } | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment