How to append a custom HTML attribute or CSS class using a .NET data annotation attribute? - html

I'm using ASP.NET MVC 3 RTM. Is it possible to change the HTML rendered from a View Model, by using an attribute?
Example:
public class Product
{
[AddHtmlAttribute(Name = "disabled", Value = "disabled")]
public string Name { get; set; }
}
I want the attribute to be able to change the rendered HTML, that property results in. I know it properly can't be done with an attribute alone. I probably have to hook into the system by implementing an interface, but where should I look?
I know MVC uses the default editor templates, and I've looked at them in the MVC 3 source code, but I haven't been able to figure out if it would be possible to somehow hook into the rendered element and add some attributes. I know the validation system does this, by adding custom HTML attributes to support unobtrusive validation.
I guess I just need a pointer to where I should look, or what interface I should take a look at.
Thank you so much.
Update: I'm using the standard HTML helper Html.EditorFor(model => model.Name) for my fields, and haven't overriden any editor templates. I would really prefer if I didn't have to change or override the default templates.

You may checkout the following blog post which illustrates how to achieve this by writing a custom DataAnnotationsModelMetadataProvider, attribute and overriding the default templates.

Related

Passing Razor Markup to view and process it

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.

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.

Rails: Conditionally setting CLASS atribute to a HTML tag

my question concerns about Rails + HAML
I would like to conditionally set a class atribute to a HTML tag. I figured out that the best way to do this is by setting controller variables that are used to set a class of the appropriate HTML tag.
The only solutions I found googling tell me to use a conditional in HAML. But I don't think this is the best approach, since Views shouldn't have any logic control.
So, how could I do this directly from the controller? Which are those controller variables that can set a class of a html tag?
Haml indeed discourages using logic in views and makes it easy to create helpers instead. So one solution would be to create your helper method with any logic inside.
You can't control html markup from controllers, the views are for this purpose.
If you don't want to create a separate helper (it's too much for your requirements), use existing tag helper that comes with rails. It accepts a hash of options which can be intialized from your controller if you like.
But again, I'd go for helper.
For simple logic (like setting a class) you can use haml_tag that exposes class attribute value as a string:
- haml_tag :th, class: "#{'hilite' if params[:order_by]=='title'}" do
- haml_concat link_to 'Movie Title', movies_path(order_by: 'title')
This way you still have conditional logic in the view but resorting to helper in this case may be an overkill.
If you don't want logic in your haml templates then you should move it into a helper. There's really no way for a controller to set the class for a specific html tag; that's not what controllers are for.

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.

Using ASP.NET Razor not MVC3 how do I allow html to render in a post? What method?

I am familiar with the [AllowHtml] parameter in MVC3, but I am building a site based on Asp.net and Razor not inline with MVC3. How do I allow users to enter html in their post and not get that error message? What property or setting do I need to make to allow the html to pass through? I am using LINQ to talk to the database and the property I would like to allow html for is the Body property.
var Body = Request["Body"];
Like this...
Request.Unvalidated("Body")