Passing NewLine (or <Br />) inside ViewData["msg"] - asp.net-mvc

How do I pass an Environment.NewLine (or a < br />) inside a ViewData["msg"]
that renders as a real <br /> inside the View itself?
I'm using C# ...

You can simply use
HttpUtility.HtmlEncode("<br />");
Have a look here for further details.
EDIT:
I am sorry but I did not understand the question at the beginning. I thought you wanted to encode the passed string. Sometimes I read question too fast :)
Anyway to completely answer your question have a look at these samples. Suppose in your action you have:
[HttpGet]
public virtual ActionResult Index() {
ViewData["Message"] = "This is a test." + "<br />" + "Does it work?";
return View();
}
And in your view you have
<p>Sample 1: <br /><%= ViewData["Message"]%></p>
<p>Sample 2: <br /><%: ViewData["Message"]%></p>
Notice the difference between the two construct. You will get the following results:
Sample 1:
This is a test.
Does it work?
Sample 2:
This is a test.<br />Does it work?
So the first sample usage answer your question. The key is to simply not encoding the string as opposed to what I understood at the beginning. The second construct, the one that use <%: %>, available if you're using .NET 4.0, automatically encode every string it render.
If you still want to use this latest construct and avoid that the string would be encoded you have to use a trick. Simply tell the construct that the string is already encoded and it does not need to be re-encoded. To achieve this use this sample code
[HttpGet]
public virtual ActionResult Index() {
ViewData["Message2"] = MvcHtmlString.Create( "This is a test." + "<br />" + "Does it work?" );
return View();
}
and in the view normally use the <%: %> construct
<p>Sample 3: <br /><%: ViewData["Message2"]%></p>
For more details on using the MvcHtmlString and how it works please refer to this question on SO.
Ciao!

Did you try \n or \r inside the ViewData string itself?

Use this:
TempData["MsgString"] = MvcHtmlString.Create("No Data" + "<br />" + "For Something");
Or, with variables:
TempData["MsgString"] = MvcHtmlString.Create(Strings.StrNoData + "<br />" + Strings.StrSomething);

Related

Checkboxes generated via CheckBoxFor helper turn into type=hidden because of MaterializeCSS

I'm creating a website with ASP.NET MVC5 and I'm using MaterializeCSS for the first time, which looks like a very exciting framework.
However, the checkboxes generated by CheckBoxFor helper become hidden !
When I write :
#Html.CheckBoxFor(m => m.IsAgreeTerms)
The generated HTML is :
<input name="IsAgreeTerms" type="hidden" value="false">
Why does Materialize change my type=checkbox into type=hidden ?
I tried to add type="checkbox" in the CheckboxFor helper, but it doesnt change anything. The only way is to modify in in my browser's console.
The only solution I found is this SO thread.
However, the accepted answer doesn't change anything for me.
The other answer works, but I think it's ugly to add some JS script to modify what Materialize modifies without my consent.
Is there any way to say "Hey, I ask for a type=checkbox, so just let my type=checkbox in the generated HTML" ?
Thank you
UPDATE :
My full ASP.NET MVC code is :
#Html.CheckBoxFor(m => m.IsAgreeTerms, new { #type = "checkbox" })
#Html.LabelFor(m => m.IsAgreeTerms, new { #class = "login-label" })
The full generated HTML is
<input data-val="true" data-val-required="Le champ IsAgreeTerms est requis." id="IsAgreeTerms" name="IsAgreeTerms" type="checkbox" value="true"
<input name="IsAgreeTerms" type="hidden" value="false">
<label class="login-label" for="IsAgreeTerms">IsAgreeTerms</label>
Here's a solution in the form of a html helper. It constructs a checkbox and label in the correct order:
public static IHtmlString CheckBoxWithLabelFor<TModel>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, bool>> expression,
string labelText,
object htmlAttributes = null
)
{
if (expression == null)
{
throw new ArgumentNullException(nameof(expression));
}
var checkBoxWithHidden = htmlHelper.CheckBoxFor(expression, htmlAttributes).ToHtmlString().Trim();
var pureCheckBox = checkBoxWithHidden.Substring(0, checkBoxWithHidden.IndexOf("<input", 1, StringComparison.Ordinal));
var labelHtml = htmlHelper.LabelFor(expression, labelText).ToHtmlString().Trim();
var result = pureCheckBox + Environment.NewLine + labelHtml + Environment.NewLine + $"<input type=\"hidden\" name=\"{ExpressionHelper.GetExpressionText(expression)}\" value=\"false\" />";
return new MvcHtmlString(result);
}
Is there other html generated by materialize.css? I think this happens because it is not possible apply a custom CSS to element input of type checkbox.
So, the checkbox becomes hidden and other html component represents visually the checkbox. Many components work like that.
UPDATE:
Why is Html checkbox generating an additional hidden input
OP here. Problem looks like more complex.
Actually, when using #Html.CheckBoxFor, MVC5 generates 3 fields, in that order :
Your input, with type="checkbox", binded to your model property
An hidden field (see the Claudio's link for an explaination)
Your label, generated by #Html.LabelFor
Problem is Materialize expects that in another order to work.
In your browser's console, just move the <label> element between the input and the hidden field, and everything works fine !
I found this very useful link, where, basically, it is said that the order of the generated fields by #Html.checkBoxFor will change ... In MVC6 !
As I'm working with MVC5, I use this very ugly solution in my _Layout:
$(":checkbox").each(function () {
$(this).nextAll("label").before($(this))
})
If anyone has a better idea, please feel free to post an elegant solution.

How to display a string with new lines as a string with <br />'s in AngularDart?

Given that I have a string being displayed on the page in AngularDart.
... <strong>Notes: </strong> {{cmp.selectedStudent.notes}} ...
How can I make it display multi-line? In the string I have newline characters, I want them to be encoded as <br /> characters in the html output.
You can replace the '\n' in your string with <br/> and use something like the proposed my-bind-html directive shown in my answer here How to add a component programatically in Angular.Dart? (the code might be a bit outdated due to a lot of recent changes in Angular)
You could use ng-repeat and repeat over your notes lines but first you need to split them by '\n' so you get an array of lines.
List<String> _notesList = null;
List<String> get notesList {
if (_notesList==null) _notesList = notes.split("\n").toList(); return _notesList;
}
.
<span ng-repeat="note in cmp.selectedStudent.notesList">{{note}}<br /></span>
By default, angular doesn't interpret HTML balise to avoid some unpredictible behavior or others bad thing, but you can disable this verification with
ng-bind-html
link to the official doc : NgHtmlBind
So you can replace directly the '\n' character by the 'br' html node.
So you can do :
// ...
String getHtmlBrNote() {
return this.notes.replaceAll("\n", "<br />");
}
// ...
and after in angular
... <strong>Notes: </strong> <span ng-bind-html="cmp.selectedStudent.getHtmlBrNote()"></span> ...
And it will be ok

Kendo UI Conditional Button in ClientTemplate

I'm trying to get a conditional client template to work in a Kendo Grid that will call into my controller with a simple userName string as a parameter but I cannot figure out the syntax to get this working correctly.
My template is in my view like this:
columns.Bound(user => user.IsLockedOut).ClientTemplate(
"# if (IsLockedOut == true) { #" +
"<input type='button' value='Unlock Acc' onclick='location.href=" + #Url.Action("UnlockAccount", "Administration", new { userName = "#= UserName #" + }) + "/>" +
"# } else { #" +
"Unlocked" +
"# } #"
);
And the action method of the controller looks like:
public void UnlockAccount(string userName)
{
}
At the moment the error generated is:
CS1525: Invalid expression term '}'
I've been looking at this for a couple of hours now and I cannot see the wood for the trees now.
You have some '+' plus symbol that you do not actually need. Also you do not need the 'at' sign # in front of the helper.
new { userName = "#= UserName #" + }) //<- that last plus
This method worked for me.
const string ShowUpdateButton = "#if (IsNetReversal == false) {#<a class='k-button k-button-icontext k-grid-edit' href='\\#'><span class='k-icon k-edit'></span>Update</a>#}#";
const string ShowReverseButton = "#if (IsNetReversal == false) {#<a class='k-button k-button-icontext k-grid-reverse' href='/JournalDetail/Reverse/#: ID #' ><span class='k-icon k-reverse'></span>Reverse</a>#}#";
const string ShowDeleteButton = "#if (IsAdjustment == true) {#<a class='k-button k-button-icontext k-grid-delete' href='\\#'><span class='k-icon k-delete'></span>Delete</a>#}#";
You can do the template inline but I find it easier (particularly for multiple buttons) if you declare constants and then use string.format to concatenate them.
col.Template(o => o).ClientTemplate(string.Format("{0}{1}{2}", ShowUpdateButton, ShowDeleteButton, ShowReverseButton));
The upside is it will work with popup editor whereas jquery hacks will ignore the conditional status when a user cancels out of edit. A cancel from the popup editor will restore the grid row from the viewmodel or wherever Kendo stores it which results in button states from before any jquery/javascript hack. The method above will also auto-wire the standard commands since I copied their HTML output for the client template.
The downside is that if Kendo changes their pattern for command buttons the client template may fail. I tired several other methods besides this one and the downside to this method seems better than the other methods.
Note on Kendo Forums: As of the date of this post, they do not appear to allow people who do not pay for support to post to the forums so I would suggest posting questions here instead. They monitor Stack Overflow and in my experience they seem to answer questions more quickly here.
I've gotta a bit further but only by manually writing the URL like this:
"<input type='button' value='Unlock Acc' onclick='location.href=/Administration/TryUnlockAccount?userName=#= UserName #'/>"
Still doesn't call my controller method though but it does have the right parameter value ...

Mvc Html.Label or Html.TextBox doesn't create

I'm making a test page for a project I'm working on and I've made desired progress so far but I'm trying to create TextBoxes from a model of List being passed to the view, however, the it seems to just ignore anything I have tried.
<form id="form1" runat="server">
<input id="btnsubmit" type="submit" name="Submit" onclick="Submit" />
<div id="divControls">
<% foreach (TextBox control in (this.Model as List<TextBox>))
{
Html.Label("lblLabel", control.Text);
Html.TextBox(control.ID, control.Text, new { id = control.ID, style = "width:50", name = "txt" + control.ID });
} %>
</div>
</form>
The List isn't null in the Controller on return. I don't have a clue at what the problem could be. If I throw a Something in the for loop it executes the appropriate number of times so why isn't it creating the labels or textboxes?
At first I thought it was that I'm adding them inside a form but I removed the form tags and it still didn't work so I really have no Idea, any help would be much appreciated. I'm relatively new to MVC.
[HttpPost]
public ActionResult Index(FormCollection form)
{
List<TextBox> controls = new List<TextBox>();
foreach (String Key in form.Keys)
{
if (Key.Contains("txt"))
{
TextBox textBox = new TextBox();
textBox.ID = Key;
textBox.Text = form.GetValues(Key)[0];
controls.Add(textBox);
}
}
return View("Index", controls);
}
Here's my Action encase it's helps.
Also encase I wasn't clear enough, I am adding controls to a form at runtime using JQuery and then that Action will be part of the submit so it must send the textboxes back to the view so they are not deleted.
Like I said I'm new to the whole MVC and Asynchronous thing so If there's a better way to do this, advice would be much appreciated.
Your not printing the html
<% foreach (TextBox control in (this.Model as List<TextBox>))
{%>
<%=Html.Label("lblLabel", control.Text)%>
<%=Html.TextBox(control.ID, control.Text, new { id = control.ID, style = "width:50", name = "txt" + control.ID })%>
<% } %>
Your code is looping through the controls and the Html.whaterever is returning a string but your not doing anything with it, just discarding it.
you also don't need to return a whole TextBox object. This is probably inefficient. Just return an struct or a class containing your data
Html.Label returns a string containing a <label> tag.
You're discarding that string.
You need to write it to the page by writing <%= Html.Whatever() %>.

Writing/outputting HTML strings unescaped

I've got safe/sanitized HTML saved in a DB table.
How can I have this HTML content written out in a Razor view?
It always escapes characters like < and ampersands to &.
Supposing your content is inside a string named mystring...
You can use:
#Html.Raw(mystring)
Alternatively you can convert your string to HtmlString or any other type that implements IHtmlString in model or directly inline and use regular #:
#{ var myHtmlString = new HtmlString(mystring);}
#myHtmlString
In ASP.NET MVC 3 You should do something like this:
// Say you have a bit of HTML like this in your controller:
ViewBag.Stuff = "<li>Menu</li>"
// Then you can do this in your view:
#MvcHtmlString.Create(ViewBag.Stuff)
You can use
#{ WriteLiteral("html string"); }
Sometimes it can be tricky to use raw html. Mostly because of XSS vulnerability. If that is a concern, but you still want to use raw html, you can encode the scary parts.
#Html.Raw("(<b>" + Html.Encode("<script>console.log('insert')</script>" + "Hello") + "</b>)")
Results in
(<b><script>console.log('insert')</script>Hello</b>)
You can put your string into viewdata in controller like this :
ViewData["string"] = DBstring;
And then call that viewdata in view like this :
#Html.Raw(ViewData["string"].ToString())
Apart from using #MvcHtmlString.Create(ViewBag.Stuff)
as suggested by Dommer, I suggest you to also use AntiXSS library as suggested phill http://haacked.com/archive/2010/04/06/using-antixss-as-the-default-encoder-for-asp-net.aspx
It encodes almost all the possible XSS attack string.
Complete example for using template functions in RazorEngine (for email generation, for example):
#model SomeModel
#{
Func<PropertyChangeInfo, object> PropInfo =
#<tr class="property">
<td>
#item.PropertyName
</td>
<td class="value">
<small class="old">#item.OldValue</small>
<small class="new">#item.CurrentValue</small>
</td>
</tr>;
}
<body>
#{ WriteLiteral(PropInfo(new PropertyChangeInfo("p1", #Model.Id, 2)).ToString()); }
</body>

Resources