ServiceStack Scripts

The ServiceStack Scripts provide integration with ServiceStack features that are already pre-registered in ServiceStack's SharpPagesFeature which are implemented in ServiceStackScripts.

See Info Scripts for accessing the currently authenticated user.

sendToGateway

sendToGateway lets you easily call any ServiceStack Service available through its Service Gateway which allows the same API to transparently call an In-Process or Remote Service.

The example below calls this QueryCustomers AutoQuery RDBMS Service, its entire implementation is below:

public class QueryCustomers : QueryDb<Customer>
{
    public string CustomerId { get; set; }
    public string CompanyNameContains { get; set; }
    public string[] CountryIn { get; set; }
}

execService

execService is a readable alternative to calling a service via sendToGateway without arguments, e.g:

AUTH = {{ 'Authenticate' |> execService({ ifErrorReturn: "null" }) |> json }};

AUTH = {{ {} |> sendToGateway('Authenticate', { ifErrorReturn: "null" }) |> json }};

publishToGateway

publishToGateway is for sending OneWay requests with side-effects to IReturnVoid Services, e.g:

{{ { id, firstName, lastName, age } |> ensureAllArgsNotNull |> publishToGateway('StoreContact') }}
{{ { id }  |> sendToGateway('GetContact') |> to => contact }}
{{ contact |> selectPartial: contact-details }}

publishMessage

publishMessage is used for sending Request DTOs to be processed by the configured MQ Server:

{{ 'ProcessOrder'.publishMessage({ orderId }) }}

sendToAutoQuery

The sendToAutoQuery method makes requests directly against the AutoQuery API. The ServiceStackScripts only supports calling AutoQuery Data Services as it's implementation is contained within the ServiceStack NuGet package.

AutoQuery Data is an open querying abstraction that supports multiple pluggable back-ends that enables rich querying of In Memory collections, results from executed ServiceStack Services as well as AWS Dynamo DB data stores. It also maintains the equivalent external API and wire-format as AutoQuery RDBMS Services which is how AutoQuery Viewer is able to transparently support building custom queries for any AutoQuery Service.

GitHub AutoQuery Data Example

For this example we'll register a ServiceSource which will call the GetGithubRepos Service implementation for any AutoQuery Data DTOs that query GithubRepo data sources:

Plugins.Add(new AutoQueryDataFeature { MaxLimit = 100 }
    .AddDataSource(ctx => ctx.ServiceSource<GithubRepo>(ctx.Dto.ConvertTo<GetGithubRepos>(), 
        HostContext.Cache, TimeSpan.FromMinutes(10)))
);

This registration also specifies to cache the response of the GetGithubRepos Service in the registered Caching Provider and operate on the cached data set for up to 10 minutes to mitigate GitHub API's rate-limiting. All that's remaining is to create the QueryGitHubRepos Service by defining the Request DTO below and implement the backing GetGithubRepos Service it calls which combines a number of GitHub API calls to fetch all Repo's for a GitHub User or Organization:

public class QueryGitHubRepos : QueryDatao<GithubRepo>
{
    public string UserName { get; set; }
}

public class GetGithubRepos : IReturn<List<GithubRepo>>
{
    public string UserName { get; set; }
}

public class AutoDataQueryServices : Service
{
    public object Any(GetGithubRepos request)
    {
        var map = new Dictionary<int, GithubRepo>();
        GetUserRepos(request.UserName).Each(x => map[x.Id] = x);
        GetOrgRepos(request.UserName).Each(x => map[x.Id] = x);
        GetUserOrgs(request.UserName).Each(org =>
            GetOrgRepos(org.Login)
                .Each(repo => map[repo.Id] = repo));

        return map.Values.ToList();
    }

    public List<GithubOrg> GetUserOrgs(string githubUsername) => 
        GetJson<List<GithubOrg>>($"users/{githubUsername}/orgs");
    public List<GithubRepo> GetUserRepos(string githubUsername) => 
        GetJson<List<GithubRepo>>($"users/{githubUsername}/repos");
    public List<GithubRepo> GetOrgRepos(string githubOrgName) => 
        GetJson<List<GithubRepo>>($"orgs/{githubOrgName}/repos");

    public T GetJson<T>(string route) 
    {
        try {
            return "https://api.github.com".CombineWith(route)
                .GetJsonFromUrl(requestFilter: req => req.UserAgent = nameof(AutoDataQueryServices))
                .FromJson<T>();
        } catch(Exception) { return default(T); }
    }
}

That's all that's required to be able to query GitHub's User and Organization APIs, since they're just normal ServiceStack Services we could've used sendToAutoQuery to call QueryGitHubRepos but it would be limited to only being able to call properties explicitly defined on the Request DTO, whereas sendToAutoQuery executes against the IAutoQueryData API which enables access to all Implicit Conventions and other Querying related functionality:

AutoQuery RDBMS

AutoQuery RDBMS is implemented in the ServiceStack.Server NuGet package which you'll need to install along with the OrmLite NuGet package for your RDBMS which can then be registered in the IOC with:

container.AddSingleton<IDbConnectionFactory>(() => 
    new OrmLiteConnectionFactory(connectionString, SqlServer2012Dialect.Provider));

AutoQuery can then be enabled by registering the AutoQueryFeature plugin:

Plugins.Add(new AutoQueryFeature { MaxLimit = 100 });

Which will let you start developing AutoQuery Services. To then let your Scripts call AutoQuery Services directly, register the AutoQueryScripts:

Plugins.Add(new SharpPagesFeature {
    ScriptMethods = { new AutoQueryScripts() },
});

sendToAutoQuery

As they share the same semantics and wire-format, you can use the same sendToAutoQuery method name to call either AutoQuery Data or AutoQuery RDBMS Services which automatically gets routed to the appropriate implementation. This also means that you can replace your implementation to from AutoQuery Data to RDBMS and vice-versa behind the scenes and your scripts will continue to work untouched.

For this example we'll re-use the same QueryCustomers AutoQuery Implementation that the sendToGateway uses:

public class QueryCustomers : QueryDb<Customer>
{
    public string CustomerId { get; set; }
    public string CompanyNameContains { get; set; }
    public string[] CountryIn { get; set; }
}

But instead of being limited by explicit properties on the Request DTO sendToAutoQuery extends the queryability of AutoQuery Services to enable querying all implicit conventions as well:

See the Scripts API Reference for the full list of ServiceStack Scripts available.

Info Scripts

The debug info methods provide an easy to inspect the state of a remote ServiceStack Instance by making a number of metadata objects and APIs available to query. The InfoScripts are pre-registered in ServiceStack's SharpPagesFeature. You can make them available in a ScriptContext with:

var context = new SharpPagesFeature 
{
    ScriptMethods = { new InfoScripts() }
}.Init();
Method Name API Mapping
Environment APIs
envVariable Environment.GetEnvironmentVariable(variable)
envExpandVariables Environment.ExpandEnvironmentVariables(name)
envProcessorCount Environment.ProcessorCount
envTickCount Environment.TickCount
envServerUserAgent Env.ServerUserAgent
envServiceStackVersion Env.ServiceStackVersion
envIsWindows (isWin) Env.IsWindows (net45) / IsOSPlatform(Windows) (netcore)
envIsLinux Env.IsLinux (net45) / IsOSPlatform(Linux) (netcore)
envIsOSX Env.IsOSX (net45) / IsOSPlatform(OSX) (netcore)
networkIpv4Addresses GetAllNetworkInterfaceIpv4Addresses()
networkIpv6Addresses GetAllNetworkInterfaceIpv6Addresses()
ServiceStack User APIs
userSession IRequest.GetSession()
userSessionId IRequest.GetSessionId()
userAuthId IRequest.GetSession().UserAuthId
userAuthName IRequest.GetSession().UserAuthName
userSession IRequest.GetSession()
userPermanentSessionId IRequest.GetPermanentSessionId()
userSessionOptions IRequest.GetSessionOptions()
userHasRole IAuthSession.HasRole(role)
userHasPermission IAuthSession.HasPermission(permission)
ServiceStack Metadata APIs
metaAllDtos Metadata.GetAllDtos()
metaAllDtoNames Metadata.GetOperationDtos(x => x.Name)
metaAllOperations Metadata.Operations
metaAllOperationNames Metadata.GetAllOperationNames()
metaAllOperationTypes Metadata.GetAllOperationTypes()
metaOperation Metadata.GetOperation(name)

/metadata/debug

Debug Inspector

Metadata Debug Inspectors Screenshot

The Debug Inspector is a Service in SharpPagesFeature that's pre-registered in DebugMode. The Service can also be available when not in DebugMode by enabling it with:

Plugins.Add(new SharpPagesFeature { 
    MetadataDebugAdminRole = RoleNames.AllowAnon
})

This registers the Service but limits it to Users with the Admin role, alternatively you configure an Admin Secret Key:

SetConfig(new HostConfig { AdminAuthSecret = "secret" })

Which will let you access it by appending the authsecret to the querystring: /metadata/debug?authsecret=secret

Alternatively if preferred you can make the Debug Inspector Service available to all users with:

Plugins.Add(new SharpPagesFeature { 
    MetadataDebugAdminRole = RoleNames.AllowAnyUser,  // Allow Authenticated Users
    MetadataDebugAdminRole = RoleNames.AllowAnon,     // Allow anyone
})

Which is the configuration used in this .NET Core App which makes the Debug Inspector Service accessible to everyone:

/metadata/debug

Debug Inspectors are executed in a new ScriptContext instance pre-configured with the above InfoScripts and a copy of any context arguments in SharpPagesFeature which is the only thing it can access from the plugin.

In addition to SharpPagesFeature arguments, they're also populated with the following additional arguments:

request The current IHttpRequest
appHost The ServiceStack AppHost Instance
appConfig ServiceStack's AppHost Configuration
appVirtualFilesPath The Read/Write IVirtualFiles (aka ContentRootPath)
appVirtualFileSourcesPath Multiple read-only Virtual File Sources (aka WebRootPath)
meta ServiceStack Metadata Services Object

See the Scripts API Reference for the full list of Info scripts available.

made with by ServiceStack