I know I can add custom attributes to any given helper using an anonymous type with the attribute and value specified for it to be rendered as a HTML5 attribute however im looking to achieve the same across all HTML Helpers in a given view triggered by an externally specified helper. Similar to the same functionality you receive from the un-obtrusive JavaScript helper where it renders validation rules in the context of a form field's attributes.
Does anyone know if there is a "simple" way to inject these customisations into the helpers, or will I need to extend each of the helpers independently?
Cheers
You can't extend all methods from one centralized point (write code that will extend all your html helper methods by adding overload with additional 'htmlAttributes' parameter - may be it is possible by using IL methods generation, but it is hard way).
Each extension should be overload of your html helper method, and you can implement like in example:
public static class HtmlExtensions
{
public static string MyPager(this HtmlHelper html, string parameter1, int parameter2)
{
var builder = new TagBuilder("div");
GenerateMyPagerBody(builder , parameter1, parameter2); // insert body into tag
return builder.ToString(TagRenderMode.SelfClosing);
}
public static string MyPager(this HtmlHelper html, string parameter1, int parameter2, object htmlAttributes)
{
var builder = new TagBuilder("div");
GenerateMyPagerBody(builder , parameter1, parameter2);
builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));
return builder.ToString(TagRenderMode.SelfClosing);
}
}
Related
I would like to create something that can be called into any view in a website like this
#MyBusinessName.TelephoneNumber
#MyBusinessName.Address
etc...
In the same way I would call a HtmlHelper
#Html.ActionLink()
How do I add a namespace like "MyBusinessName" for use in an MVC view?
Html in Razor pages is a property of the class that pages inherit from, so of course you can't implement what you want in the same way as the standard HTML helper works. But I can suggest a different solution.
You may define a static class in your project that will work as your own helper (define there static methods/properties you want to use in views). I'd suggest something like the following:
using System.Web.Mvc;
namespace YourProject.Infrastructure {
public static class YourBusinessHelper {
public static MvcHtmlString TextBox(string name) {
string html = string.Format("<input name=\"{0}\" />", name);
return new MvcHtmlString(html);
}
// ...
}
}
System.Web.Mvc.MvcHtmlString is a class representing HTML markup that an HTML helper method inserts into the view where it is used. You may create it using a constructor that receives a string parameter containing the needed HTML markup — like in my code.
Now you can use this class in your views. You just need to import the containing namespace with this Razor instruction:
#using YourProject.Infrastructure
I'd suggest to put it into the view start file (_ViewStart.cshtml) so that it applies to all your views.
The sample helper method above can be used simply:
#YourBusinessHelper.TextBox("TextBoxName")
UPDATE: you may also create an extension method for HtmlHelper:
using System.Web.Mvc;
namespace YourProject.Infrastructure {
public static class YourBusinessHelper {
public static string CompanyPhoneNumber(this HtmlHelper helper) {
return "+82649256720";
}
// ...
}
}
You may use string not MvcHtmlString in helper methods if they return plain text (no HTML markup).
Use it like a built-in helper method:
#:Call us: #Html.CompanyPhoneNumber()
The default DisplayFor helper just throws some escaped text on the page. Is there a way to wrap the default in a <span> or <div> without writing custom DisplayFor templates for each property you want to display? Instead of it spewing out
Foo
I want it to spit out
<span>Foo</span>
I've seen a lot of articles for making the custom stuff; I use those quite often. But most of my display stuff I just want to handle with simple CSS where the content is wrapped in a tag, and I can't find a reference on how to do this, or even if it's possible.
Sure use the 'object' template and override as follows from ViewData.ModelMetadata.Properties
Object template - Html.Display using ViewBag
By having your display template named object.cshtml you will apply to all types with numerable properties
There's a link to brad wilsons entry that contains the primary details
http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-3-default-templates.html
You could create your own HtmlHelper extension
public static class HtmlHelperExtensions
{
public static MvcHtmlString EnhancedDisplayFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
var stringBuilder = new StringBuilder("<span>");
stringBuilder.Append(html.DisplayFor(expression));
stringBuilder.Append("</span>");
return new MvcHtmlString(stringBuilder.ToString());
}
}
and then use it like this
#Html.EnhancedDisplayFor(model => model.MyProperty);
I have an ASP.NET WebForms control (derived from Control, not WebControl, if it helps) that has a rather complicated Render() function. The control has no viewstate and only uses the Control approach so it can render output directly. I feel it's a fine candidate for working with the MVC approach.
I'd like to use it in an MVC application I'm using, however I don't know what's the best way to go about it.
At first I thought about converting it to a HTML Helper method, but my control renders a large amount of HTML so the Helper method (with it returning strings) isn't too attractive.
The alternative is a PartialView, but those are UserControl derivatives, which wouldn't be appropriate in this case.
I see other HTML Helper methods don't return HtmlString, but actually use HtmlHelper.ViewContext.Writer to write output directly, but according to this question ( HtmlHelper using ViewContext.Writer not rendering correctly ) he was getting strange results. I'd like to avoid that mishap.
EDIT:
I think I've solved it using the HtmlHelper.ViewContext.Writer approach, and I haven't experienced the same problem as the problem I quoted.
Here's the code I wrote:
public static class MiniViewHelper {
public static void RenderMiniView<TModel>(this HtmlHelper html, MiniView<TModel> view, TModel model) {
TextWriter wtr = html.ViewContext.Writer;
HtmlTextWriter hwtr = wtr as HtmlTextWriter;
if( hwtr == null ) hwtr = new HtmlTextWriter( wtr );
view.Render( hwtr );
}
}
public abstract class MiniView<TModel> {
public TModel Model { get; set; }
public abstract void Render(HtmlTextWriter wtr);
}
public class VeryComplicatedMiniView : MiniView<ComplicatedViewModel> {
public override void Render(HtmlTextWriter wtr) {
wtr.WriteLine("VeryComplicatedMiniView ");
}
}
Used like so from my pages:
<% Html.RenderMiniView( new VeryComplicatedMiniView () { Propery1 = foo }, Model.RelevantMiniViewModel ); %>
Any thoughts?
The two approaches you have outlined in your question are correct. You could either try to write a custom HTML helper which will spit the same HTML as the control or use a partial.
I see other HTML Helper methods don't return HtmlString, but actually
use HtmlHelper.ViewContext.Writer to write output directly
ViewContext.Writer should be fine. Returning an IHtmlString from the helper is also fine. Just make sure you are properly encoding it inside since IHtmlString will not be automatically HTML encoded in Razor and it supposes that the helper takes care of this. Using a TagBuilder to generate a DOM tree in a helper is a good approach.
I have some read-only data I want to display in a View, but it needs to be manipulated by jQuery in the browser.
I could use Html.DisplayTextFor but then I can't manipulate it (at least, I don't think I can.) Oh, and I also want to be able to style this.
What's the best way of doing this?
You could just output it in a div or span, maybe write an extension method on HtmlHelper to do this (untested):
public static string Display(this HtmlHelper html, string value, string cssClass)
{
TagBuilder span = new TagBuilder("span");
span.InnerHtml = value;
span.AddCssClass(cssClass);
return span.ToString();
}
I have an HtmlHelper extension that currently returns a string using a string builder and a fair amount of complex logic. I now want to add something extra to it that is taken from a render partial call, something like this ...
public static string MyHelper(this HtmlHelper helper)
{
StringBuilder builder = new StringBuilder();
builder.Append("Hi There");
builder.Append(RenderPartial("MyPartialView"));
builder.Append("Bye!");
return builder.ToString();
}
Now of course RenderPartial renders directly to the response so this doesn;t work and I've tried several solutions for rendering partials to strings but the all seem to fall over one I use the HtmlHelper within that partial.
Is this possible?
Because this question, although old and marked answered, showed up in google, I'm going to give a different answer.
In asp.net mvc 2 and 3, there's an Html.Partial(...) method that works like RenderPartial but returns the partial view as a string instead of rendering it directly.
Your example thus becomes:
//using System.Web.Mvc.Html;
public static string MyHelper(this HtmlHelper helper)
{
StringBuilder builder = new StringBuilder();
builder.Append("Hi There");
builder.Append(helper.Partial("MyPartialView"));
builder.Append("Bye!");
return builder.ToString();
}
I found the accepted answer printed out the viewable HTML on the page in ASP.NET MVC5 with for example:
#Html.ShowSomething(Model.MySubModel, "some text")
So I found the way to render it properly was to return an MvcHtmlString:
public static MvcHtmlString ShowSomething(this HtmlHelper helper,
MySubModel subModel, string someText)
{
StringBuilder sb = new StringBuilder(someText);
sb.Append(helper.Partial("_SomeOtherPartialView", subModel);
return new MvcHtmlString(sb.ToString());
}
You shouldn't be calling partials from a helper. Helpers "help" your views, and not much else. Check out the RenderAction method from MVCContrib (if you need it now) or MVC v2 (if you can wait a few more months). You'd be able to pass your model to a standard controller action and get back a partial result.