Skip to content

Instantly share code, notes, and snippets.

@gistlyn
Last active February 10, 2023 06:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gistlyn/6e0677825059822fbaffec123403bf38 to your computer and use it in GitHub Desktop.
Save gistlyn/6e0677825059822fbaffec123403bf38 to your computer and use it in GitHub Desktop.
VB.NET Empty .NET 6 ServiceStack App
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TypeScriptToolsVersion>latest</TypeScriptToolsVersion>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ServiceStack" Version="6.*" />
</ItemGroup>
</Project>
{
"scripts": {
"dtos": "x mjs"
}
}
Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Linq
Imports System.Threading.Tasks
Imports Microsoft.AspNetCore
Imports Microsoft.AspNetCore.Hosting
Imports Microsoft.Extensions.Configuration
Imports Microsoft.Extensions.Logging
Imports ServiceStack
Module Program
Sub Main(args As String())
BuildWebHost(args).Run()
End Sub
Function BuildWebHost(args As String()) As IWebHost
Return WebHost.CreateDefaultBuilder(args).UseModularStartup(Of Startup)().Build()
End Function
End Module
{
"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/"
}
}
}
Imports System
Imports ServiceStack
Imports MyApp.ServiceModel
Namespace Global.MyApp.ServiceInterface
Public Class MyServices
Inherits Service
public Function Any(request AS Hello) AS Object
Return new HelloResponse With { .Result = $"Hello, {request.Name}!" }
End Function
End Class
End Namespace
Imports ServiceStack
Namespace Global.MyApp.ServiceModel
<Route("/hello")>
<Route("/hello/{Name}")>
Public Partial Class Hello
Implements IReturn(Of HelloResponse)
Public Overridable Property Name As String
End Class
Public Partial Class HelloResponse
Public Overridable Property Result As String
End Class
End Namespace
Imports System.Collections.Generic
Imports System.Linq
Imports Microsoft.AspNetCore.Builder
Imports Microsoft.AspNetCore.Hosting
Imports Microsoft.Extensions.Hosting
Imports Microsoft.Extensions.DependencyInjection
Imports Microsoft.Extensions.Configuration
Imports Funq
Imports ServiceStack
Imports ServiceStack.Configuration
Imports MyApp.ServiceInterface
Imports ServiceStack.Script
Imports ServiceStack.Web
Imports System
Imports ServiceStack.Text
Imports ServiceStack.Logging
Namespace Global.MyApp
Class Startup
Inherits 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
Overloads Sub ConfigureServices(Services as IServiceCollection)
End Sub
Overloads Sub Configure(app AS IApplicationBuilder, env AS IWebHostEnvironment)
If env.IsDevelopment()
app.UseDeveloperExceptionPage()
End If
app.UseServiceStack(new AppHost With {
.AppSettings = new NetCoreAppSettings(Configuration)
})
End Sub
End Class
Class AppHost
Inherits AppHostBase
Public Sub New()
MyBase.New("My App", GetType(MyServices).Assembly)
End Sub
' Configure your AppHost with the necessary configuration and dependencies your App needs
Public Overrides Sub Configure(container AS Container)
SetConfig(new HostConfig With {
.UseSameSiteCookies = true,
.DebugMode = HostingEnvironment.IsDevelopment()
})
End Sub
End Class
End Namespace
<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
&lt;script type="importmap"&gt;
{
"imports": {
"@servicestack/client":"https://unpkg.com/@servicestack/client@2/dist/servicestack-client.mjs"
}
}
&lt;/script&gt;
```
This lets us reference the **@servicestack/client** package name in our source code instead of its physical location:
```html
&lt;input type="text" id="txtName"&gt;
&lt;div id="result"&gt;&lt;/div&gt;
```
```html
&lt;script type="module"&gt;
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
}
})
&lt;/script&gt;
```
### 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>
/* 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