Passing Razor Markup to view and process it - html

I've searched the internet for days now with no luck finding this.
My model has a property which holds a chunk of html containing Razor markup.
exmaple:
public class ViewModel
{
public string Content = "<div>#Html.TextBox(\"UserName\")</div>";
}
In the view, I display that with
#Html.Raw(Server.HtmlDecode(Model.Content).toString())
I need to be able to convert the Razor markup into html, although because the Content is dropped in through the model, the view engine doesn't process it.
I have tried simply dropping in the Content, using just .Raw(Model.Content), .Encode(Model.Content), nothing works.
Any thoughts?

You could use the RazorEngine package which allows you to parse and execute Razor code. This being said I would not recommend you giving your users the power of editing directly Razor templates. You are opening a huge security hole in your website.
There are other templating engines such as DotLiquid for example which are better suited for scenarios where you don't trust user input.

Related

How to use Thymeleaf th:text in reactJS

I am running a springboot application with Thymeleaf and reactJS. All the HTML text are read from message.properties by using th:text in the pages, but when I have th:text in reactJS HTML block, reactJS seems angry about it.
render() {
return (
<input type="text" th:text="#{home.welcome}">
)
}
The error is:
Namespace tags are not supported. ReactJSX is not XML.
Is there a walkaround besides using dangerouslySetInnerHTML?
Thank you!
There is no sane workaround.
You are getting this error because Thymeleaf outputs XML, and JSX parsers do not parse XML.
You did this because JSX looks very, very similar to XML. But they are very, very different, and even if you somehow hacked Thymeleaf to strip namespaced attributes and managed to get a component to render, it would be merely a fleeting moment of duct-taped-together, jury-rigged code that will fall apart under further use.
This is a really, really bad idea because JSX is Javascript. You are generating Javascript on the fly. Just to name a few reasons this will not work in the long term:
This makes your components difficult if not impossible to test.
Reasoning about application state will be a nightmare as you will struggle to figure out if the source of a certain state is coming from Thymeleaf or JS.
Your application will completely grind to a halt if Thymeleaf outputs bad JS.
These problems will all get worse with time (Thyme?) as as developers abuse the ease with which they can render server-side data to the client-side, leading to an insane application architecture.
Do not do this. Just use Thymeleaf, or just use React.
Sample Alternative: I primarily work on a React application backed by a Java backend. So I understand how someone could stumble upon this hybrid and think it might be a good idea. You are likely already using Thymeleaf and are trying to figure out how you can avoid rewriting your servlets but still get the power of React.
We were in a similar boat two years ago, except with an aging JSP frontend, but the difference is negligible. What we did (and it works well) is use a JSP page to bootstrap the entire React application. There is now one JSP page that we render to the user. This JSP page outputs JSON into a single <script> tag that contains some initial startup data that we would otherwise have to fetch immediately. This contains resources, properties, and just plain data.
We then output another <script> that points to the location of a compiled JS module containing the entire standalone React application. This application loads the JSON data once when it starts up and then makes backend calls for the rest. In some places, we have to use JSP for these, which is less than ideal but still better than your solution. What we do is have the JSP pages output a single attribute containing JSON. In this way (and with some careful pruning by our XHR library) we get a poor man's data interchange layer built atop a JSP framework we don't have time to change.
It is definitely not ideal, but it works well and we have benefited vastly from the many advantages of React. When we do have issues with this peculiar implementation, they are easy to isolate and resolve.
It is possible wrap ReactJS apps in Thymeleaf. Think if you want a static persistent part (like some links, or even just displayed data), you could use Thymeleaf. If you have a complicated part (something that requires DOM repaints, shared data, updates from UI/Sockets/whatever), you could use React.
If you need to pass state you could use Redux/other methods.
You could have your backend send data via a rest API to the React part and just render your simple parts as fragments or as whole chunks of plain HTML using Thymeleaf.
Remember, Thymeleaf is really just HTML. React is virtual DOM that renders as HTML. It's actually fairly easy to migrate one to the other. So you could write anything "Static" or that does not respond much to UI, in Thymeleaf/HTML. You could also just render those parts in React too, but without State.
Thymeleaf 3 allows you to render variables from your Java to a separate JS file. So that is also an option to pass into JSX
function showCode() {
var code = /*[[${code}]]*/ '12345';
document.getElementById('code').innerHTML = code;
}
Now you can use data- prefix attributes (ex. data-th-text="${message}").
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#support-for-html5-friendly-attribute-and-element-names

ASP.NET - Using HAP (HTML Agility Pack) to Add Class References During Render

Is it possible to use the HAP (HTML Agility Pack) to:
Grab a collection of nodes e.g. all <a> elements which are children of <li> elements
Iterate over the collection
Add CSS class references into the class attribute for each element e.g. class &= "foo"
Update the nodes in their original position within the HTML
For point 4, I need to know whether:
When I grab a collection of nodes, am I working with copies?
If so, can I easily update the nodes in their original position within the HTML
Finally, would it be practical to do this when rendering a page in an ASP.NET website, considering:
I will need to modify the class references for no more than 100
elements
I am not working with large HTML documents
I plan to select my nodes starting at a div e.g. div[2] where body
contains 4 divs
I realise that this may seem like a bunch of separate questions but really it is just a breakdown of the following two questions:
Can I easily modify the HTML output of an ASP.NET page e.g. to insert class references?
Would it be practical to do this on 50 - 100 elements WRT speed e.g. no more than 2 seconds cost?
Many thanks.
Check out my CsQuery project: https://github.com/jamietre/csquery or on nuget as "CsQuery".
This is a C# (.NET 4) port of jQuery. Selectors are orders of magnitude faster than HTML Agility Pack; in fact, my initial purpose in writing it was to do exactly what you want to do: manipulate HTML in real time. As it happens, from a CMS with html generated by ckeditor.
To intercept HTML in webforms with CsQuery you do this in the page codebehind:
using CsQuery;
using CsQuery.Web;
protected override void Render(HtmlTextWriter writer)
{
// the CsQueryHttpContext object is part of the CsQuery library, it's a helper
// than abstracts the process of intercepting base.Render() for you.
CsQueryHttpContext csqContext =
WebForms.CreateFromRender(Page, base.Render, writer);
// CQ object is like a jQuery object. The "Dom" property of the context
// returned above represents the output of this page.
CQ doc = csqContext.Dom;
doc["li > a"].AddClass("foo");
// write it
csqContext.Render();
}
There is basic documentation on GitHub, but apart from getting HTML in and out, it works pretty much like jQuery. The WebForms object above is just to help you handle interacting with the HtmlTextWriter object and the Render method. The general-purpose usage is very simple:
var doc = CQ.Create(htmlString);
// or
var doc = CQ.CreateFromUrl(url);
.. do stuff with doc, a CQ object that acts like a jQuery object
string html = doc.Render();
Don't do that ! ASP.NET is not meant to be used that way, there is a better ways to do this task depending on how do you create that markup in witch you want change or add css classes. ASP.NET uses aspx templates, basically html markup and there you can intervene with code executing on server, here you can set css class statically or use server side scripts to set css class on markup with some code.
You can also create controls in code behind and set css to controls if anchor control have parent that is list item control (you will have to use server side controls).
To do it your way you will have to make Response Filter (example here) and after request is done do your parsing and write results and changes back to response stream. It's much easier using common ASP.NET techniques.

rendering front-end of survey into an MVC app

Lately I have been watching Pluralsight intro videos on MVC 3. I have never worked with the Model View Control approach before, but I'm starting to understand how these 3 crucial parts of an app are separated.
I created a front-end prototype of a survey I would like to implement into a View of my MVC web app. The survey is in HTML, CSS, using jQuery to deliver content changes depending on the type of evaluation (6-11 questions), and jQuery UI for a couple slider ratings.
I noticed through tutorials that you can use an HTML form and helpers that allow the user to edit content, but my prototype already allows the users to rate via radio buttons, comment text boxes, and sliders. Would I need to change any of my existing code if I just want to store this employee data to the Model, and depending on what survey's the employee has completed through the Controller, disable drop down fields?
Also, would I store the current employee data on submit of survey through an HttpPost in the Controller to the Model?
My apologies if my questions seem rather vague. Could someone point me in the right direction to a resource or documentation similar to my needs above? The Pluralsight videos are taking me in the wrong direction.
The form helpers you mentioned are optional. You could use a static HTML page in an MVC app with no issues, but it'll mean some extra work.
All the helpers are doing is rendering HTML for you to save you the trouble of handcoding it.
Your form should have a action attribute, and you can point that at an MVC controller URL. The data will arrive in your controller in the request, and you can pull the values out by hand. There are a number of ways to do this, including pulling the values out by key:
public ActionResult HelloWorld()
{
ViewData["Message"] = "Hello World!";
return View();
}
That would retrieve the value of a form input with a name="Message" attribute.
The best way to collect these values, though, is to allow ASP.NET MVC to map them to a .NET object for you. Read up on model binding to see how that works.
If you like books, I highly recommend Wrox Professional ASP.NET MVC3. It's very approachable and will cut your learning curve drastically. Good stuff.

Multiple views for 1 controller - Play Framework [duplicate]

If i want to have a common piece of UI across multiple pages, such as a menu, what is the recommended way to do this?
It would contain both template code and a back-end controller (similar to "snippets" in the LiftWeb framework).
I am aware that there is a menu module for Play, but I'm more interested in how this would be achieved in general.
There are two ways to include common view code into the Play Framework.
You can use the #{include} tag or the #{extends} tag.
The extends tag, as the name suggests, extends from a parent view. The extends tag is used by default in the skeleton code set up by Play when you create a new application. It extends the main.html. You add your code here.
The includes tag, allows you to inject a common piece of view code into your templates at a specified point. This works in much the same was a php include/require, or jsp includes work.
The problem will come when your template code also requires data or logic from the model (via the controller). If this is the case, then you will need to use the #Before or #With notation in your controller to ensure that the common piece of controller code is executed each time. You can add any data to the renderArgs list, so that it is available for use within the view.
A simple example of using renderArgs would be.
#Before
private static void commonData() {
// do your logic here
renderArgs.put("menu", menu);
renderArgs.put("selected", selectedMenuItem);
}
the values you have put into renderArgs (menu and selected in the example) will be available just in the same way as if you passed them into the render method.

WPF: Display HTML-based content stored in resource assembly

In my WPF project I need to render HTML-based content, where the content is stored in a resource assembly referenced by my WPF project.
I have looked at the WPF Frame and WebBrowser controls. Unfortunately, they both only expose Navigation events (Navigating, Navigated), but not any events that would allow me, based on the requested URL, to return HTML content retrieved from the resource assembly.
I can intercept navigation requests and serve up HTML content using the Navigating event and the NavigateToString() method. But that doesn't work for intercepting load calls for images, CSS files, etc.
Furthermore, I am aware of an HTML to Flowdocument SDK sample application that might be useful, but I would probably have to extend the sample considerably to deal with images and style sheets.
For what it is worth, we also generate the HTML content to be rendered (via Wiki pages) so the source HTML is somewhat predictable (e.g., maybe no JavaScript) in terms for referenced image locations and CSS style sheets used. We are looking to display random HTML content from the internet.
Update:
There is also the possibility to create an MHT file for each HTML page, which would 'inline' all images as MIME-types and alleviate the need to have finer-grained callbacks.
If you're okay with using a 28 meg DLL, you may want to take a look at BerkeliumSharp, which is a managed wrapper around the awesome Berkelium library. Berkelium uses the chromium browser at its core to provide offscreen rendering and a delegated eventing model. There are tons of really cool things you can do with this, but for your particular problem, in Berkelium there is an interface called ProtocolHandler. The purpose of a protocol handler is to take in a URL and provide the HTTP headers and body back to the underlying rendering engine.
In the BerkeliumSharp test app (one of the projects available in the source), you can see one particular use of this is the FileProtocolHandler -- it handles all the file IO for the "file://" protocol using .NET managed classes (System.IO). You could do the same thing for a made up protocol like "resource://". There's really only one method you have to override called HandleRequest that looks like this:
bool HandleRequest (string url, ref byte[] responseBody, ref string[] responseHeaders)
So you'd take a URL like "resource://path/to/my/html" and do all the necessary Assembly.GetResourceStream etc. in that method. It should be pretty easy to take a look at how FileProtocolHandler is used to adapt your own.
Both berkelium and berkelium sharp are open source with a BSD license.
The WebBrowser exposes a NavigateToStream(Stream) method that might work for you:
If your content is then stored as an embedded resource, you could use:
var browser = new WebBrowser();
var source = Assembly.Load("ResourceAssemblyName");
browser.NavigateTo(source.GetManifestResourceStream("ResourceNamespace.ResourceName"));
There is also a NavigateToString(string) method that expects the string content of the document.
Note: I have never used this in anger, so I have no idea how much help it will be!