I’ve got a class with a property that looks like this:
[AllowHtml]
[DataType(DataType.MultilineText)]
public string Description { get; set; }
I’ve already put in the [AllowHtml] attribute to let me submit HTML to this property via the form that I’ve built, but what I want to do is output the value of the property as the raw HTML without it being escaped.
I know I can use Html.Raw(Model.Description) but what I’m looking for is some way of telling Html.DisplayFor(m => m.Description) to always output the raw HTML. Is there an attribute I can use to decorate the properties in my class that I wish to behave like that?
Basically it’s me being lazy—I don’t want to have to remember which properties might contain HTML, so I don’t want to have to think about using Html.Raw(…) when I need to do the above—I’d much rather my Model know what it should do and do it automatically. I’ve tried searching for an answer, but either I’m not phrasing it correctly or there’s no way of doing it :(
Thanks,
Change your Description proerpty to return an HtmlString.
Razor does not escape HtmlString values.
(In fact, all Html.Raw does is create an HtmlString)
This is actually rather simple (once you know how...). Change your DataType attrib to [DataType(DataType.Html)], and create a partial view, put it in Views/Shared/DisplayTemplates/Html.cshtml, with this:
#model string
#Html.Raw(Model)
Of course you can also not change your DataType attrib, and name the view MultilineText.cshtml instead of Html.cshtml.
Just to provide a bit more info here - your issue is that # will always HtmlEncode unless you have IHtmlString returned - so the issue is sourced at the # symbol. It's one of the benefits of the razor syntax - its safer to htmlencode than to not. So there is no 'quick' way here since the root of your issue is the # symbol which will exclude HtmlEncoding if it finds IHtmlString. So - no 'quick' way around this unless you use the old <% syntax which IMHO sucks compared to razor : )
Related
I have created a model binder to sanitize string property from malicious input using AntiXssEncoder.HtmlEncode for us to be able to save encoded string without worrying about XSS. So I have made this work, however, the only problem that I'm having and solving is how to Decode string property with AntiXss encoded the value.
The page render this text as see the below:
I want the page to render the text to <test> me instead of the above image. I tried to look to some resource to do this and can make this happen by adding an extension method to a string in the view. But this is tedious I want to set something global that automatically sanitize string properties in the model before rendering them on the page.
Could anyone suggest a way implement auto string sanitization globally or override the view model and check for string properties and sanitize them before rendering the page?
Update:
Or a way which I could override this part of ActionResult
public ActionResult Test()
{
return View(model);
}
The fact that your code isn't decoding it will depend on how you are implementing your model binder.
To decode you would normally just use HttpUtility.Decode, so you may have to run this somewhere.
It may be that you need to put the [AllowHtml] attribute onto your model properties.
Alternatively it may be that you need to implement IHtmlString somehow to make use of the ToHtmlString() method which lets you put html directly onto the page without MVC sanitising it automatically.
Possibly some more code would make it clearer but one of those three should point you in the right direction.
I have already searched here to answer my question, and the closest I ever got was that post, but it still does not completely clarify the matter to me, so I will ask.
What I need is extending maxlengthattribute in the way that when I set it inside the C# file,
[MaxLength(50)]
[Display(Name = "Project Description")]
public string ProjectDescription { get; set; }
the attribute "maxlength" will be added inside the tag and will be <\stuff stuff maxlength = "50">
I have initially implemented it as writing html-helper to modify TextBoxFor, however, this is out of option since project is tightly intertwined with .js, and inserting renamed method will break a code, which will be a pain to fix.
The answer I referred above provides the closest explanation of what I need, but it looks like I will need to declare attributes (like inside ( ) in function), which I do not see there.
At this point I can either try modifying JS file on the server-side, or extending maxlengthattribute. Thus far, latter is preferable for me, thus I would like to ask how to properly extend it inside the c# file.
Thank you very much in advance!
You can write a custom dataannotation provider. The max length attribute will get added to the control.
Refer this link
I've been searching for this for a while, and couldn't find anything, apologies if there is something and I've missed it.
Is there anything in the Web-API 2 framework that will automatically reject HTML tags on string model properties (except for a select few)?
I know I could create a custom validation attribute, and whack it on every property, but that's a lot of over head to maintain and remember to do on all new models.
public class Person {
public string Name{ get; set; }
// ... snipped
}
I can make a post request to my POST endpoint with JSON similar to:
{
"name": "<h1>This is my name</h1>"
}
In the action the person.Name will be equal to "<h1>This is my name</h1>", with no validation errors raised
I was looking for the same thing as you. Coming from a MVC standpoint where we have parameters to disallow html in input fields in forms, this seems reasonable.
I found this library tho, that sort of, in a way might help out... It does not fully answer your question in the way you want it, but it helps out with the custom attributes you would otherwise have to generate by yourself, if you decided to go for an attribute path...
Nuget package:
https://www.nuget.org/packages/ASPNetWebAPIAntiXss/
Examples and the product page:
https://bitbucket.org/embarr-development/asp.net-web-api-antixss-attribute
I thought Html.HiddenFor could use Templates like Html.DisplayFor or Html.EditorFor. Unfortunately the method doesn't accept a TemplateName like the others.
I know, the workaround would be to use a DisplayFor/EditorFor Template which has HiddenFors. But I would like to find out how to extend the Html.HiddenFor method. Anyone?
Regards
Seems like you are mislead by wrong analogy. HiddenFor corresponds exactly to the <input type="hidden"/> tag. Just like TextBoxFor, CheckBoxFor etc. These methods are not designed to use templates. DisplayFor/EditorFor on the other side are specially created to be used with templates defined in the project. Thus what you are asking for is not possible out-of-the-box.
However you can always define your own overload for HiddenFor with whatever set of parameters and whatever logic you might require.
There is an overload which accept additional parameter - htmlAttributes. And you can use it for add some attributes to the result tag.
Also the second way is to create razor partial view in one of the folders
~/Areas/AreaName/Views/ControllerName/DisplayTemplates/TemplateName.cshtml
~/Areas/AreaName/Views/Shared/DisplayTemplates/TemplateName.cshtml
~/Views/ControllerName/DisplayTemplates/TemplateName.cshtml
~/Views/Shared/DisplayTemplates/TemplateName.cshtml
with name HiddenInput.cshtml
Here's what you do, you create it as an editor template, because as Andre pointed out, HiddenFor is equivalent to the helper methods like TextBoxFor and CheckboxFor.
It's likely that you'll want to have an actual editor too, so place your real editor under ~/Shared/EditorTemplates. We're going to put our "hidden editor" under the controller you wish to use it on.
~/Views/ControllerName/EditorTemplates/ModelName.cshtml
Lets say we have a Person model.
public class Person
{
public string First { get; set; }
public string Last { get; set; }
}
We'll create a partial view.
#Model Person
#Html.HiddenFor(p => p.First);
#Html.HiddenFor(p => p.Last);
And then we'll pretend we have a model that contains a Person as a property. From our main view, we call our "hidden editor" like so.
#Model Foo
#Html.EditorFor(f => f.Person)
Easy peasy lemon squeezy. A bit hacky, but it works like a charm.
Whilst looking at a theme I downloaded from the Orchard CMS gallery, I noticed that a Layout.cshtml file had this block of code at the top of the file:
#functions {
// To support the layout classifaction below. Implementing as a razor function because we can, could otherwise be a Func<string[], string, string> in the code block following.
string CalcuClassify(string[] zoneNames, string classNamePrefix)
{
var zoneCounter = 0;
var zoneNumsFilled = string.Join("", zoneNames.Select(zoneName => { ++zoneCounter; return Model[zoneName] != null ? zoneCounter.ToString() : ""; }).ToArray());
return HasText(zoneNumsFilled) ? classNamePrefix + zoneNumsFilled : "";
}
}
I know what the declared function does (calculates which zones are populated in order to return the width of each column), my question is- what is the correct use of the #function block, and when should I ever use it?
The #functions block lets you define utility functions directly in the view, rather than adding them as extensions to the #Html helper or letting the controller know about display properties. You'd want to use it when you can meet these conditions:
The functionality is tied closely to the view and is not generally useful elsewhere (such as "How wide do I make my columns").
The functionality is more than a simple if statement, and/or is used in multiple places in your view.
Everything that the function needs to determine it's logic already exists in the Model for the view.
If you fail the first one, add it as a #Html helper.
If you fail the second one, just inline it.
If you fail the third one, you should do the calculation in your controller and pass the result as part of the model.
Others have explained what #functions does so I won't rehash that. But I would like to add this:
If your view is typed to a viewmodel, I think a viable option would be to move this logic into the viewmodel to avoid cluttering your markup with too much code. Otherwise your views start to look more and more like classic ASP and I don't think anybody wants that.
I don't think there's anything wrong with using #functions or #helper in your view, but once you get beyond a couple of methods in your view, or even if the function is somewhat complicated, it might be worth refactoring to the viewmodel if at all possible. If it's code that can be reused, it may be a good idea to to pull it out into a helper class or an extension to the HtmlHelper class. One thing that is a bummer is realizing you just rewrote a piece of code that already existed because you didn't know it was hidden away in some arbitrary view.
From msdn blogs, #functions block is to let you wrap up reusable code, like the methods and properties
In this particular case, the people who have created the theme you are using probably were trying to keep it as a simple theme (only views, css and images).
If you need to write some code for a theme for Orchard, you have to turn to a module (as stated here: http://docs.orchardproject.net/Documentation/Anatomy-of-a-theme) unless you write this code in the view.
I am not sure it is worth the time to switch from a theme to a module only to get the size of a column.