Permalink
Browse files

First cut of MVC Razor support in ServiceStack based on work done in …

…razorengine.codeplex.com

IContainerAdapter and JSONP tests and bug fixes
  • Loading branch information...
mythz committed Jun 22, 2011
1 parent 39dcefe commit 5a8f2a1a110e69f14d162c17e2bcc754683013d4
Showing with 4,891 additions and 406 deletions.
  1. +51 −0 src/RazorEngine/Compilation/CSharp/CSharpDirectCompilerService.cs
  2. +48 −0 src/RazorEngine/Compilation/CSharp/CSharpRazorCodeGenerator.cs
  3. +41 −0 src/RazorEngine/Compilation/CSharp/CSharpRazorCodeLanguage.cs
  4. +191 −0 src/RazorEngine/Compilation/CompilerServiceBase.cs
  5. +90 −0 src/RazorEngine/Compilation/CompilerServices.cs
  6. +33 −0 src/RazorEngine/Compilation/DefaultCompilerServiceFactory.cs
  7. +89 −0 src/RazorEngine/Compilation/DirectCompilerServiceBase.cs
  8. +12 −0 src/RazorEngine/Compilation/HasDynamicModelAttribute.cs
  9. +27 −0 src/RazorEngine/Compilation/ICompilerService.cs
  10. +21 −0 src/RazorEngine/Compilation/ICompilerServiceFactory.cs
  11. +56 −0 src/RazorEngine/Compilation/RazorDynamicObject.cs
  12. +49 −0 src/RazorEngine/Compilation/TypeContext.cs
  13. +68 −0 src/RazorEngine/Configuration/ConfigurationServices.cs
  14. +26 −0 src/RazorEngine/Configuration/NamespaceConfigurationElement.cs
  15. +36 −0 src/RazorEngine/Configuration/NamespaceConfigurationElementCollection.cs
  16. +71 −0 src/RazorEngine/Configuration/RazorEngineConfigurationSection.cs
  17. +92 −0 src/RazorEngine/Configuration/TemplateServiceConfigurationElement.cs
  18. +66 −0 src/RazorEngine/Configuration/TemplateServiceConfigurationElementCollection.cs
  19. +14 −0 src/RazorEngine/IRazorTemplate.cs
  20. +13 −0 src/RazorEngine/Language.cs
  21. +10 −0 src/RazorEngine/MicrosoftCSharpReferenceStub.cs
  22. +365 −0 src/RazorEngine/MvcRazorFormat.cs
  23. +22 −0 src/RazorEngine/Properties/AssemblyInfo.cs
  24. +237 −0 src/RazorEngine/Razor.cs
  25. +137 −0 src/RazorEngine/RazorEngine.csproj
  26. +48 −0 src/RazorEngine/RazorHandler.cs
  27. +127 −0 src/RazorEngine/RazorPage.cs
  28. +26 −0 src/RazorEngine/RazorPageBase.cs
  29. +25 −0 src/RazorEngine/Templating/DefaultActivator.cs
  30. +43 −0 src/RazorEngine/Templating/DelegateActivator.cs
  31. +40 −0 src/RazorEngine/Templating/DelegateTemplateResolver.cs
  32. +19 −0 src/RazorEngine/Templating/IActivator.cs
  33. +44 −0 src/RazorEngine/Templating/ITemplate.cs
  34. +16 −0 src/RazorEngine/Templating/ITemplateOfT.cs
  35. +17 −0 src/RazorEngine/Templating/ITemplateResolver.cs
  36. +36 −0 src/RazorEngine/Templating/RequireNamespacesAttribute.cs
  37. +136 −0 src/RazorEngine/Templating/TemplateBase.cs
  38. +50 −0 src/RazorEngine/Templating/TemplateBaseOfT.cs
  39. +33 −0 src/RazorEngine/Templating/TemplateCompilationException.cs
  40. +35 −0 src/RazorEngine/Templating/TemplateParsingException.cs
  41. +115 −0 src/RazorEngine/Templating/TemplateService.ServiceStack.cs
  42. +378 −0 src/RazorEngine/Templating/TemplateService.cs
  43. +66 −0 src/RazorEngine/Templating/TemplateServiceFactory.cs
  44. +44 −0 src/RazorEngine/Templating/TemplateWriter.cs
  45. +15 −0 src/ServiceStack.Common/ReflectionExtensions.cs
  46. +7 −0 src/ServiceStack.Common/ServiceClient.Web/WebRequestExtensions.cs
  47. +2 −0 src/ServiceStack.Common/Web/HttpHeaders.cs
  48. +7 −0 src/ServiceStack.ServiceInterface/ServiceBase.cs
  49. +10 −0 src/ServiceStack.sln
  50. +1 −1 src/ServiceStack/CacheAccess.Providers/ContentSerializer.cs
  51. +16 −10 src/ServiceStack/Funq/Container.cs
  52. +12 −0 src/ServiceStack/Markdown/ITemplatePage.cs
  53. +10 −10 src/ServiceStack/Markdown/MarkdownViewBase.cs
  54. +1 −1 src/ServiceStack/Markdown/TagBuilder.cs
  55. +1 −1 src/ServiceStack/Properties/AssemblyInfo.cs
  56. +1 −0 src/ServiceStack/ServiceHost/HttpRequestExtensions.cs
  57. +1 −0 src/ServiceStack/ServiceStack.csproj
  58. +34 −6 src/ServiceStack/WebHost.EndPoints/EndpointHostConfig.cs
  59. +28 −10 src/ServiceStack/WebHost.EndPoints/Extensions/IHttpResponseExtensions.cs
  60. +12 −6 src/ServiceStack/WebHost.EndPoints/Formats/MarkdownFormat.cs
  61. +6 −5 src/ServiceStack/WebHost.EndPoints/GenericHandler.cs
  62. +1 −1 src/ServiceStack/WebHost.EndPoints/Metadata/BaseSoapMetadataHandler.cs
  63. +1 −1 src/ServiceStack/WebHost.EndPoints/Metadata/CustomMetadataHandler.cs
  64. +1 −1 src/ServiceStack/WebHost.EndPoints/Metadata/JsonMetadataHandler.cs
  65. +1 −1 src/ServiceStack/WebHost.EndPoints/Metadata/JsvMetadataHandler.cs
  66. +1 −1 src/ServiceStack/WebHost.EndPoints/Metadata/XmlMetadataHandler.cs
  67. +5 −5 src/ServiceStack/WebHost.EndPoints/RestHandler.cs
  68. +2 −1 src/ServiceStack/WebHost.EndPoints/Support/HttpListenerBase.cs
  69. +32 −4 src/ServiceStack/WebHost.EndPoints/Support/Markdown/Evaluator.cs
  70. +10 −6 src/ServiceStack/WebHost.EndPoints/Support/Markdown/MarkdownPage.cs
  71. +1 −1 src/ServiceStack/WebHost.EndPoints/Support/Markdown/TemplateExtensions.cs
  72. +1 −1 src/ServiceStack/WebHost.EndPoints/Support/Markdown/TextBlock.cs
  73. +4 −15 src/ServiceStack/WebHost.EndPoints/Support/Metadata/Controls/IndexOperationsControl.cs
  74. +4 −9 src/ServiceStack/WebHost.EndPoints/Support/Metadata/Controls/OperationsControl.cs
  75. +11 −8 tests/ServiceStack.ServiceHost.Tests/App.config
  76. +19 −0 tests/ServiceStack.ServiceHost.Tests/AppData/NoTemplate/Static.cshtml
  77. +19 −0 tests/ServiceStack.ServiceHost.Tests/AppData/Template/StaticTpl.cshtml
  78. +20 −0 tests/ServiceStack.ServiceHost.Tests/AppData/Template/default.cshtml
  79. +0 −84 tests/ServiceStack.ServiceHost.Tests/AppData/TestsResults/AltCustomerDetailsResponse.htm
  80. +0 −31 tests/ServiceStack.ServiceHost.Tests/AppData/TestsResults/Customer.htm
  81. +0 −84 tests/ServiceStack.ServiceHost.Tests/AppData/TestsResults/CustomerDetailsResponse.htm
  82. +0 −83 tests/ServiceStack.ServiceHost.Tests/AppData/TestsResults/CustomerDetailsResponse.txt
  83. +2 −2 tests/ServiceStack.ServiceHost.Tests/Formats/IntroductionLayoutTests.cs
  84. +3 −1 tests/ServiceStack.ServiceHost.Tests/Formats/MockClass.cs
  85. +1 −2 tests/ServiceStack.ServiceHost.Tests/Formats/TemplateTests.cs
  86. +6 −4 tests/ServiceStack.ServiceHost.Tests/Formats/ViewTests.cs
  87. +11 −0 tests/ServiceStack.ServiceHost.Tests/Formats_Razor/CustomRazorBasePage.cs
  88. +108 −0 tests/ServiceStack.ServiceHost.Tests/Formats_Razor/RazorEngineTests.cs
  89. +989 −0 tests/ServiceStack.ServiceHost.Tests/Formats_Razor/TemplateTests.cs
  90. +22 −2 tests/ServiceStack.ServiceHost.Tests/ServiceStack.ServiceHost.Tests.csproj
  91. +18 −0 tests/ServiceStack.ServiceHost.Tests/Views/NoTemplate/Dynamic.cshtml
  92. +18 −0 tests/ServiceStack.ServiceHost.Tests/Views/Shared/DynamicShared.cshtml
  93. +18 −0 tests/ServiceStack.ServiceHost.Tests/Views/Shared/DynamicTplShared.cshtml
  94. +17 −0 tests/ServiceStack.ServiceHost.Tests/Views/Template/Customer.cshtml
  95. +33 −0 tests/ServiceStack.ServiceHost.Tests/Views/Template/CustomerDetailsResponse.cshtml
  96. +25 −0 tests/ServiceStack.ServiceHost.Tests/Views/Template/DynamicListTpl.cshtml
  97. +29 −0 tests/ServiceStack.ServiceHost.Tests/Views/Template/DynamicNestedTpl.cshtml
  98. +20 −0 tests/ServiceStack.ServiceHost.Tests/Views/Template/DynamicTpl.cshtml
  99. +20 −0 tests/ServiceStack.ServiceHost.Tests/Views/Template/default.cshtml
  100. +1 −1 tests/ServiceStack.WebHost.Endpoints.Tests/FileUploadTests.cs
  101. +2 −2 tests/ServiceStack.WebHost.Endpoints.Tests/IntegrationTests/IntegrationTestBase.cs
  102. +2 −0 tests/ServiceStack.WebHost.Endpoints.Tests/IocServiceTests.cs
  103. +1 −0 tests/ServiceStack.WebHost.Endpoints.Tests/ServiceStack.WebHost.Endpoints.Tests.csproj
  104. +9 −0 tests/ServiceStack.WebHost.Endpoints.Tests/Support/Host/IocAppHost.cs
  105. +1 −1 tests/ServiceStack.WebHost.Endpoints.Tests/Support/ServiceClientTestBase.cs
  106. +12 −4 tests/ServiceStack.WebHost.Endpoints.Tests/Support/Services/IocService.cs
  107. +62 −0 tests/ServiceStack.WebHost.Endpoints.Tests/_JsonpTests.cs
  108. +1 −0 tests/ServiceStack.WebHost.Endpoints.Tests/_SyncRestClientTests.cs
@@ -0,0 +1,51 @@
+namespace RazorEngine.Compilation.CSharp
+{
+ using System;
+ using System.Linq;
+ using System.Web.Razor.Parser;
+
+ using Microsoft.CSharp;
+
+ /// <summary>
+ /// Defines a direct compiler service for the C# syntax.
+ /// </summary>
+ public class CSharpDirectCompilerService : DirectCompilerServiceBase
+ {
+
+ #region Constructor
+ /// <summary>
+ /// Initialises a new instance of <see cref="CSharpDirectCompilerService"/>.
+ /// </summary>
+ /// <param name="strictMode">Specifies whether the strict mode parsing is enabled.</param>
+ /// <param name="markupParser">The markup parser to use.</param>
+ public CSharpDirectCompilerService(bool strictMode = true, MarkupParser markupParser = null)
+ : base(
+ new CSharpRazorCodeLanguage(strictMode),
+ new CSharpCodeProvider(),
+ markupParser) { }
+ #endregion
+
+ #region Methods
+ /// <summary>
+ /// Builds a type name for the specified generic type.
+ /// </summary>
+ /// <param name="type">The type.</param>
+ /// <param name="isDynamic">Specifies whether the type is dynamic.</param>
+ /// <returns>
+ /// The string typename (including namespace and generic type parameters).
+ /// </returns>
+ public override string BuildTypeNameInternal(Type type, bool isDynamic)
+ {
+ if (!type.IsGenericType)
+ return type.FullName;
+
+ return type.Namespace
+ + "."
+ + type.Name.Substring(0, type.Name.IndexOf('`'))
+ + "<"
+ + (isDynamic ? "dynamic" : string.Join(", ", type.GetGenericArguments().Select(t => BuildTypeNameInternal(t, CompilerServices.IsDynamicType(t)))))
+ + ">";
+ }
+ #endregion
+ }
+}
@@ -0,0 +1,48 @@
+namespace RazorEngine.Compilation.CSharp
+{
+ using System.Web.Razor;
+ using System.Web.Razor.Parser.SyntaxTree;
+
+ using Templating;
+
+ /// <summary>
+ /// Defines a code generator that supports C# syntax.
+ /// </summary>
+ public class CSharpRazorCodeGenerator : System.Web.Razor.Generator.CSharpRazorCodeGenerator
+ {
+ #region Constructor
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CSharpRazorCodeGenerator"/> class.
+ /// </summary>
+ /// <param name="className">Name of the class.</param>
+ /// <param name="rootNamespaceName">Name of the root namespace.</param>
+ /// <param name="sourceFileName">Name of the source file.</param>
+ /// <param name="host">The host.</param>
+ /// <param name="strictMode">Flag to specify that this generator is running in struct mode.</param>
+ public CSharpRazorCodeGenerator(string className, string rootNamespaceName, string sourceFileName, RazorEngineHost host, bool strictMode)
+ : base(className, rootNamespaceName, sourceFileName, host)
+ {
+ StrictMode = strictMode;
+ }
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// Gets whether the code generator is running in strict mode.
+ /// </summary>
+ public bool StrictMode { get; private set; }
+ #endregion
+
+ #region Methods
+ /// <summary>
+ /// Visits an error generated through parsing.
+ /// </summary>
+ /// <param name="err">The error that was generated.</param>
+ public override void VisitError(RazorError err)
+ {
+ if (StrictMode)
+ throw new TemplateParsingException(err);
+ }
+ #endregion
+ }
+}
@@ -0,0 +1,41 @@
+namespace RazorEngine.Compilation.CSharp
+{
+ using System.Web.Razor;
+ using System.Web.Razor.Generator;
+
+ public class CSharpRazorCodeLanguage : System.Web.Razor.CSharpRazorCodeLanguage
+ {
+ #region Constructor
+ /// <summary>
+ /// Initialises a new instance
+ /// </summary>
+ /// <param name="strictMode">Flag to determine whether strict mode is enabled.</param>
+ public CSharpRazorCodeLanguage(bool strictMode)
+ {
+ StrictMode = strictMode;
+ }
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// Gets whether strict mode is enabled.
+ /// </summary>
+ public bool StrictMode { get; private set; }
+ #endregion
+
+ #region Methods
+ /// <summary>
+ /// Creates the code generator.
+ /// </summary>
+ /// <param name="className">Name of the class.</param>
+ /// <param name="rootNamespaceName">Name of the root namespace.</param>
+ /// <param name="sourceFileName">Name of the source file.</param>
+ /// <param name="host">The host.</param>
+ /// <returns>An instance of <see cref="RazorCodeGenerator"/>.</returns>
+ public override RazorCodeGenerator CreateCodeGenerator(string className, string rootNamespaceName, string sourceFileName, RazorEngineHost host)
+ {
+ return new CSharpRazorCodeGenerator(className, rootNamespaceName, sourceFileName, host, StrictMode);
+ }
+ #endregion
+ }
+}
@@ -0,0 +1,191 @@
+namespace RazorEngine.Compilation
+{
+ using System;
+ using System.CodeDom;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Linq;
+ using System.Reflection;
+ using System.Web.Razor;
+ using System.Web.Razor.Generator;
+ using System.Web.Razor.Parser;
+
+ using Templating;
+
+ /// <summary>
+ /// Provides a base implementation of a compiler service.
+ /// </summary>
+ public abstract class CompilerServiceBase : ICompilerService
+ {
+ #region Constructor
+ /// <summary>
+ /// Initialises a new instance of <see cref="CompilerServiceBase"/>
+ /// </summary>
+ /// <param name="codeLanguage">The code language.</param>
+ /// <param name="markupParser">The markup parser.</param>
+ protected CompilerServiceBase(RazorCodeLanguage codeLanguage, MarkupParser markupParser)
+ {
+ if (codeLanguage == null)
+ throw new ArgumentNullException("codeLanguage");
+
+ CodeLanguage = codeLanguage;
+ MarkupParser = markupParser ?? new HtmlMarkupParser();
+ }
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// Gets the code language.
+ /// </summary>
+ public RazorCodeLanguage CodeLanguage { get; private set; }
+
+ /// <summary>
+ /// Gets the markup parser.
+ /// </summary>
+ public MarkupParser MarkupParser { get; private set; }
+ #endregion
+
+ #region Methods
+ /// <summary>
+ /// Builds a type name for the specified template type and model type.
+ /// </summary>
+ /// <param name="templateType">The template type.</param>
+ /// <param name="modelType">The model type.</param>
+ /// <returns>The string type name (including namespace).</returns>
+ public virtual string BuildTypeName(Type templateType, Type modelType)
+ {
+ if (templateType == null)
+ throw new ArgumentNullException("templateType");
+
+ if (!templateType.IsGenericTypeDefinition && !templateType.IsGenericType)
+ return templateType.FullName;
+
+ if (modelType == null)
+ throw new ArgumentException("The template type is a generic defintion, and no model type has been supplied.");
+
+ bool @dynamic = CompilerServices.IsDynamicType(modelType);
+ Type genericType = templateType.MakeGenericType(modelType);
+
+ return BuildTypeNameInternal(genericType, @dynamic);
+ }
+
+ /// <summary>
+ /// Builds a type name for the specified generic type.
+ /// </summary>
+ /// <param name="type">The type.</param>
+ /// <param name="isDynamic">Is the model type dynamic?</param>
+ /// <returns>The string typename (including namespace and generic type parameters).</returns>
+ public abstract string BuildTypeNameInternal(Type type, bool isDynamic);
+
+ /// <summary>
+ /// Compiles the type defined in the specified type context.
+ /// </summary>
+ /// <param name="context">The type context which defines the type to compile.</param>
+ /// <returns>The compiled type.</returns>
+ public abstract Type CompileType(TypeContext context);
+
+ /// <summary>
+ /// Generates any required contructors for the specified type.
+ /// </summary>
+ /// <param name="constructors">The set of constructors.</param>
+ /// <param name="codeType">The code type declaration.</param>
+ private static void GenerateConstructors(IEnumerable<ConstructorInfo> constructors, CodeTypeDeclaration codeType)
+ {
+ if (constructors == null || !constructors.Any())
+ return;
+
+ var existingConstructors = codeType.Members.OfType<CodeConstructor>().ToArray();
+ foreach (var existingConstructor in existingConstructors)
+ codeType.Members.Remove(existingConstructor);
+
+ foreach (var constructor in constructors)
+ {
+ var ctor = new CodeConstructor();
+ ctor.Attributes = MemberAttributes.Public;
+
+ foreach (var param in constructor.GetParameters())
+ {
+ ctor.Parameters.Add(new CodeParameterDeclarationExpression(param.ParameterType, param.Name));
+ ctor.BaseConstructorArgs.Add(new CodeSnippetExpression(param.Name));
+ }
+
+ codeType.Members.Add(ctor);
+ }
+ }
+
+ /// <summary>
+ /// Gets the code compile unit used to compile a type.
+ /// </summary>
+ /// <param name="className">The class name.</param>
+ /// <param name="template">The template to compile.</param>
+ /// <param name="namespaceImports">The set of namespace imports.</param>
+ /// <param name="templateType">The template type.</param>
+ /// <param name="modelType">The model type.</param>
+ /// <returns>A <see cref="CodeCompileUnit"/> used to compile a type.</returns>
+ public CodeCompileUnit GetCodeCompileUnit(string className, string template, ISet<string> namespaceImports, Type templateType, Type modelType)
+ {
+ if (string.IsNullOrEmpty(className))
+ throw new ArgumentException("Class name is required.");
+
+ if (string.IsNullOrEmpty(template))
+ throw new ArgumentException("Template is required.");
+
+ templateType = templateType
+ ?? ((modelType == null)
+ ? typeof(TemplateBase)
+ : typeof(TemplateBase<>));
+
+ var host = new RazorEngineHost(CodeLanguage, () => MarkupParser)
+ {
+ DefaultBaseClass = BuildTypeName(templateType, modelType),
+ DefaultClassName = className,
+ DefaultNamespace = "CompiledRazorTemplates.Dynamic",
+ GeneratedClassContext = new GeneratedClassContext("Execute", "Write", "WriteLiteral",
+ "WriteTo", "WriteLiteralTo",
+ "RazorEngine.Templating.TemplateWriter",
+ "WriteSection")
+ };
+
+ var templateNamespaces = templateType.GetCustomAttributes(typeof (RequireNamespacesAttribute), true)
+ .Cast<RequireNamespacesAttribute>()
+ .SelectMany(att => att.Namespaces);
+
+ foreach (string ns in templateNamespaces)
+ namespaceImports.Add(ns);
+
+ foreach (string @namespace in namespaceImports)
+ host.NamespaceImports.Add(@namespace);
+
+ var engine = new RazorTemplateEngine(host);
+ GeneratorResults result;
+ using (var reader = new StringReader(template))
+ {
+ result = engine.GenerateCode(reader);
+ }
+
+ var type = result.GeneratedCode.Namespaces[0].Types[0];
+ if (modelType != null)
+ {
+ if (CompilerServices.IsAnonymousType(modelType))
+ {
+ type.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(HasDynamicModelAttribute))));
+ }
+ }
+
+ GenerateConstructors(CompilerServices.GetConstructors(templateType), type);
+
+ var statement = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "Clear");
+ foreach (CodeTypeMember member in type.Members)
+ {
+ if (member.Name.Equals("Execute"))
+ {
+ ((CodeMemberMethod)member).Statements.Insert(0, new CodeExpressionStatement(statement));
+ break;
+ }
+ }
+
+ return result.GeneratedCode;
+ }
+ #endregion
+ }
+}
Oops, something went wrong.

0 comments on commit 5a8f2a1

Please sign in to comment.