Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

LOL What?

Allows you to write methods that contain mixed HTML and C# in Razor Views (.cshtml) / Razor Components (.razor) files.

This is a primitive for composing Razor code that is very low overhead / low concept. Your code calls your code.

In Views (not components): Can be async, can use tag helpers. In Components (not views): Usage and semantics still need figuring out, but we want to build something like this.

Sample

<h1>Here is some info about people on the team</h1>

@foreach(var person in people)
{
    DisplayPerson(person);
}

@functions {
    void DisplayPerson(Person person)
    {
       @<div>
            <h3>
                @person.Name is @person.Age
            </h3>

            @if (DateTime.Now.DayOfYear == person.Birthday.DayOfYear)
            {
                <h4>Happy Birthday! @person.Name</h4>
            }
        </div>
    }

    Person[] people = new Person[]
    {
        new Person()
        {
            Name = "Ryan",
            Age = 33,
            Birthday = new DateTime(1985, 9, 9),
        },
        new Person()
        {
            Name = "Dan", // Not Dan Roth, some other guy. 
            Age = 53,
            Birthday = new DateTime(1965, 2, 3),
        },
    };

    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public DateTime BirthDay { get; set; }
    }
}

Your feedback

Is this W A V Y ? SPICY? Have you had cases where you wanted this? What would you add/change/remove?

@iamtheoneaboveall

This comment has been minimized.

Copy link

@iamtheoneaboveall iamtheoneaboveall commented Mar 8, 2019

text of html elements would look better if it was $"{person.name} is {person.Age}" instead of this weird syntax.

@IDisposable

This comment has been minimized.

Copy link

@IDisposable IDisposable commented Mar 8, 2019

2019 - 1965 = 54, no?

Kidding aside, I agree with @IAmTheOneAbove, above...

@andre-artus

This comment has been minimized.

Copy link

@andre-artus andre-artus commented Mar 8, 2019

I like @iamtheoneaboveall 's suggestion, it's more consistent when the display value is a more complicated expression.

Also, is the code only meant to activate on their day of birth, or also every subsequent annual celebration thereof? My experience with newborn babies is that that they tend to be a bit too out of sorts to visit websites on their first day out.

@poke

This comment has been minimized.

Copy link

@poke poke commented Mar 8, 2019

It felt that natural to me that you had to call it out explicitly here for me to notice.

When I looked at it on Twitter, I really only clicked the link to point out that the condition DateTime.Now.Date == person.BirthDay probably only works for a single birthday but not for the annual birthday.

@scottspiller

This comment has been minimized.

Copy link

@scottspiller scottspiller commented Mar 8, 2019

Happy birthday! Text needs to be person.name not person.birthday

@rynowak

This comment has been minimized.

Copy link
Owner Author

@rynowak rynowak commented Mar 9, 2019

@iamtheoneaboveall @IDisposable @andre-artus - are you familiar with Razor or just C#? This is a syntax we already have, but normally you're using it in one big method. Razor predates the $"" feature and has different semantics (HTML encoding is included).

@rynowak

This comment has been minimized.

Copy link
Owner Author

@rynowak rynowak commented Mar 9, 2019

When I looked at it on Twitter, I really only clicked the link to point out that the condition DateTime.Now.Date == person.BirthDay probably only works for a single birthday but not for the annual birthday.

Heh! Yeah, this isn't an amazing example. I wanted to include some control flow.

The purpose is that you can refactor your logic into smaller methods if you think it needs it. It's possible to decompose Razor today, but the tools to use it are weakly typed and have high overhead relative to something like a method call.

@ladeak

This comment has been minimized.

Copy link

@ladeak ladeak commented Mar 9, 2019

Interesting concept. I wonder if I would write cleaner code with this, or just make a bigger mess. Probably the second one, so I would try to use it either everywhere or nowhere.

@ateregulov

This comment has been minimized.

Copy link

@ateregulov ateregulov commented Mar 9, 2019

I think it should be as

@void DisplayPerson(Person person)

Without excess word "function", without excess level of nesting.

@ardacetinkaya

This comment has been minimized.

Copy link

@ardacetinkaya ardacetinkaya commented Mar 9, 2019

This is a big mess. Please don’t...

@Mitiko

This comment has been minimized.

Copy link

@Mitiko Mitiko commented Mar 9, 2019

I'd say the method should return something that's not void. Maybe that html content object that is used in components.

Just @ seems very undescriptive, maybe change it to return @<div> ... </div>.

@Yves57

This comment has been minimized.

Copy link

@Yves57 Yves57 commented Mar 9, 2019

In my opinion, the syntax above has too much '@' to be easy to use. In case of small components, I would like to have HTML more integrated in the C# syntax.

For me, a good compromise (i.e. remaing near the current Razor syntax) would be:

void DisplayPerson(Person person)
{
    <div>
        <h3>@person.Name is @person.Age</h3>
        if (DateTime.Now.DayOfYear == person.Birthday.DayOfYear)
        {
            <h4>Happy Birthday! @person.Name</h4>
        }
    </div>
}
  • If the first char of a line is '<', it is an HTML element. Otherwise, it is a C# expression.
  • All text following an HTML element on the same line is considered as HTML text.

Other questions:

  • In your example, the "function" is returns void. Is it possible to have async code?
  • What about HTML elements in lambda?
  • What is the function scope? Only this Razor file? Or is it possible to use more as a lightweight component in several files?
  • If it is a lightweight component, I would like to call it like in Typescript React <DisplayPerson person=@myVar />.

But I'm going probably too far :-)

@JesperTreetop

This comment has been minimized.

Copy link

@JesperTreetop JesperTreetop commented Mar 9, 2019

Just to underline what's new here, it's that with this new syntax, you could include Razor in @functions methods, whereas before if you tried, it would syntax error because it's meant to be pure C#?

I like the idea and it could help replace helpers, but this also muddies up the rules for what's HTML and what's C#. Most of the time, @ switches from HTML into C#, and not from C# into HTML. Writing HTML from inside C# is not a clean fit, especially without co-opting any return type or parameter the way @helper does. Not being able to capture the output in IHtmlContent is also problematic since most of the rest of the Razor public interface is based on top of it, although I understand that the idea is to be low-level and high-efficiency and it would be very "allocatey".

In the end, I can't help but like the way @helper solved this problem, by acknowledging that there's going to have to be some magic behind the scenes and so you can't set a return type, and using something like it would also give permission for the method signature to be malleable and different from exactly what's entered - ie in a low-level scenario, there could be an alternate method generated which output text to a writer passed in as an extra parameter instead of constructing an IHtmlContent to return. If every helper up and down the stack got that for free, I imagine there could be some savings.

Regarding the syntax: I remember that there's a feature like @<something></something> in classic Razor too, which comes with a magical item parameter which you couldn't change the name of. I don't remember the name of the feature and I have no idea if it made it to Core or not, and I think the syntax has a lot to do with that. Considering every other Razor syntax rule, it looks too close to a typo to feel natural, and it's basically impossible to Google.

@dodyg

This comment has been minimized.

Copy link

@dodyg dodyg commented Mar 9, 2019

void DisplayPerson(Person person)
{
    <div></div>
}

Removing the @ is better

also it will be great if we can compose the functions

void DisplayPerson(Person person)
{
    <div>@ShowName(person)</div>
}

void Showname(Person person)
{
  <h3>@person.Name is @person.Age</h3>
}
@conficient

This comment has been minimized.

Copy link

@conficient conficient commented Mar 9, 2019

Love it - makes it easier to compose ui

@adrianwright109

This comment has been minimized.

Copy link

@adrianwright109 adrianwright109 commented Mar 9, 2019

I get the @ in front of person e.g. @person. and if e.g. @if (... but don't think the one at the start makes sense e.g. @<div>

@HerraHak

This comment has been minimized.

Copy link

@HerraHak HerraHak commented Mar 10, 2019

The @ in front of the div is a bit confusing but overall templating html using a method in the @functions that way is good.

@Bartmax

This comment has been minimized.

Copy link

@Bartmax Bartmax commented Mar 10, 2019

This:
poke:
It felt that natural to me that you had to call it out explicitly here for me to notice.

Exactly the same feeling.

I understand some can make a mess out of this but that's up to the developer. Totally want to have the option.

The example doesn't help understand why this could be usable

@HKochniss

This comment has been minimized.

Copy link

@HKochniss HKochniss commented Mar 10, 2019

To make a comparison as someone who went to the "dark side" of pure frontend development (but still doing a lot of C#, just more PAI and no Razor no more) I have to say there is a reason that vue.js is so successful and got traction: the .vue files just click with people. And the .vue files big thing: template markup, then script, then style tag, having everything in one place, making it a real component. Makes it much simpler to read the markup, too .

Sure, that is not the topic here, but just saying that having the option to just put markup in a Razor file at the top and markup-less C# code at the bottom with some binding-magic would solve sooth the "razor is a mess" fraction (I'm partially in), because.. well.. sorry.. having converted old Razor code to a modern frontend framework.. yeah, it's a mess. Or at least it's hard to read without a proper colorization, and often even with one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment