Phillip Powers - 246 - Aug 6, 2014

I’m trying to use the System.Web.Optimization classes (as is demonstrated at http://www.gregpakes.co.uk/post/using-mvc-optimization-framework-with-servicestackrazor) within a ServiceStack Razor page, and I’m getting a “null HttpContext” exception from the @Styles.Render(…) call that embedded in my .cshtml file.

I think a similar issue has been noted on StackOverflow (without any resolution):  http://stackoverflow.com/questions/22595703/servicestack-razor-view-httpcontext-current-is-null

Is this a known issue?  Is the current HttpContext always null in the ServiceStack Razor implementation (and therefore System.Web.Optimization is incompatible)? Maybe it’s some sort of configuration that I’m missing?

Thanks.

HttpContext isn’t available in Content Pages but is available in View Pages, (i.e. in /Views and called with the response of a Service). 
If you need to, you can use [FallbackRoute] for adding a fallback route for default.cshtml pages: 
https://github.com/ServiceStack/ServiceStack/wiki/Routing#fallback-route

Phillip Powers:

Cool, thanks.  A related question, then.

I’m serving up an Angular app, and currently in the Fallback service I’m doing “return HttpResult.Redirect(”/app/")", which ends up causing /app/default.cshtml to be rendered.

In the Fallback service, I know I can do a “new HttpResult() { View = … }” to return a Razor page, but it seems that it’s not working because my default.cshtml file is in /app/ and not in /Views/.  

Is there any way to return the HttpResult using /app/default.cshtml as the layout file? I tried just moving my default.cshtml file to /Views/ but that had ramifications wrt relative paths that I’d really rather not have to deal with. 

The view or the layout file? The Layout is normally called _Layout.cshtml and its default location in /Views/Shared/. View Pages do need to be in /Views.

But why can’t you just let Fallback Service fall through to call /app/ instead of redirecting to it?

Phillip Powers:

It’s really more like a Layout file. All of the actual dynamic views are client-side Angular views and are in /app/views/* (just static HTML files as far as the server is concerned). 

It looks like if I don’t handle the Fallback (but still have a catch-all FallbackRoute DTO) then I get back into my original issue, where the HttpContext is not available.  If I just return the Fallback DTO (or null, etc), then it doesn’t end up calling /app/. Is there some other way to “fall through” the Fallback service?

Basically I’m just trying to take the outer Angular layout file (default.cshtml) and put it through Razor so I can do server-side CSS/JS bundling with it, etc. It looks like it’ll work if I move the file from /app/default.cshtml and put it in /Views, but then I’ll have to go through and change a bunch of relative paths in other spots in the Angular app.  Not a dealbreaker, just wanted to make sure there’s not an alternative first (ie, forcing a render of /app/default.cshtml from inside the Fallback service).

Thanks again.

Yeah /Views is the cleaner option, but you could also return the rendered page as HTML in your service, e.g:

[FallbackRoute("/{Path*}")]
public class Fallback
{
    public string Path { get; set; }
}

public class FallbackService : Service
{
    public object Any(Fallback request)
    {
        var feature = HostContext.GetPlugin<RazorFormat>();

        var page = feature.GetContentPage("/default.cshtml");

        var html = feature.RenderToHtml(page);

        return html;
    }
}

You could also use a better optimization solution that doesn’t rely on HttpContext.Current like GruntJS/GulpJS or Bundler :) 

Phillip Powers:

Perfect, thanks.