Reputation: 3632
I've been trying to use RazorEngine in a little project of mine but can't get past this error when I try to use template layouts.
Unable to compile template. 'object' does not contain a definition for 'Description' and no extension method 'Description' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)
My Setup: I have a template layout like this:
<html>
<head>
<title>@Model.Description</title>
</head>
<body>
@RenderBody()
</body>
</html>
And then a page template that looks like this:
@{
_Layout = "Layout.cshtml";
}
<h1>@Model.Description</h1>
Here is a test Main function I'm using to try and figure this out:
static void Main(string[] args)
{
// Configuration for RazorEngine
var config = new TemplateServiceConfiguration
{
EncodedStringFactory = new RawStringFactory(),
Resolver = new DelegateTemplateResolver(name =>
{
var file = name;
var content = File.ReadAllText("Templates/" + file);
return content;
})
};
// Try to render output using Razor
using (var service = new TemplateService(config))
{
string template = File.ReadAllText("Templates/Default.cshtml");
dynamic model = new ExpandoObject();
model.Description = "This is a test";
string result = service.Parse(template, model);
Console.WriteLine(result);
if (Debugger.IsAttached)
{
Console.ReadLine();
}
}
}
Any idea what I'm missing?
Update: It works if I replace the dynamic model object with a POCO with a Description property. I also tried the typed version of Parse with
dynamic
, ExpandoObject
, and IDictionary<string, object>
but they all have the same error.
Update: I found this project on Github that seems to make it work somehow: https://github.com/mikoskinen/graze/blob/master/src/core/Graze.cs#L174
Upvotes: 10
Views: 3428
Reputation: 11
try to use like this :
service.AddTemplate("layout", "<h1>@RenderBody()</h1>");
service.AddTemplate("template", @"@{Layout = ""layout"";}my template");
service.Compile("template");
Upvotes: 0
Reputation: 11
Razor vs. MVC vs. WebPages vs. RazorEngine There is often a confusion about where Razor sits in this set of technologies. Essentially Razor is the parsing framework that does the work to take your text template and convert it into a compilable class. In terms of MVC and WebPages, they both utilise this parsing engine to convert text templates (view/page files) into executable classes (views/pages). Often we are asked questions such as "Where is @Html, @Url", etc. These are not features provided by Razor itself, but implementation details of the MVC and WebPages frameworks.
Upvotes: 1
Reputation: 1793
Create the model as you do above
In your Index template set the ViewBag.Description to the Model.Description
@{
_Layout = "Layout.cshtml";
ViewBag.Description = Model.Description;
}
<div>Hello John </div>
In the layout page use the viewbag instead of the model
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>@ViewBag.Description</title>
</head>
<body>
<div id="content">
@RenderBody()
</div>
@if (IsSectionDefined("Footer"))
{
<div id="footer">
@RenderSection("Footer")
</div>
}
</body>
</html>
I don't know why the dynamic model cant be used in the layout page. This is how i use it in my project
Upvotes: 2
Reputation: 43
You can't pass an anonymous type into a dynamically-typed view because the anonymous types are compiled as internal. Since the CSHTML view is compiled into a separate assembly, it can't access the anonymous type's properties.
Upvotes: 4
Reputation: 1925
I would think it to be more appropriate to use the template service's Parse
overload that takes a ViewBag
and use the ViewBag
in your view rather than a model.
Edit:
public virtual string Parse(string razorTemplate, object model, DynamicViewBag viewBag, string cacheName)
Upvotes: 4