Create an ActionLink with HTML elements in the link text - asp.net-mvc

In an ASP.NET MVC view I'd like to include a link of the form:
Link text <span>with further descriptive text</span>
Trying to include the <span> element in the linkText field of a call to Html.ActionLink() ends up with it being encoded (as would be expected).
Are there any recommended ways of achieving this?

You could use Url.Action to build the link for you:
link text <span>with further blablah</span>
or use Html.BuildUrlFromExpression:
text <span>text</span>

if you like using Razor, this should work:
link text <span>with further blablah</span>

Another option is to render your action link to an MvcHtmlString as per normal, using either HTML.ActionLink, or Ajax.ActionLink (depending on your context), then write a class that takes the rendered MvcHtmlString and hacks your html link text directly into the already rendered MvcHtmlString, and returns another MvcHtmlString.
So this is the class that does that: [please note that the insertion/substitution code is VERY simple, and you may need to beef it up to handle more nested html]
namespace Bonk.Framework
{
public class CustomHTML
{
static public MvcHtmlString AddLinkText(MvcHtmlString htmlString, string linkText)
{
string raw = htmlString.ToString();
string left = raw.Substring(0, raw.IndexOf(">") + 1);
string right = raw.Substring(raw.LastIndexOf("<"));
string composed = left + linkText + right;
return new MvcHtmlString(composed);
}
}
}
And then you would use it in the view like this:
#Bonk.Framework.CustomHTML.AddLinkText(Ajax.ActionLink("text to be replaced", "DeleteNotificationCorporateRecipient"), #"Link text <span>with further descriptive text</span>")
This approach has the advantage of not having to reproduce/understand the tag-rendering process.

Related

How to setup a helper for an Html extension

I apologize for the somewhat vagueness of this question in advance. I have setup a number of custom Html helpers to use in partial views...
What i am trying to do is set it up so if want to change how the field is displayed, then I can use an extension.
The following:
#Html.FieldFor("Somefield", "Label name:", #Model.Somevalue)
will render a standard text box on the screen with with the Id of "SomeField" and a Label of "Label Name:" and the third element is what would be shown in the field itself.
Let's say I want to show the Value in #Model.Somevalue on the screen without it being in a text field if the value is not editable at that time...
In that case I would like to be able to have something like this...
#Html.FieldFor("Somefield", "Label name:", #Model.Somevalue).NotEditbable()
and use that in the helper to determine the code that is passed back. Can someone point me to a tutorial or other resource I can use to accomplish this?
below is the Helper in question if that is useful...
public static MvcHtmlString FieldFor(this HtmlHelper helper, string FieldName, string Label, string ValueContents = null)
{
return new MvcHtmlString(String.Format("<label for=\"{0}\">{1}</label><input id=\"{0}\" type=\"text\" Value = \"{2}\">", FieldName, Label, ValueContents));
}
I ended up using this page as a guide to setup a new extension method and then to create the method I switched the MVCHtmlString to a regular string... Made the alterations, I wanted to make and then re-encoded it to a MVCHtmlString...

ASP.NET MVC with Razor, custom HtmlHelper outputs just text

I am experimenting with custom HtmlHelpers, but can't get even a basic one to work correctly. My code (just for testing sake) looks like this -
My class -
namespace HtmlHelpers.Extensions
{
public static class Helpers
{
public static string MySubmitButton(this HtmlHelper helper)
{
return String.Format("<input type=\"submit\" value=\"Submit This\">");
}
}
}
In my view -
#using HtmlHelpers.Extensions;
#Html.MySubmitButton()
This I believe should generate a simple submit button, but instead, it justs writes the following text to the screen -
<input type="submit" value="Submit">
I inspected the element, and for some reason the entire input element is being surrounded with double quotes.
Anyone know why? Thanks!
I believe you should be returning a MvcHtmlString class. Try
public static MvcHtmlString MySubmitButton(this HtmlHelper helper)
{
return MvcHtmlString.Create("<input type=\"submit\" value=\"Submit This\">");
}
although there's probably better ways to do this using a TagBuilder if you look at examples online, or the MVC source code since it's open source, you can look at their html helpers(although they are pretty complicated due to the way they layer them).
To directly answer your question of "why" it was displaying that as if it were a string, is Razor tries to be safe and convert anything you display as text instead of HTML/script. For example, #Model.PeronName will escape any characters in the peron's name with HTML character codes. Consider if there was no protection like this, and one of your users changed their name to be <script>someDangerousJavascriptThatWouldChangeCurrentUsersPassword()</script>, then posted on your forum or anywhere their name would appear, then other users visit the page, and that javascript runs and POSTS a change password form for that current user's password to some password that the hacker chose in the script. There are a wide variety of complicated attacks like this, or users might accidentally enter angle brackets(and while fairly harmless if treated as HTML they will mess up your page display).
For that reason MVC will assume just about any string is not HTML and thus replace things like <script> with <script> which basically is a way of saying "this is not html/script, I want you to display the less-than symbol and greater than symbol". If you wanted to display something as HTML, there is a #Html.Raw() helper for that, and it won't clean output, and thus should never be used with a string that you concatenated together from any data that a user my supply.

Is there a function similar to Eval() in asp.net razor?

Is there a way by which I can do somethin like this inside a Razor view:
<h1>Normal razor code</h2>
#Html.Action("NormalRazorCode")
#Eval(" #Html.Action(\"RuntimeEval\") ")
Basically a text-to-razor compiler at runtime (that doesnt create a whole new view like RazorEngine does for example).
I think you could assume that the views exist at compile time, and create the actual files at runtime, this way the ViewEngine will work the way it does by default
basically you could create a Html.Eval helper that will create the .cshtml file and after Render it using Html.Action or Html.Partial
I wanted to do something similar; I have model data (under my control) stored in a database, and it would simplify my life if I was able to include HTML helpers in those strings that could be "expanded" when included in a page.
Main motivation was to allow me to re-use existing partial views.
There's no eval function, but you can easily write an extension method that will evaluate methods that you choose to allow in advance. In my case, I want to evaluate calls to #Html.Partial(). The example here is pretty simple - it looks specifically for #Html.Partial("somePartialView") calls and replaces it with the actual partial:
public static IHtmlString ExpandHtmlString(
this HtmlHelper htmlHelper,
String html)
{
if (String.IsNullOrEmpty(html))
return new HtmlString(html);
const String IDENTIFY_PARTIAL = #"#Html.Partial\(""([a-zA-Z0-9\-_]*)""\)";
var partialFinder = new Regex(IDENTIFY_PARTIAL);
var matches = partialFinder.Matches(html);
foreach (Match m in matches) {
var matchedStr = m.Value;
var viewName = m.Groups[1].Value;
var partial = htmlHelper.Partial(viewName);
html = html.Replace(matchedStr, partial.ToHtmlString());
}
return new HtmlString(html);
}
And you call it from your Razor page as so:
#Html.ExpandHtmlString((String)Model.SomeStringField)
You could easily expand on this to to evaluate a set of methods or operators that you decide in advance you will accept.

Looking for a Html.SubmitButton helper that would accept class attributes in MVC3

I would like to use a helper for Submit button in MVC3. Is such a thing available? If not, then does anyone know where I could get some code for this. I would like one that allows me to pass a class attribute.
Isn't it simple just to write
<input type="submit" class="myclassname"/>
In MVC, there are no such things like controls, that carry much application logic. In fact, it is possible but not recommended. What i want to say is that Html helpers are just making Html writing more comfortable and help you not write duplicate code. In your particular case, i think it is simpler to write direct html than that with helper. But anyways, if you want to, it is contained in MVC Futures Library. Method is called SubmitButton
Just add to your project class with such code:
using System.Text;
namespace System.Web.Mvc
{
public static class CustomHtmlHelper
{
public static MvcHtmlString SubmitButton(this HtmlHelper helper, string buttonText, object htmlAttributes = null)
{
StringBuilder html = new StringBuilder();
html.AppendFormat("<input type = 'submit' value = '{0}' ", buttonText);
//{ class = btn btn-default, id = create-button }
var attributes = helper.AttributeEncode(htmlAttributes);
if (!string.IsNullOrEmpty(attributes))
{
attributes = attributes.Trim('{', '}');
var attrValuePairs = attributes.Split(',');
foreach (var attrValuePair in attrValuePairs)
{
var equalIndex = attrValuePair.IndexOf('=');
var attrValue = attrValuePair.Split('=');
html.AppendFormat("{0}='{1}' ", attrValuePair.Substring(0, equalIndex).Trim(), attrValuePair.Substring(equalIndex + 1).Trim());
}
}
html.Append("/>");
return new MvcHtmlString(html.ToString());
}
}
}
And usage example:
#Html.SubmitButton("Save", new { #class= "btn btn-default", id="create-button" })
chk this link out it tells you how to create custom helper method, and there is no builtin submit helper ...
http://stephenwalther.com/blog/archive/2009/03/03/chapter-6-understanding-html-helpers.aspx
and it also include a very basic Submit helper method, hope it helps
There isn't a HTML helper for a button because the HTML helpers reflect over a model's propertys and help you by setting the correct attributes for binding purposes, they also look at the VilidationAttribute metadata for that property (if any) and add any jQuery validation attributes.
Buttons are not part of the model and so do not have any helpers.
You can crate your own HTML helper by following this article http://www.asp.net/mvc/overview/older-versions-1/views/creating-custom-html-helpers-cs or using the TagBuilder class: http://www.asp.net/mvc/overview/older-versions-1/views/using-the-tagbuilder-class-to-build-html-helpers-cs but I prefer to return HTMLString than a string
There isn't one but that shouldn't stop you from building one yourself.
Even though the MVC futures project doesn't appear to be moving forward at all or supported, it's not too hard to download the source, and grab the Submit button helper (and it's supporting code) to roll your own.
It's exactly how we created the base of our SubmitButton helper for a large MVC 4 project.
Here is how I did it.
Speaking of HTML 5 <button> attribute
Create a PartialView - call it like _HTML5Button.vbhtml
#ModelType YourProjectName.ButtonViewModel
<button onclick="location.href = '#Model.URL'" class="btn btn-info">#Model.ButtonText</button>
And create a ButtonViewModel
Public Class ButtonViewModel
Public URL As String
Public ButtonText As String = "Modify Button Text"
'You can add more parameters or do as you please
End Class
Then as you need to create it call you partial like this
#Html.Partial("~/Views/Shared/MiniPartialViews/_HTML5Button.vbhtml", New ButtonViewModel With {.URL = "http://www.goanywhere.com", .ButtonText = "Name That Will Appear On The Button"})
That way if you want to add more parameters later - it is all in that one partial view centralized for you - lets say you want to add an id later on
Well you go to you partial, add an id="#Model.Id" so then in your PartialView Call you just add that parameter - it does not break anything - if you ever need to add a class to that button - add it - in one place rather than searching for all the calls.
Hope that helps - it works super well for me!

HTML.Encode but preserve line breaks

I take user input into a text area, store it and eventually display it back to the user.
In my View (Razor) I want to do something like this...
#Message.Replace("\n", "</br>")
This doesn't work because Razor Html Encodes by default. This is great but I want my line breaks.
If I do this I get opened up to XSS problems.
#Html.Raw(Message.Replace("\n", "</br>"))
What's the right way to handle this situation?
Use HttpUtility.HtmlEncode then do the replace.
#Html.Raw(HttpUtility.HtmlEncode(Message).Replace("\n", "<br/>"))
If you find yourself using this more than once it may be helpful to wrap it in a custom HtmlHelper like this:
namespace Helpers
{
public static class ExtensionMethods
{
public static IHtmlString PreserveNewLines(this HtmlHelper htmlHelper, string message)
{
return message == null ? null : htmlHelper.Raw(htmlHelper.Encode(message).Replace("\n", "<br/>"));
}
}
}
You'll then be able to use your custom HtmlHelper like this:
#Html.PreserveNewLines(Message)
Keep in mind that you'll need to add a using to your Helpers namespace for the HtmlHelper to be available.
You can encode your message, then display it raw. Something like:
#Html.Raw(Server.HtmlEncode(Message).Replace("\n", "<br/>"))
For those who use AntiXssEncoder.HtmlEncode
As AntiXssEncoder.HtmlEncode encode the /r/n character to
so the statement should be
_mDraftMsgModel.wnItem.Description = AntiXssEncoder.HtmlEncode(draftModel.txtMsgContent, false).Replace("
", "<br/>");
In my case, my string contained html that I wanted to encode but I also wanted the HTML line breaks to remain in place. The code below turns the HTML line breaks in to \n then encodes everything. It then turns all instances of \n back in to HTML line breaks:
#Html.Raw(HttpUtility.HtmlEncode(message.Replace("<br/>", "\n").Replace("<br />", "\n")).Replace("\n", "<br/>"))

Resources