Permalink
Browse files

Finishing up with our abstracted view engine

  • Loading branch information...
1 parent 0228946 commit 1c1afeadba280f3f55ec7620873c8e2deb43f320 @aaronpowell committed Apr 2, 2012
View
3 Owin.HelloWorld/Owin.HelloWorld.csproj
@@ -109,6 +109,9 @@
<None Include="Views\Model.cshtml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
+ <None Include="Views\_Layout.cshtml">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
View
2 Owin.HelloWorld/Startup.cs
@@ -10,7 +10,7 @@ public class Startup
public static void Configuration(IAppBuilder builder)
{
builder
- .UseViewEngine<RazorViewEngine>()
+ .DefaultViewEngine<RazorViewEngine>()
.Get("/hi", (req, res) =>
{
res.ContentType = "text/plain";
View
32 Owin.HelloWorld/ViewEngine/RazorViewEngine.cs
@@ -10,30 +10,30 @@ namespace Owin.HelloWorld.ViewEngine
{
public class RazorViewEngine : IViewEngine
{
+ private static readonly Dictionary<string, string> viewCache = new Dictionary<string, string>();
+
public string ViewFolder { get; set; }
+ public string LayoutViewName { get; set; }
public RazorViewEngine()
- : this("views")
+ : this("views", "_layout")
{
}
- public RazorViewEngine(string viewFolder)
+ public RazorViewEngine(string viewFolder, string layoutViewName)
{
ViewFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, viewFolder);
+ LayoutViewName = layoutViewName;
if (!Directory.Exists(ViewFolder))
throw new DirectoryNotFoundException("The view folder specified cannot be located.\r\nThe folder should be in the root of your application which was resolved as " + AppDomain.CurrentDomain.BaseDirectory);
}
-
private FileInfo FindView(string view)
{
var file = new FileInfo(Path.Combine(ViewFolder, view + ".cshtml"));
if (!file.Exists)
file = new FileInfo(Path.Combine(ViewFolder, view + ".vbhtml"));
- if (!file.Exists)
- throw new FileNotFoundException("No view with the name '" + view + "' was found in the views folder (" + ViewFolder + ").\r\nEnsure that you have a file with that name and an extension of either cshtml or vbhtml");
-
return file;
}
@@ -44,9 +44,25 @@ public string Parse(string viewName)
public string Parse<T>(string viewName, T model)
{
- var file = FindView(viewName);
+ viewName = viewName.ToLower();
+
+ if (!viewCache.ContainsKey(viewName))
+ {
+ var layout = FindView(LayoutViewName);
+ var view = FindView(viewName);
+
+ if (!view.Exists)
+ throw new FileNotFoundException("No view with the name '" + view + "' was found in the views folder (" + ViewFolder + ").\r\nEnsure that you have a file with that name and an extension of either cshtml or vbhtml");
+
+ var content = File.ReadAllText(view.FullName);
+
+ if (layout.Exists)
+ content = File.ReadAllText(layout.FullName).Replace("@Body", content);
+
+ viewCache[viewName] = content;
+ }
- return Razor.Parse(File.ReadAllText(file.FullName), model);
+ return Razor.Parse(viewCache[viewName], model);
}
}
}
View
46 Owin.HelloWorld/ViewEngine/ViewEngineActivator.cs
@@ -8,6 +8,50 @@ namespace Owin.HelloWorld.ViewEngine
{
public static class ViewEngineActivator
{
- public static IViewEngine ViewEngine { get; set; }
+ private static IViewEngine defaultViewEngine;
+ private static Dictionary<string, Tuple<Func<IViewEngine>, IViewEngine>> viewEngines = new Dictionary<string, Tuple<Func<IViewEngine>, IViewEngine>>();
+
+ public static void RegisterViewEngine(string viewEngineId, Func<IViewEngine> viewEngineActivator)
+ {
+ viewEngines.Add(viewEngineId, new Tuple<Func<IViewEngine>, IViewEngine>(viewEngineActivator, (IViewEngine)null));
+ }
+
+ public static IViewEngine ResolveViewEngine(string viewEngineId)
+ {
+ if (string.IsNullOrEmpty(viewEngineId))
+ {
+ throw new ArgumentNullException("viewEngineId", "A ViewEngine ID needs to be provided for resolution");
+ }
+
+ if (!viewEngines.ContainsKey(viewEngineId))
+ {
+ throw new KeyNotFoundException(string.Format("The ViewEngine ID {0} has not been registered, ensure it is registered before use", viewEngineId));
+ }
+
+ var engine = viewEngines[viewEngineId];
+
+ if (engine.Item2 == null)
+ {
+ var activator = engine.Item1;
+ engine = viewEngines[viewEngineId] = new Tuple<Func<IViewEngine>, IViewEngine>(activator, engine.Item1());
+ }
+
+ return engine.Item2;
+ }
+
+ public static IViewEngine DefaultViewEngine
+ {
+ get
+ {
+ if (defaultViewEngine == null)
+ defaultViewEngine = ResolveViewEngine("defaultViewEngine");
+
+ return defaultViewEngine;
+ }
+ set
+ {
+ defaultViewEngine = value;
+ }
+ }
}
}
View
39 Owin.HelloWorld/ViewEngine/ViewEngineExtensions.cs
@@ -7,22 +7,37 @@ namespace Owin.HelloWorld.ViewEngine
{
public static class ViewEngineExtensions
{
- public static IAppBuilder UseViewEngine<TViewEngine>(this IAppBuilder builder)
+ public static IAppBuilder DefaultViewEngine<TViewEngine>(this IAppBuilder builder)
where TViewEngine : IViewEngine, new()
{
- return builder.UseViewEngine(new TViewEngine());
+ return builder.DefaultViewEngine(() => new TViewEngine());
}
- public static IAppBuilder UseViewEngine<TViewEngine>(this IAppBuilder builder, TViewEngine viewEngine)
- where TViewEngine : IViewEngine
+ public static IAppBuilder DefaultViewEngine(this IAppBuilder builder, Func<IViewEngine> viewEngine)
{
- ViewEngineActivator.ViewEngine = viewEngine;
+ ViewEngineActivator.DefaultViewEngine = viewEngine();
+ return builder.RegisterViewEngine(viewEngine, "defaultViewEngine");
+ }
+
+ public static IAppBuilder RegisterViewEngine(this IAppBuilder builder, Func<IViewEngine> viewEngine, string viewEngineId)
+ {
+ ViewEngineActivator.RegisterViewEngine(viewEngineId, viewEngine);
return builder;
}
public static void View(this Response res, string view)
{
- var output = ViewEngineActivator.ViewEngine.Parse(view);
+ var output = ViewEngineActivator.DefaultViewEngine.Parse(view);
+
+ res.ContentType = "text/html";
+ res.Status = "200 OK";
+ res.End(output);
+ }
+
+ public static void View(this Response res, string view, string viewEngineId)
+ {
+ var viewEngine = ViewEngineActivator.ResolveViewEngine(viewEngineId);
+ var output = viewEngine.Parse(view);
res.ContentType = "text/html";
res.Status = "200 OK";
@@ -31,7 +46,17 @@ public static void View(this Response res, string view)
public static void View<T>(this Response res, string view, T model)
{
- var output = ViewEngineActivator.ViewEngine.Parse(view, model);
+ var output = ViewEngineActivator.DefaultViewEngine.Parse(view, model);
+
+ res.ContentType = "text/html";
+ res.Status = "200 OK";
+ res.End(output);
+ }
+
+ public static void View<T>(this Response res, string view, T model, string viewEngineId)
+ {
+ var viewEngine = ViewEngineActivator.ResolveViewEngine(viewEngineId);
+ var output = viewEngine.Parse(view);
res.ContentType = "text/html";
res.Status = "200 OK";
View
10 Owin.HelloWorld/Views/Basic.cshtml
@@ -1,9 +1 @@
-<!doctype html>
-<html>
- <head>
- <title>Hello World!</title>
- </head>
- <body>
- <h1>Hello World, I came from Razor!</h1>
- </body>
-</html>
+<h1>Hello World, I came from Razor!</h1>
View
11 Owin.HelloWorld/Views/Model.cshtml
@@ -1,10 +1 @@
-<!DOCTYPE html>
-<html>
-<head>
- <meta charset="utf-8" />
- <title>Hi @Model.Name</title>
-</head>
-<body>
- <h1>Hi there @Model.Name. Did you know you're a model property?</h1>
-</body>
-</html>
+<h1>Hi there @Model.Name. Did you know you're a model property?</h1>
View
11 Owin.HelloWorld/Views/_Layout.cshtml
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+
+<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <meta charset="utf-8" />
+ <title>Demo title</title>
+</head>
+<body>
+ @Body
+</body>
+</html>

0 comments on commit 1c1afea

Please sign in to comment.