# [Razor Syntax](https://docs.microsoft.com/en-us/aspnet/core/mvc/views/razor)

## Markup

```cs
@page  // set this as razor page

@model <App>.Models.Entity  // if MVC set type of elements passed to the view 
@model <Page>Model  // if Razor page set underlying class

@* razor comment *@

// substitute @variable with it's value
<tag>@variable</tag>

@{
    // razor code block
    // can contain C# or HTML

    Model  // access to passed @model (MVC)
}

@if (condition) { }

@for (init, condition, iteration) { }

@Model.Property  // display Property value (MVC)
```

---

## Tag Helpers (ASP.NET Core)

**Tag helpers** are reusable components for automating the generation of HTML in Razor Pages. Tag helpers target specific HTML tags.

Example:

```html
<!-- tag helpers for a lin in ASP.NET MVC -->
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
```

### Managing Tag Helpers

The `@addTagHelper` directive makes Tag Helpers available to the view. Generally, the view file is `Pages/_ViewImports.cshtml`, which by default is inherited by all files in the `Pages` folder and subfolders, making Tag Helpers available.

```cs
@using <App>
@namespace <App>.Pages  // or <Project>.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
```

The first parameter after `@addTagHelper` specifies the Tag Helpers to load (`*` for all Tag Helpers), and the second parameter (e.g. `Microsoft.AspNetCore.Mvc.TagHelpers`) specifies the assembly containing the Tag Helpers.
`Microsoft.AspNetCore.Mvc.TagHelpers` is the assembly for the built-in ASP.NET Core Tag Helpers.

#### Opting out of individual elements

It's possible to disable a Tag Helper at the element level with the Tag Helper opt-out character (`!`)

```cshtml
<!-- disable email validation -->
<!span asp-validation-for="Email" ></!span>
```

### Explicit Tag Helpers

The `@tagHelperPrefix` directive allows to specify a tag prefix string to enable Tag Helper support and to make Tag Helper usage explicit.

```cshtml
@tagHelpersPrefix th:
```

### Important Tag Helpers (`asp-`) & HTML Helpers (`@Html`)

[Understanding Html Helpers](https://stephenwalther.com/archive/2009/03/03/chapter-6-understanding-html-helpers)

```cs
@model <App>.Models.Entity

// Display the name of the property
@Html.DisplayNameFor(model => model.EntityProp)
@nameof(Model.EntityProp)

// Display the value of the property
@Html.DisplayFor(model => model.EntityProp)
@Model.EntityProp

<from>
    // use the property as the label, eventually w/ [DisplayName("...")]
    <label asp-for="EntityProp"></label>
    @Html.LabelFor()

    // automatically set the value at form compilation and submission
    <input asp-for="EntityProp"/>
    @Html.EditorFor()
</from>

// route config is {Controller}/{Action}/{Id?}
<a asp-controller="<Controller>" asp-action="<Action>">Link</a>  // link to /Controller/Action
<a asp-controller="<Controller>" asp-action="<Action>" asp-route-Id="@model.Id">Link</a>  // link to /Controller/Action/Id
@Html.ActionLink("<Link Text>", "<Action>", "<Controller>", new { @HTmlAttribute = value, Id = value }) // link to /Controller/Action/Id

// link to /Controller/Action?queryParameter=value
@Html.ActionLink("<Link Text>", "<Action>", "<Controller>", new { @HTmlAttribute = value, queryParameter = value })
<a asp-controller="<Controller>" asp-action="<Action>" asp-route-queryParameter="value">Link</a>  // asp-route-* for query strings
```

### [Select Tag Helper](https://docs.microsoft.com/en-us/aspnet/core/mvc/views/working-with-forms)

[StackOverflow](https://stackoverflow.com/a/34624217)
[SelectList Docs](https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.selectlist)

In `ViewModel.cs`:

```cs
class ViewModel 
{
    public int EntityId { get; set; }  // value selected in form ends up here

    // object has numeric id and other props
    public SelectList Entities = new()

    public ViewModel(){ }  // parameterless constructor (NEEDED)
}
```

In `View.cs`

```cs
@model ViewModel

<form asp-controller="Controller" asp-action="PostAction">

    <select asp-for"EntityId" asp-items="Model.Entities">
    </select>

    <button type="submit">Send<button>
</form>
```

In `Controller.cs`:

```cs
public IActionResult GetAction()
{
    var vm = new ViewModel();

    vm.Entities = new SelectList(_context.Entities, "Id", "Text");  // fill SelectList
    vm.EntityId = value;  // set selected option (OPTIONAL)
    
    return View(vm);
}


[HttpPost]
public IActionResult PostAction(ViewModel)
{
    if(ModelState.IsValid)
    {
        // extract info from view model
        // save to db
    }
}
```
