Permalink
Browse files

Also get ServiceStack.Razor to server embedded resource razor page te…

…mplates
  • Loading branch information...
1 parent 1abd03d commit 55598cec11cb480c78ade96f72b22778dc39a922 @mythz mythz committed Jul 22, 2012
@@ -3,7 +3,6 @@
using System.Configuration;
using System.IO;
using System.Linq;
-using System.Xml;
using System.Xml.Linq;
using ServiceStack.Common;
using ServiceStack.Configuration;
@@ -66,8 +65,11 @@ public static RazorFormat Instance
public HashSet<string> TemplateNamespaces { get; set; }
+ public bool WatchForModifiedPages { get; set; }
+
public RazorFormat()
{
+ this.WatchForModifiedPages = true;
this.FindRazorPagesFn = FindRazorPages;
this.ReplaceTokens = new Dictionary<string, string>();
this.TemplateNamespaces = new HashSet<string> {
@@ -83,16 +85,20 @@ public RazorFormat()
private void RegisterNamespacesInConfig()
{
//Infer from <system.web.webPages.razor> - what VS.NET's intell-sense uses
- var xml = "~/web.config".MapServerPath().ReadAllText();
- var doc = XElement.Parse(xml);
- doc.AnyElement("system.web.webPages.razor")
- .AnyElement("pages")
- .AnyElement("namespaces")
- .AllElements("add").ToList()
- .ForEach(x => TemplateNamespaces.Add(x.AnyAttribute("namespace").Value));
+ var configPath = EndpointHostConfig.GetAppConfigPath();
+ if (configPath != null)
+ {
+ var xml = configPath.ReadAllText();
+ var doc = XElement.Parse(xml);
+ doc.AnyElement("system.web.webPages.razor")
+ .AnyElement("pages")
+ .AnyElement("namespaces")
+ .AllElements("add").ToList()
+ .ForEach(x => TemplateNamespaces.Add(x.AnyAttribute("namespace").Value));
+ }
//E.g. <add key="servicestack.razor.namespaces" value="System,ServiceStack.Text" />
- if (ConfigUtils.GetAppSetting(NamespacesAppSettingsKey) != null)
+ if (ConfigUtils.GetNullableAppSetting(NamespacesAppSettingsKey) != null)
{
ConfigUtils.GetListFromAppSetting(NamespacesAppSettingsKey)
.ForEach(x => TemplateNamespaces.Add(x));
@@ -125,14 +131,16 @@ public void Configure(IAppHost appHost)
if ((razorPage = GetViewPageByResponse(dto, httpReq)) == null)
return false;
- ReloadModifiedPageAndTemplates(razorPage);
+ if (WatchForModifiedPages)
+ ReloadModifiedPageAndTemplates(razorPage);
return ProcessRazorPage(httpReq, razorPage, dto, httpRes);
});
appHost.CatchAllHandlers.Add((httpMethod, pathInfo, filePath) => {
ViewPage razorPage;
- if (filePath == null || (razorPage = GetContentPage(filePath.WithoutExtension())) == null)
+ if (filePath == null || (razorPage = GetContentPage(filePath.WithoutExtension())
+ ?? GetContentResourcePage(pathInfo)) == null)
return null;
return new RazorHandler {
@@ -170,8 +178,11 @@ public IEnumerable<ViewPage> FindRazorPages(string dirPath)
var viewPath = Path.Combine(di.FullName, "Views");
var viewSharedPath = Path.Combine(viewPath, "Shared");
+ var hasWebPages = false;
foreach (var razorFile in razorFiles)
{
+ hasWebPages = true;
+
var fileInfo = new FileInfo(razorFile);
var pageName = fileInfo.Name.WithoutExtension();
var pageContents = File.ReadAllText(razorFile);
@@ -189,6 +200,45 @@ public IEnumerable<ViewPage> FindRazorPages(string dirPath)
LastModified = fileInfo.LastWriteTime,
};
}
+
+ if (!hasWebPages) WatchForModifiedPages = false;
+
+ //Load embedded Resource Pages
+ var appHostType = EndpointHost.AppHost.GetType();
+ if (appHostType.Namespace != null)
+ {
+ viewPath = "Views";
+ viewSharedPath = Path.Combine(viewPath, "Shared");
+
+ var allResourceNames = appHostType.Assembly.GetManifestResourceNames();
+ foreach (var resourceName in allResourceNames)
+ {
+ if (resourceName.EndsWith(".cshtml") || resourceName.EndsWith(".rzr"))
+ {
+ var parts = resourceName.SplitOnLast(".");
+ var relativeName = parts[0].Replace(appHostType.Namespace + ".", "");
+ var pageName = relativeName.SplitOnLast(".").Last();
+ var razorDirPath = relativeName.Replace('.', Path.DirectorySeparatorChar);
+ var razorFile = razorDirPath + "." + parts[1];
+
+ var pageType = RazorPageType.ContentPage;
+ if (razorFile.StartsWithIgnoreCase(viewSharedPath))
+ pageType = RazorPageType.SharedViewPage;
+ else if (razorFile.StartsWithIgnoreCase(viewPath))
+ pageType = RazorPageType.ViewPage;
+
+ var pageContents = appHostType.Assembly.GetManifestResourceStream(resourceName)
+ .ReadFully().FromUtf8Bytes();
+
+ var templatePath = GetTemplateResourcePath(razorDirPath);
+
+ yield return new ViewPage(this, razorFile, pageName, pageContents, pageType) {
+ TemplatePath = templatePath,
+ LastModified = EndpointHost.StartedAt,
+ };
+ }
+ }
+ }
}
readonly Dictionary<string,string> templatePathsFound = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
@@ -219,6 +269,35 @@ private string GetTemplatePath(string fileDirPath)
return null;
}
+ private string GetTemplateResourcePath(string resourcePath)
+ {
+ if (templatePathsNotFound.Contains(resourcePath)) return null;
+
+ var appHostAssembly = EndpointHost.AppHost.GetType().Assembly;
+
+ var templateDirPath = resourcePath;
+ string templatePath;
+
+ while (templateDirPath != null && appHostAssembly.GetManifestResourceInfo(
+ Path.Combine(templateDirPath, TemplateName).Replace(Path.DirectorySeparatorChar, '.')) == null)
+ {
+ if (templatePathsFound.TryGetValue(templateDirPath, out templatePath))
+ return templatePath;
+
+ templateDirPath = templateDirPath.ParentDirectory();
+ }
+
+ if (templateDirPath != null)
+ {
+ templatePath = Path.Combine(templateDirPath, TemplateName);
+ templatePathsFound[templateDirPath] = templatePath;
+ return templatePath;
+ }
+
+ templatePathsNotFound.Add(resourcePath);
+ return null;
+ }
+
public bool ProcessRazorPage(IHttpRequest httpReq, ViewPage razorPage, object dto, IHttpResponse httpRes)
{
httpRes.AddHeaderLastModified(razorPage.GetLastModified());
@@ -325,6 +404,7 @@ public void AddPage(ViewPage page)
catch (Exception ex)
{
var errorViewPage = new ErrorViewPage(this, ex) {
+ Name = page.Name,
PageType = page.PageType,
FilePath = page.FilePath,
};
@@ -390,6 +470,14 @@ public ViewPage GetContentPage(string pageFilePath)
return razorPage;
}
+ static readonly char[] DirSeps = new[] { '\\', '/' };
+ public ViewPage GetContentResourcePage(string pathInfo)
+ {
+ ViewPage razorPage;
+ ContentPages.TryGetValue(pathInfo.TrimStart(DirSeps), out razorPage);
+ return razorPage;
+ }
+
public string GetTemplate(string name)
{
Console.WriteLine("GetTemplate(): " + name);
@@ -1,4 +1,5 @@
using System.Net;
+using ServiceStack.Common.Web;
using ServiceStack.ServiceHost;
using ServiceStack.Text;
using ServiceStack.WebHost.Endpoints.Support;
@@ -15,7 +16,9 @@ public class RazorHandler : EndpointHandlerBase
public override void ProcessRequest(IHttpRequest httpReq, IHttpResponse httpRes, string operationName)
{
- var contentPage = RazorPage;
+ httpRes.ContentType = ContentType.Html;
+
+ var contentPage = RazorPage;
if (contentPage == null)
{
var pageFilePath = this.FilePath.WithoutExtension();
@@ -32,7 +35,6 @@ public override void ProcessRequest(IHttpRequest httpReq, IHttpResponse httpRes,
if (httpReq.DidReturn304NotModified(contentPage.GetLastModified(), httpRes))
return;
-
var modelType = RazorPage.GetRazorTemplate().ModelType;
var model = modelType == typeof(DynamicRequestObject)
? null
@@ -31,6 +31,10 @@ public class EndpointHost
public static List<IPlugin> Plugins { get; set; }
+ public static DateTime StartedAt { get; set; }
+
+ public static DateTime ReadyAt { get; set; }
+
static EndpointHost()
{
ContentTypeFilter = HttpResponseFilter.Instance;
@@ -69,6 +73,7 @@ private static void ApplyConfigChanges()
//After configure called
public static void AfterInit()
{
+ StartedAt = DateTime.Now;
if (config.EnableFeatures != Feature.All)
{
@@ -109,6 +114,8 @@ public static void AfterInit()
pluginsLoaded = true;
AfterPluginsLoaded(specifiedContentType);
+
+ ReadyAt = DateTime.Now;
}
private static void AfterPluginsLoaded(string specifiedContentType)
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Configuration;
+using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
@@ -158,7 +159,18 @@ public EndpointHostConfig()
this.DefaultJsonpCacheExpiration = instance.DefaultJsonpCacheExpiration;
}
- public static System.Configuration.Configuration GetAppConfig()
+ public static string GetAppConfigPath()
+ {
+ var configPath = "~/web.config".MapHostAbsolutePath();
+ if (File.Exists(configPath))
+ return configPath;
+
+ var appHostDll = new FileInfo(EndpointHost.AppHost.GetType().Assembly.Location).Name;
+ configPath = "~/{0}.config".Fmt(appHostDll).MapAbsolutePath();
+ return File.Exists(configPath) ? configPath : null;
+ }
+
+ private static System.Configuration.Configuration GetAppConfig()
{
System.Reflection.Assembly entryAssembly;
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+ <configSections>
+ <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
+ <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
+ <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
+ </sectionGroup>
+ </configSections>
+
+ <appSettings>
+ <add key="webPages:Enabled" value="false" />
+ </appSettings>
+
+ <system.web.webPages.razor>
+ <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
+ <pages pageBaseType="ServiceStack.Razor.ViewPage">
+ <namespaces>
+ <add namespace="ServiceStack.Html" />
+ <add namespace="ServiceStack.Razor" />
+ <add namespace="ServiceStack.Auth.Tests" />
+ </namespaces>
+ </pages>
+ </system.web.webPages.razor>
+
+ <system.web>
+ <compilation debug="true" targetFramework="4.0">
+ <buildProviders>
+ <add extension=".cshtml" type="ServiceStack.Razor.ServiceStack.ServiceStackCSharpRazorBuildProvider, ServiceStack.Razor" />
+ </buildProviders>
+ <assemblies>
+ <add assembly="System.Data.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
+ <add assembly="ServiceStack"/>
+ <add assembly="ServiceStack.Razor"/>
+ <add assembly="ServiceStack.Auth.Tests" />
+ </assemblies>
+ </compilation>
+ </system.web>
+
+</configuration>
@@ -0,0 +1,15 @@
+@inherits ViewPage<ViewThatUsesLayoutAndModel>
+
+@{
+ Layout = "SimplyLayout";
+}
+
+<div>CATCH ALL: @Model.Id</div>
+<ul>
+ @foreach (var name in Get<DataSource>().Items)
+ {
+ <li>@name</li>
+ }
+
+ @Html.TextBoxFor(x => x.Id)
+</ul>
@@ -0,0 +1,13 @@
+@inherits ViewPage
+
+@{
+ Layout = "SimplyLayout";
+}
+
+<div>CATCH ALL: @Model.Id</div>
+<ul>
+ @foreach (var name in Get<DataSource>().Items)
+ {
+ <li>@name</li>
+ }
+</ul>
Oops, something went wrong.

0 comments on commit 55598ce

Please sign in to comment.