servicestackservicestack-razor

How to use ServiceStack Templates to support dynamic results based on request type?


With ServiceStack's Razor Story we have a variety of ways of selecting which Razor View we want to use to render a page. Even better, and critical in my case, is we can pass in a Content-Type header (or query string parameter, or even page "suffix") as well to return the raw model in a variety of formats.

Is there any way to use ServiceStack Templates (now known as SharpScript) to do the same thing? I follow the example here but I just get back the standard HTML format response. It doesn't use my template, no matter how named.

Following the example in the v5.5 Release Notes:

[Route("/hello/{Name}")]
public class Hello : IReturn<HelloResponse>
{
    public string Name { get; set; }
}
public class HelloResponse
{
    public string Result { get; set; }
}

public class HelloService : Service
{
    public object Any(Hello request) => new HelloResponse { Result = $"Hello, {request.Name}!" };
}

Going to /hello/World?format=html provides me the standard HTML report, not my template. I followed another example to force it to use the template ....

public object Any(Hello request) =>
        new PageResult(Request.GetPage("examples/hello")) {
            Model = request.Name
        };

... and it ALWAYS returns my template, even if I specify /hello/World?format=json.

Is there any way to have Razor-like view selection for ServiceStack + ScriptSharp pages, but also support different response formats?


Solution

  • It's hard to answer a vague question like this without details of a specific scenario you want to achieve that's not working.

    You can return Sharp Pages in a number of ways:

    Select which view to render inside your Service by returning your Response DTO inside a custom HttpResult:

    public object Any(MyRequest request)
    {
        ...
        return new HttpResult(response)
        {
            View = "CustomPage",  // -> /Views/CustomPage.html
            //Template = "_custom-layout",
        };
    }
    

    Add the [ClientCanSwapTemplates] Request Filter attribute to let the View and Template by modified on the QueryString, e.g: ?View=CustomPage&Template=_custom-layout

    [ClientCanSwapTemplates]
    public object Any(MyRequest request) => ...
    

    Choosing which page you want to render inside your Model View Controller Service by returning a custom PageResult:

    public class CustomerServices : Service
    {
        public object Any(ViewCustomer request) =>
            new PageResult(Request.GetPage("examples/customer")) {
                Model = TemplateQueryData.GetCustomer(request.Id)
            };
    }
    

    Note: That the SharpPagesFeature resolves pages using your cascading AppHost.VirtualFileSources. In .NET Core it's configured to use its WebRoot, e.g /wwwroot.

    For Sharp Pages to return its Response in Multiple Content Types:

    as well to return the raw model in a variety of formats.

    You need to use a Sharp APIs which return a value, e.g. /hello/_name/index.html:

    {{ { result: `Hello, ${name}!` } | return }}