1

In MVC, there's a ViewSwitcher, and you can add _Layout, _Layout.mobile; MyView and optional MyView.mobile

What's the best way to accomplish this in ServiceStack razor view? Thanks

Whoever
  • 1,295
  • 1
  • 14
  • 21

1 Answers1

1

ServiceStack doesn't implicitly switch layouts at runtime, instead the preferred layout needs to be explicitly set. ServiceStack's RazorRockstars Demo website explains how to dynamically switch views, i.e:

Change Views and Layout templates at runtime

The above convention is overrideable where you can change both what View and Layout Template is used at runtime by returning your Response inside a decorated HttpResult:

return new HttpResult(dto) {
    View = {viewName},
    Template = {layoutName},
};

This is useful whenever you want to display the same page in specialized Mobile and Print Preview website templates. You can also let the client change what View and Template gets used by attributing your service with the ClientCanSwapTemplates Request Filter Attribute:

[ClientCanSwapTemplates]
public class RockstarsService : RestServiceBase { ... }

Which itself is a very simple implementation that also shows you can you can swap the View or Template used inside a Request Filter:

public class ClientCanSwapTemplatesAttribute : RequestFilterAttribute
{
    public override void Execute(IHttpRequest req, IHttpResponse res, object requestDto)
    {
        req.Items["View"] = req.GetParam("View");
        req.Items["Template"] = req.GetParam("Template");
    }
}

This attribute allows the client to change what View gets used with the View and Template QueryString or FormData Request Params. A live example of this feature is used to change the /rockstars page:

Changing Layout used from inside a view

You can even change the layout used by setting the Layout property from inside a Razor View, e.g:

@inherits ViewPage<Response>
@{
    Layout = IsMobileRequest(base.Request) ? "_LayoutMobile" : "_Layout";
}
mythz
  • 141,670
  • 29
  • 246
  • 390
  • Thanks for the update. Just got started on this, so far I only have 3 projects Web, Service and Modal referencing each other, with a default _Layout and Hello.cshtml. How do I do return new HttpResult(dto) {}? Do I have to do this with every request/response? Or can it be done on a base class? Thanks – Whoever Oct 07 '13 at 15:22
  • @Whoever You can use a [Global](https://github.com/ServiceStack/ServiceStack/wiki/Request-and-response-filters) or custom [Response Filter Attribute](https://github.com/ServiceStack/ServiceStack/wiki/Filter-attributes) which lets you inspect the Response DTO and set the `req.Items["Template"]` as done in `[ClientCanSwapTemplates]`. Otherwise for adding *base-class-like* functionality you can use a [Custom Service Runner](https://github.com/ServiceStack/ServiceStack/wiki/Customize-HTTP-Responses#using-a-custom-servicerunner) – mythz Oct 07 '13 at 15:45
  • Thanks, seems the possibilities are endless. I'll get back to documentation for now. Or maybe give the javascript approach a try. Speaking of Filter attribute, I do have some questions about accessing Request and Response at the same time, and batching requests in a single round trip, etc. I'll do some searching first and maybe start a separate thread if necessary. Incredible job! Almost too good to be true ^_^ – Whoever Oct 07 '13 at 16:08
  • I got the custom response filter working and it's really amazing! Two follow up questions, in case you are still follow this: Where do Request/ResponseFilterAttribute reside? I setup 3 projects, Modal, Service and Web(Host/View). In Modal and Service, I only added ServiceStack.Common. Even though ResponseFilterAttribute is in ServiceInterface namespace, it's still not available. Unless I add the entire ServiceStack. Is there a way to avoid this? – Whoever Oct 08 '13 at 12:48
  • From within the filter (in Modal/Service), is there a way to check if aView.mobile.cshtml actually exist before setting it (and hopefully without adding too much overhead by doing so)? Even though I can avoid the error by selectively adding the attribute, it could be error-prone if the project grown beyond Hello. Thanks. – Whoever Oct 08 '13 at 12:48