-
Notifications
You must be signed in to change notification settings - Fork 221
Add an HTML-formatted constructions support into Razor instead of the removed @helper directive. #715
Comments
First, I should clarify that View Components were designed as a replacement for MVC 5.x's Child Actions, it is not at all meant to be a replacement for It's also worth noting that I think in the meantime there are several alternatives to
In summary, there are several rich alternatives, though there aren't any that are an exact replacement for That's certainly a feature we will look at bringing back, but without the limitations that |
I have not asked about recovery of the @Helper directive. I asked how reuse a chunk of HTML (Razor) code without adding a new file? It is impossible in MVC 6 RC, isn't it? |
@alexaku you can do:
Which generates (behind the scenes): Func<dynamic, IHtmlContent> foo = item => new HelperResult(async(__razor_template_writer) => {
WriteLiteralTo(__razor_template_writer, "<p>Some HTML</p>");
}); If you want to get fancy and have it take a value by utilizing the generated
|
|
Our documentation is a work in progress but rest assured it's being worked on. These are definitely a less known part of Razor.
As unfortunate as it might be you'd need to provide some sort of poco object in that case. A potential, less clean solution would be using variables from outside of the
|
Thank you for your patience, @NTaylorMullen. What do you think about the ability of implementation of this Razor syntax in the @functions directive?
|
I'll let @NTaylorMullen answer that, as he's the resident Razor expert. |
To @crbranch, @Eilon.
|
Ah, that looks fine to me, then. |
@alexaku it will not be in ASP.NET Core 1.0 MVC at RTM (formerly known as MVC 6). But it's certainly a feature we will look to add back in the future. |
@alexaku sorry I might be confused. I thought you were asking for One difference between |
@Eilon, |
@Eilon,
And from my understanding of view components, they'd suffer from the same duplication of model metadata as simply using viewmodels with editor templates.
|
Hmm, what model metadata gets lost? There's only one model metadata system and it should get picked up no matter whether it's a partial view, |
@tboby, |
In the end, I propose to call it the "ASP.NET Core 0.6 MVC" until the old functionality will be restored. |
Same here. We used Example: What we wanted:
What we did in MVC 5:
What we do in Core: |
@DamianEdwards @rynowak @NTaylorMullen have been looking at some possible improvements in this area, so there is certainly a positive outlook that we'll see improvements here, though we don't yet have any commitment or final design. |
@alexaku You’re making it look like it’s impossible to pass parameters to functions. I don’t know how to use MVC Core, but with the real version I can get typed parameters this way: @{
Func<string, int, IEnumerable<string>, HelperResult> showThing = (name, age, tags) => new Func<object, HelperResult>(@<text>
<div>
<h3>@name</h3>
<p>Age: @age</p>
<ul>
@foreach (var tag in tags)
{
<li>@tag</li>
}
</ul>
</div>
</text>)(null);
}
<div>
@showThing("Name", 1, new[] { "a", "b", "c", })
</div> Can someone check for me if this still works in Core? Thanks. Now, I do have a library of |
@NTaylorMullen @binki @alexaku Did you find a way to put these "helpers" in separate files? I tried putting the helpers in the view's layout, but then the view can't see them. |
We have no plans to do this |
@Helper had the benefit of being extremely fast, razor syntax, strongly typed, and as many helpers as you wanted in each file. The primary cons were having to put it in App_Code to share across views, having to create static classes for helpers like HtmlHelper and UrlHelper, and some oddities in formatting/indenting with Visual Studio. The applications my company has created have hundreds of @Helper functions in App_Code. There is no way to have a high level of speed, razor syntax, and strongly typed calls without them. If they are removed we will have to move to a ton of compiled methods returning IHtmlString built from StringBuilders (or a custom type of chaining TagBuilders) which is truly a step down from @Helper. I updated your comparison of other options to @Helper.
|
The example given was:
But how about using a C# tuple to ship several values into the first argument? As in:
The only odd looking bit may be the double parentheses needed at the call sites but that's far better than having to rely on closures for parameterization. |
In addition to using C# tuples, as shown above, using local C# functions can also make it simpler to pass multiple arguments:
|
What are the extensibility points for the community to add |
@duncansmart take a look at how we built some of MVCs directives: You'll run into some issues with getting the exact syntax of the old |
How can I compatible this code with asp.net core 2 ? //Recursive function for rendering child nodes for the specified node
@helper CreateNavigation(int parentId, int depthNavigation, int currentPageId)
{
@MyHelpers.Navigation(parentId, depthNavigation, currentPageId);
}
@helper Navigation(int parentId, int depthNavigation, int currentPageId)
{
if ()
{
if ()
{
<ul style="">
@foreach ()
{
if ()
{
<li class="">
@Navigation(child.Id, depthNavigation, currentPageId)
</li>
}
}
</ul>
}
}
} |
@jahanalem's, @atifaziz suggestions should be enough to massage your code back into a similar looking state. |
This issue should be re-opened as it is still not really addressed. I have been using Core for a couple years now and I run into this limitation all the time.
|
I agree. The limitation I have right now is you can't (sensibly) make recursive functions. Partials are simply too slow for this, especially if you're generating something like a menu or a tree view. |
@NTaylorMullen |
how about this code in mvc5 , without @Helper i can't implement this perfectly in core
|
Nice idea. Let's improve on that a bit by eliminating the need for the separate public static HelperExtensions
{
public static Func<T1,IHtmlContent> Helper<T1>(
this RazorPageBase page,
Func<T1,Func<object,IHtmlContent>> helper
) => p1 => helper(p1)(null);
public static Func<T1,T2,IHtmlContent> Helper<T1,T2>(
this RazorPageBase page,
Func<T1,T2,Func<object,IHtmlContent>> helper
) => (p1, p2) => helper(p1, p2)(null);
public static Func<T1,T2,T3,IHtmlContent> Helper<T1,T2,T3>(
this RazorPageBase page,
Func<T1,T2,T3,Func<object,IHtmlContent>> helper
) => (p1, p2, p3) => helper(p1, p2, p3)(null);
// etc. for as high as you want to take the # of parameters
} Use like:
|
@rjgotten nice idea... I've added it to my benchmarks: Looks like closing over the helper arguments performs a lot better than actually passing them in as the model to the template!
|
That's a nice workaround improvement @rjgotten. Some issues with it after trying it out. The helper vars need to be declared before they're used (with |
@duncansmart E.g. public static Helper
{
public static IHtmlContent Body(Func<object, IHtmlContent> body)
{
return body(null);
}
} And then consume as
That should solve both the argument naming problem and the definition hoisting problem. Still saves you a bit of type declaration on the local functions return type vs the original by @atifaziz |
Don't we all? :-) |
The @Helper directive was removed from Razor (MVC 6) and it was not given any simple replacement. See #281.
For example, if I have define HTML code
<a src="http://www.youtube.com/watch?v=4EGDxkWoUOY" title="click me"><b>MVC 6</b> documentation</a>
and I would like to use it in many places of my Razor-compatible web-page, then I must create a new file - a "partial view". The entire file for one HTML-formatted string? Furthermore, this separated file is for a single web-page only. What if there are many chunks of HTML-code, that I need to reuse in a single web-page? How many "partial view" files should I spawn? How convenient to accompany this zoo? The answer is obvious.MVC developers have provided us with TagHelpers that are going to be added to ASP.NET MVC 6. Each tag helper is a new separate file (class). Furthermore, each of these separate file can't contain an HTML markup (Razor). So, it is not a replacement for @helpers. If you remember ViewComponents, then you understand that each new ViewComponent will add two new files - "class" and "view". It is not a replacement for @helpers too.
How can I reuse some portion of the simple HTML code in my "Razor file" without adding a bunch of extra files?
Dear MVC-developers, if you retain the @functions directive in the Razor in spite of deletion of the @Helper directive, then you must add HTML markup feature in their bodies (@functions). See below two @functions that could produce the identical result (if you will develop the interpretator of inlined HTML blocks).
@functions {
public HtmlString GetTableHeader1(String className)
{
HtmlString result = <text>
<tr class="@className">
<td title="abc">one</td>
<td title="xyz">two</td>
</tr>
</text>;
return result;
}
public HtmlString GetTableHeader2(String className)
{
HtmlString result = new HtmlString(@"
<tr class=""" + Html.Encode(className) + @""">
<td title=""abc"">one</td>
<td title=""xyz"">two</td>
</tr>
");
return result;
}
}
The text was updated successfully, but these errors were encountered: