Closed AndyMDoyle closed 4 years ago
Sure, you need to reference extension method assembly correctly.
Also you need to add @using
directive, either in template body or in builder.AddUsing("Assembly2");
(will do the same)
Have a look at my test app:
namespace Assembly1
{
public class Model
{
public string Name { get; set; }
}
}
namespace Assembly2
{
public static class StringExtender
{
public static string UppercaseFirst(this string value)
{
if (value == null)
{
return null;
}
if (value.Length > 1)
{
return char.ToUpper(value[0]) + value.Substring(1);
}
return value.ToUpper();
}
}
}
namespace ConsoleApp24
{
class Program
{
static void Main(string[] args)
{
IRazorEngine razorEngine = new RazorEngine();
var template = razorEngine.Compile<RazorEngineTemplateBase<Model>>(
"Hello @Model.Name.UppercaseFirst()",
builder =>
{
builder.AddAssemblyReference(typeof(Assembly2.StringExtender));
builder.AddUsing("Assembly2");
});
string result = template.Run(instance =>
{
instance.Model = new Model()
{
Name = "andy"
};
});
Console.WriteLine(result);
Console.ReadKey();
}
}
}
Perfect, thank you.
We had a custom razor engine setup that was utilizing the non-generic overrides to generate the template and this appears to be the cause. As the model is wrapped as an anonymous type it appears to affect the template generation, particularly in that with the anonymous model we found we had to specifically cast the properties of the model like this:
@(((MyLibrary.MyObject)Model.Value).MyExtensionMethod())
However I have added generic support to our custom engine so we can pass a strongly typed model and cut out this casting in the markup.
Thanks again.
You welcome.
For my CMS I prefer to add helpers in TemplateBase, imo it makes cshtml code look clean and nice.
pageData
, FileUrl
and Prettify
are TemplateBase members and I dont use Model
keyword at all since it does not add any value for me.
<div>
@foreach(var document in pageData.documents)
{
if (document.file == null)
{
continue;
}
<a href="@FileUrl(document.file)">document.title</a>
<div>@Prettify(document.summary)</div>
}
</div>
helpers like Prettify
work with dynamic values and do various type and value checks inside, so it is pretty safe to call helpers with whatever arguments
Hi,
Is there a way to call extension methods from templates?
I have an object in an external assembly, and in that assembly there is a public static class without a namespace that contains some extension methods for that object.
I want to call
@Model.MyObject.MyExtensionMethod(parameter)
from within the template, but I get aMicrosoft.CSharp.RuntimeBinder.RuntimeBinderException
exception throw with the error:'MyLibrary.MyObject' does not contain a definition for 'MyExtensionMethod'
I have tried adding a reference to MyLibrary this way:
But without any luck.
Is this achievable?