How to properly pass string to Razor? - asp.net-mvc

I want to create a simple function in a static class ChardinHtml.DataIntro(string message). The function is supposed to render something like data-intro='my message' and I want to use it that way:
<div #ChardinHtml.DataIntro("These are your site's settings")/>.
(The output would be <div data-intro="These are your site's settings"/> )
What exactly should I return?
Is it string/encoded string/MvcHtmlString/MvcHtmlString with encoded string inside? What should I do to protect myself from characters like ( ' ) (apostrophe) inside a message?
The code looks like this:
public static string DataIntro(string msg)
{
string str = string.Format("data-intro='{0}'", msg);
return str;
}

You can create an HTML helper method to render this. You might return MvcHtmlString as the output. Use HttpUtility.HtmlEncode to encode the string before you use it
public static class MyCustomFancyHtmlExtensions
{
public static MvcHtmlString MyFancyAttr(this HtmlHelper helper, string msg)
{
msg = HttpUtility.HtmlEncode(msg);
return new MvcHtmlString(string.Format("data-intro ='{0}'", msg));
}
}
And you can call it like after including the namespace in the razor view using the using statement
#usint YourNamespaceWhereYouDefinedTheMethod
<div class="test" #Html.MyFancyAttr("test'ing")> test</div>
While this answer your question, I am not sure what your use case is, But my recommendation is to write the data attribute directly in the razor view unless you have some complex logic involved in determining what/when to render this.

Related

Using an HtmlHelper inside a custom HtmlHelper

Is there a way to do something like the following:
public static IHtmlString TableFor(this HtmlHelper helper, IEnumerable<MaterialGroup> groups, Func<HtmlHelper, MaterialGroup, int, string> tableContentsFunc)
{
return MvcHtmlString.Create("#Html.TextBoxFor(x => this.Model.Something)");
}
Obviously this is a trivial example, but when ever I try something of the sort it renders the Helpers i.e. "#Html.TextBoxFor(x => this.Model.Something)" as text on the page instead of processing them as helpers.
Is there a way to achieve this?
public static MvcHtmlString TableFor(this HtmlHelper<IEnumerable<MaterialGroup>> helper, IEnumerable<MaterialGroup> groups, Func<HtmlHelper<MaterialGroup>, MaterialGroup, int, string> tableContentsFunc)
{
String html = "<table class='materials joists'>";
String endHtml = "</table>";
for (int i = 0; i < groups.Count(); ++i)
{
HtmlHelper<MaterialGroup> groupHelper = new HtmlHelper<MaterialGroup>(helper.ViewContext, helper.ViewDataContainer); // Crashes here with cannot convert IEnumerable<MaterialGroup> to MaterialGroup.
html += TbodyFor(groupHelper , groups.ElementAt(i), i);
html += tableContentsFunc(groupHelper , groups.ElementAt(i), i);
}
return MvcHtmlString.Create(html + endHtml);
}
public static string TbodyForJoists(this HtmlHelper<MaterialGroup> helper, MaterialGroup group, int index)
{
string html = string.Empty;
MvcHtmlString markTextbox = InputExtensions.TextBoxFor<MaterialGroup, String>(helper, x => group.Joists.ElementAt(i).Mark, new { Name = "MaterialGroups[" + index + "].Joists[" + i + "].Mark", Class = "auto-size first-column" });
html += martTextbox;
.
.
.
return html;
}
When I attempt the above I get issues with the HtmlHelper<> Types.
If I leave it with just HtmlHelper I get an error telling me to explicity state since it doesn't know what I doing with it. If I explicitly state is have conversion? issues I guess you could say.
How can I simply just use the TextBoxFor in this way?
Because that is very literally what you are telling it to do. The output of the helper itself is not processed by Razor. Whatever you return is what's going on the page.
However, you could always do:
MvcHtmlString textBox = Html.TextBoxFor(expression);
And, you'd have to feed the helper the expression to use. It perhaps would be easier in this situation to use Html.TextBox instead, but then you're going to have to do more work to try to figure out the right names and such for the fields.
It's going to be far easier and less convoluted to just use editor templates for this type of thing.

How do I use razor to make something a link conditionally?

I have a razor view where I'm currently using code that looks something like this:
#if(Model.IsLink)
{
<a href="...">
}
Some text that needs to appear
#if(Model.IsLink)
{
</a>
}
This works but the code doesn't feel clean. Is there a better/more accepted way of accomplishing this pattern?
Here is a simple method I think is a little cleaner.
Set the text to a variable at the top of the view:
#{
var someText = "Some text that must appear";
}
Then output conditionally:
#if (Model.IsLink)
{
<a href='#'>#someText </a>
}
else
{
#someText
}
The multi-line if statement above avoids doing string construction with HTML, but if you want to condense the syntax down to one line you can do this.
#Html.Raw(Model.IsLink?String.Format("<a href='#'>{0}</a>",someText):someText)
You could create a custom HtmlHelper method. See the reference on how to do that here: http://www.asp.net/mvc/tutorials/older-versions/views/creating-custom-html-helpers-cs
Your method could take the "IsLink" boolean as a parameter, and use it to either output an anchor or plain text. Here's a sample of what that might look like:
namespace MvcApplication1.Helpers
{
public static class LabelExtensions
{
public static string LinkableText(this HtmlHelper helper, bool isLink, string text, string url = null)
{
return isLink ? string.Format("<a href='{0}'>{1}</a>", url, text) : text;
}
}
}
In HTML 5 it is valid to have markup like this if you do not have a link
<a>some text</a>
and markup like this if you do
some text
And as of razor v2 your null conditional attributes take care of the href, so your code can be like this.
some text
If #link is null the href attribute will be omitted.

Turn off HTML Encoding in Razor

I have a function that returns a snippet of JavaScript and/or HTML.
static public string SpeakEvil()
{
return "<script>alert('BLAH!!');</script>";
}
In the view, Razor is quite rightly HTML encoding it, as most would expect.
#StaticFunctions.SpeakEvil()
How do I have Razor not HTML Encode this, so that the HTML and JavaScript are emitted verbatim, and that any script actually runs?
You could use the Raw() function but it's mostly meant for things that come from the database.
For a helper like you have I would suggest returning an IHtmlString:
static public IHtmlString SpeakEvil() {
return new HtmlString("<script>alert('BLAH!!');</script>");
}
That way you don't have have to call Raw() at every callsite.
Use the Html.Raw helper.
#Html.Raw(StaticFunctions.SpeakEvil())
Return a MvcHtmlString (Inherits from HtmlString) by calling the MvcHtmlString.Create() method like so:
public static MvcHtmlString SpeakEvil()
{
return MvcHtmlString.Create("<script>alert('BLAH!!');</script>");
}
You could also make it into an String extension:
public static MvcHtmlString HtmlSafe(this string content)
{
return MvcHtmlString.Create(content);
}
Source:
http://geekswithblogs.net/shaunxu/archive/2010/04/10/lt-gt-htmlencode-ihtmlstring-and-mvchtmlstring.aspx

Is there any way to combine the output of two IHtmlStrings into a single IHtmlString instance?

I'm writing an ASP.NET MVC Html Helper which basically takes 2 HTML Helpers that return IHtmlStrings and combines them together and also returns them as an IHtmlString like so:
//this doesn't work
public static IHtmlString CompositeHelper(this HtmlHelper helper, string data)
{
//GetOutput returns an IHtmlString
var output1 = new Component1(data).GetOutput();
var output2 = new Component2(data).GetOutput();
return output1 + output2
}
Now I know this isn't going to work because IHtmlString is an interface with an implementation that is a complex type, but if I go
return output1.ToHtmlString() + output2.ToHtmlString()
I just get a normal string which gets HtmlEncoded when I return it from my HtmlHelper.
So my question is, how can I take the output form two IHtmlStrings and combine them into a single IHtmlString?
Like this:
return new HtmlString(output1.ToString() + output2.ToString());

How to use ASP.NET MVC Html Helpers from a custom helper?

I have several pages listing search results, for each result I would like to display I want to create a custom View Helper in order to avoid duplicating the display code.
How do I access the convenient existing view helpers from my custom view helper? I.e. in my custom view helper I would like to use Url.Action(), Html.ActionLink, etc. How do I access them from my custom view helper?
using System;
namespace MvcApp.Helpers
{
public class SearchResultHelper
{
public static string Show(Result result)
{
string str = "";
// producing HTML for search result here
// instead of writing
str += String.Format("{1}", result.id, result.title);
// I would like to use Url.Action, Html.ActionLink, etc. How?
return str;
}
}
}
using System.Web.Mvc gives access to HtmlHelpers, but non of the convenient methods like ActionLink seem to be present.
This example should help you. This helper renders different link text depending on whether the user is logged in or not. It demonstrates the use of ActionLink inside my custom helper:
public static string FooterEditLink(this HtmlHelper helper,
System.Security.Principal.IIdentity user, string loginText, string logoutText)
{
if (user.IsAuthenticated)
return System.Web.Mvc.Html.LinkExtensions.ActionLink(helper, logoutText, "Logout", "Account",
new { returnurl = helper.ViewContext.HttpContext.Request.Url.AbsolutePath }, null);
else
return System.Web.Mvc.Html.LinkExtensions.ActionLink(helper, loginText, "Login", "Account",
new { returnurl = helper.ViewContext.HttpContext.Request.Url.AbsolutePath }, null);
}
EDIT:
All you would need to do to to access the Url.Action() method would be to replace the this HtmlHelper helper param with something like this UrlHelper urlHelp and then just call urlHelp.Action(...
Hope this helps.
A simple gravatar html helpler, your class needs to be static also.
public static string GetGravatarURL(this HtmlHelper helper, string email, string size, string defaultImagePath)
{
return GetGravatarURL(email, size) + string.Format("&default={0}", defaultImagePath);
}
you can extend the default HtmlHelper and UrlHelper just with an extension method (so you have the xxxHelper as first param in your method).
Or you can just create your base view with the method you want and use the Html or URL variable of the view.
In my opinion, you shouldn't be trying to use ActionLink within code. The whole concept of MVC is to separate logic from display, so you should try to stick with that.
I would suggest you pass the result object through to the view (maybe through ViewData) and then parse the result inline within the view. e.g.
<%= Html.ActionLink(result.title,"/showresult/" + result.id, "myController") %>

Resources