With Dynamicweb 8.2.3 we released Razor based templates in Dynamicweb.
This thread is for discussing these new features and ask questions to the first implementations.
With Dynamicweb 8.2.3 we released Razor based templates in Dynamicweb.
This thread is for discussing these new features and ask questions to the first implementations.
Hi,
I would like to share a blog post where I write about fetching a RSS feed using items and Razor templates.
Lets prototype a razor and item based rss feed publisher
I have added the templates and itemtypes to Gist (find link in above blog post).
There is a simpel version and a version with cache and execution time implemented.
/Sten Hougaard
Hi Sten
Thank you for that post. Great example of how you can achieve something cool with few lines of code inside the template.
Nicolai
We've created a Dynamicweb Razor repository on Github where we plan to share example templates using Dynamicweb Razor [https://github.com/dynamicweb/razor/].
The repository has a wiki [https://github.com/dynamicweb/razor/wiki] where you can share your tips and tricks (you need a Github account to edit wiki pages). Feel free to edit existing pages or create new ones.
Best regards,
Mikkel
Here is some stuff that I think is missing in the beta version. Please correct me if any of this is already possible (without using classic template tags):
What Morten said.
And what about html encoding. In DW Razor strings are not html encoded by default currently. I think it should just like mvc razor. If we want the raw string we should be able to use @Html.Raw(GetValue("dwtag"))
Hi Morten and Remi
Thank you for the great suggestions. We are still looking into the heart of our implementation and might release something that is much closer to MVC.
Morten
@1: You can still use the regular Dynamicweb Translate tag. It is not a template tag, but a template tag syntax. We should have a Razor version.
@2: @Html is VERY MVC specific and not a Razor thing - and since DW is not MVC this can pose a problem.
@3: The engine supports it - there are some namespace issues in the compiled template though that we need to fix.
@4: Yes
@5: Oh YES! we are working on this, but see my general comment.
@6: Yes. There might be some issues though...
Remi:
We have chosen not to do that - there is a lot of fields that renderes HTML, like editors, Navigations, content placeholders etc. You would have to write A LOT of @Raw statements - we found it more appropriate to add html encoding where needed.
Nicolai
Thanks for the feedback. Have you measured what is or should not be html encoded?
I have not. But a quick estimate makes me think it is the other way around.
Also today a lot of tags are not html encoded which should be. We have the html encode function in the old and new templates but i have to add it a lot. Only on the richtext files i need the raw html string.
I prefer to always html encode and apply raw string only where needed. This is a safer approach.
I can not estimate the impact on the code of DW and maybe the old templates. This could be a valid reason for DW not to do html encoding by default. For Razor i prefer html encoding by default as you can see :)
I guess i have to live with no html encoding by default :(
Hi Remi
Yes we have. And yes, lots of tags should.
We can make a setting so you can define the default - that would be for the entire solution and all Razor templates in it then.
Would that be a viable solution?
BR Nicolai
Yes being able to choose the default would be appreciated. :)
Probably a newbie Razor question, but is it possible to separate Razor functions from view.
Eg. i have 8 paragraph templates that all use the same function to render their images.
I'd like to create one Razor file to contain my functions, and then just include it in my 8 templates.
Makes sense? Is it possible in Razor, and in DW Razor?
// Martin
You can use the good old <!--@Include(…)--> to reuse Razor function and helpers across templates.
Check out https://github.com/dynamicweb/itembasedmodules/blob/master/Files/Templates/Designs/itembasedmodules/ItemPublisher/List/Blog_Post_List.cshtml for an example.
Best regards,
Mikkel
Hi there,
Any way we can access e.g. the Product collection in a product list template an do some manipulating what that before the loop is rendered?
Also, I saw on another thread that assumably it should be possible to include HTML templates in a razor template. I'm trying that by including it inside a loop, but I don't seem to be very succesfull at it. Is it possible?
BR.
Lars
Hi Lars
No, the Collection is not available in the template. You can access the data though and change it like this:
@foreach (LoopItem i in GetLoop("Someloop")){ i.Values("MyOwnTag") = "Myvalue"; i.Values("DwTag") = i.Values("DwTag") + "PostFix"; }
Values property returns an object with the type of data in the tag, int, datetime, string, boolean etc.
You cannot add items to the loop i.e., and the loop will only contain the i.e. 10 products ot of X products on the page.
If you want to manipulate the Collection it self before it hits the rendering engine, subscribe to Notifications.eCommerce.ProductList.BeforeSort notification.
If you want to control the contents of the product Collection, create a Dynamicweb.Extensibility.Provider.ProductListCollectionProvider.
You can use @Include() in raszor file, but it has to include another razor file. All includes are handled when the file is read from disk and merged into one. If the master is razor, all the content (including includes) of that file is handled like one razor file. So razor can include razor, html can include html.
BR Nicolai
Hi there,
We're experiencing problems accessing website item tags in a razor template. We included a paragraph in the master template with the CartV2 modul having. The module template is Razor, and the master page is HTML. Have you experienced something similar?
BR.
Lars
Sorry, I asked a stupid question before searching:) I just needed to apply the correct syntax as described here:
"We can make a setting so you can define the default - that would be for the entire solution and all Razor templates in it then.
Would that be a viable solution?"
Has this been implemented? Have not seen it yet.
Hi Remi
No it did not make it...
BR Nicolai
When will it make it?
I am asking because we see more customers starting with security scans. We keep fixing html encoding issues on older sites.
For new developments i want to enforce html encoding. A frontend developer must have a good reason when he needs the raw value.
This might be a long reach, but it is possible to include razor files in a normal html template? I'm getting errors when trying, but i'm not sure if its a genuine error from the razor file, or simply that the template cant render the razor.
Hi Kasper
You can do like this:
@Include(somefile.cshtml) @if (GetInteger("counter") > 0) { ... }
Yeah sure but that's razor syntax. Can I incule a razor within a normal html template like <!--@Include(somefile.cshtml)--> ?? I know I can include html templates in razor but does it work the other way around?
Hi Kasper
You can include Razor files in Razor files and html in html files.
The type of the including file determines if the merged template is parsed as Razor or Html.
Include is basically just a merge of 2 files into one before execution.
Sure i'm aware. But can we agree that you can also include html files in razor files?
Yes you can, but it will be parsed as Razor.
The Razor that includes a HTML will be merged into a Razor.
You can also include Razor in HTML, but it will be parsed as HTML and Razor code will not be executed.
Right, got it. That's what I was looking for. Thank you for your time
Can i ask again to add an option to enable default html ecoding in razor templates?
Please add it because i am still seeing issues in recent websites where things should have been html encoded.
Remi, have you tried inserting this in your template:
<!--@HtmlEncodeTagValues=True-->
I'm not sure if it works in Razor templates though. I prefer to do my own encoding :)
http://developer.dynamicweb.com/releases/all-new-features-in-8-x.aspx#item9752
This does not work for razor :(
And i like it the other way around. Like mvc :) Let's try to get parity between Asp.net and Dynamicweb.
Also consider the following.
We are creating html templates. Most values need to be html encoded.
There are exceptions of course where you need the raw or a url encoded value for example.
If i forget to use a raw value somewhere this becomes visible on the frontend or somewhere else and i can fix it.
If i forget to use a html encoded value this is not immediately visible and can lead to XSS problems.
I think a lot of dw sites have XSS issues because we forgot to html encode values.
Just a thought ;)
Is it possible to mix .html and .cshtml templates?
Say I have a task to change a template in a module, but do not want to change the master, page and paragraph template to razor.
Is that possible?
Med venlig hilsen/Best regards,
Sten Hougaard
Webudvikler
It is possible. Kind of. But not really. Razor templates can't be nested, and there's no razor syntax to include partials. Razor can't be included in html, but html can be included in razor with <!--@Include(Partial.cshtml)-->. So it depends on how your structure is.
Sten, you can mix Dynamicweb HTML templates and Razor templates, i.e. use Razor in a module template and HTML in the paragraph template, but you cannot mix Razor and Dynamicweb HTML within the same template.
@IncludeFile and @MasterPageFile work by replacing the statement with the content of the actual file being referenced. This means that if your layout templates uses Razor then any master template must also use Razor. And any included files must use the same syntax as the file with the @IncludeFile.
Best regards,
Mikkel
Hi,
I'd like to know if it's possible to create some helper class which uses some of the core methods from the Dynamicweb Razor implementation. As an example I have the following HTML helper:
public static IHtmlString GetProductSpecifications(object context, string prefix, int fields) { var builder = new StringBuilder(); var features = new List<string>(); for (var i = 1; i < fields + 1; i++) { var value = context.GetString(String.Format("Ecom:Product:Field.{0}{1}.Value", prefix, i)); if (!string.IsNullOrEmpty(value)) { features.Add(value); } } // Do more stuff return new HtmlString(builder.ToString()); }
I'd like to pass an object (I don't know of which type) as a parameter (marked in orange) to my helper method. This object should be able to call the GetString methodto get the value from a certain product field.
Is this possible? And if so, which object should I pass to make the code compile?
Thanks!
Tom
Assuming you're calling this function from within a loop you should pass an object of type LoopItem (fully qualified: Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>.LoopItem), i.e.
public static IHtmlString GetProductSpecifications(LoopItem context, string prefix, int fields) { … }
Best regards,
Mikkel
PS: This thread is getting really long and we should start new threads when new questions arise.
Hi Mikkel,
I'm actually not calling it from a loop, I'm calling it from a page (containing the Product Catalog module). Is it possible to pass the context of the current displayed product to a helper method in order to use the GetString / GetValue helper methods on the context?
Regards,
Tom
The current template is actually an instance of Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>, so you can pass it to your function using a Razor template like this:
@inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> … @functions { public static IHtmlString GetProductSpecifications(Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> context, string prefix, int fields) { … } … }
Best regards,
Mikkel
And I could actually pass a new instantiated object of type Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> to my helper class in order to use the GetString and other helper methods?
Well, you could do that, but the idea behind my last example is that you can pass the current template object to the function:
@GetProductSpecifications(this, "", 0)
Best regards,
Mikkel
Sorry, your answer was what I was looking for but accidentaly pushed the mark as answer button... maybe that's a good moment to start a new thread regarding Razor... :-)
Please start a new thread whenever you have a new question …
Best regards,
Mikkel
Hi Nicolai,
Is the following still a criteria in order to manipulate the product collection before it renders on the frontend:
"If you want to manipulate the Collection it self before it hits the rendering engine, subscribe to Notifications.eCommerce.ProductList.BeforeSort notification."
'If you want to control the contents of the product Collection, create a Dynamicweb.Extensibility.Provider.ProductListCollectionProvider."
I am currently trying to manipulate a product collection via the Dynamicweb.eCommerce.ProductList.BeforeRender notification in order to hide/show specific products and optimize paging as products not visible to specific users shouldnt be paged.
BR MikkelTO
Hi Mikkel
Yes. But, it really depends on your configuration and implementation. If you use optimized product retrieval, DW will only give you a collection with a product count of the page size, i.e. 10 - so if you remove one, you are lacking a product no 10. So that is the issue with BeforeSort notification.
Using the Provider, you return the products - that works, but you need to do a lot of work.
If you want to remove products for some users, I would recommend using assortments - they do just that.
Hi Nicolai,
Thanks for your answer. Actually we're currently rewriting some custom code which already can specify a collection of products available to the user based on a user field on his/her's user. However as we're trying to implement the functionality into a more standard dynamicweb solution. So basically we're rendering all the products as it is, though we, of course, aren't interested in showing products that isn't available to the specific user, or getting products paged for that matter.
Maybe I need to do the above mentioned logic in the ProductListCollectionProvider?
BR MikkelTO
Hi Mikkel
Yes, simply use the ProductListCollectionProvider to return the collection you want to show. If the provider returns a collection instance, Dynamicweb will not make its own. But you have to fill the collection.
You can use the beforesort notification to get the collection Dynamicweb returns, and manipulate that (remove stuff) and have it displayed. But then disable optimized product retrieval (which is fine on smaller lists) and it should work.
BR Nicolai
Hi Nicolai,
I got it working using the ProductListCollectionProvider - which is awesome! The only "down-side" atm. is that it takes forever to load the different category pages (30-40secs each), given the fact that I currently loop the total products in each category and output the ones available to the user. I guess caching could be a way to improve the load time on this. Anyway, thanks for your feedback!
BR MikkelTO
You must be logged in to post in the forum