[ASP.NET Core] Send data from Razor to TypeScript
Tags: csharp, aspnetcore, typescript
Published: 2022-02-28 17:56:26

## Intro
When I send some data from Razor pages to TypeScript codes, I sometimes get troubles.
In this time, I will try avoid them.

### Environments
* .NET ver.6.0.200
* Newtonsoft.Json ver.13.0.1
* Microsoft.AspNetCore.Mvc.NewtonsoftJson ver.6.0.2

* Node.js ver.17.6.0
* TypeScript ver.4.5.5
* Webpack ver.5.69.1
* Moment ver.2.29.1

## Base projects
#### Program.cs
```cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllers();

var app = builder.Build();
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints => endpoints.MapControllers());
app.Run();
```

#### Book.cs
```cs
namespace ConfigSample.Books.Models;
public record Book
{
    public int Id { get; init; }
    public string Name { get; init; } = "";
}
```

#### HomeController.cs
```cs
using Microsoft.AspNetCore.Mvc;

namespace ConfigSample.Controllers;
public class HomeController: Controller
{
    [Route("")]
    public IActionResult Index()
    {
        return View("Views/Index.cshtml");
    }
}
```

#### Index.cshtml
```html
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Razor sample</title>
        <meta charset="utf-8">
    </head>
    <body>
        <script src="js/main.page.js"></script>
        <!-- add various types arguments here -->
        <script>Page.init();</script>
    </body>
</html>
```
#### book.ts
```ts
export type Book = {
    id: number,
    name: string
};
```
#### main.page.ts
```ts
export function init(): void {
    // gets the arguments and output.
    console.log("hello world");
}
```

## string values
I can put string values directly.

#### Index.cshtml
```html
@{
    var stringValue = "Hello World";
}
<!DOCTYPE html>
<html lang="en">
...
    <body>
        <script src="js/main.page.js"></script>
        <script>Page.init('@stringValue');</script>
    </body>
</html>
```
#### main.page.ts
```ts
export function init(stringValue: string): void {
    // output "Hello World".
    console.log(stringValue);
}
```

### Japanese or other languages
I should take care if the values has Japanese or any other languages.
I have to encode and decode.

#### Index.cshtml
```html
@{
    var japaneseValue = "こんにちは世界";
    var encodedValue = System.Web.HttpUtility.UrlEncode(japaneseValue);
}
<!DOCTYPE html>
<html lang="en">
...
    <body>
        <script src="js/main.page.js"></script>
        <script>Page.init('@japaneseValue', '@encodedValue');</script>
    </body>
</html>
```

#### main.page.ts
```ts
export function init(stringValue: string, encodedStringValue: string): void {
    // output "&#x3053;&#x3093;&#x306B;&#x3061;&#x306F;&#x4E16;&#x754C;".
    console.log(stringValue);
    // output "こんにちは世界".
    console.log(decodeURI(encodedStringValue));
}
```

## int, float, double
I can put number values directly.

#### Index.cshtml
```html
@{
    var intValue = 3;
    var floatValue = 4.56f;
    var minusValue = -3.005d;
}
<!DOCTYPE html>
<html lang="en">
...
    <body>
        <script src="js/main.page.js"></script>
        <script>Page.init(@intValue, @floatValue, @minusValue);</script>
    </body>
</html>
```

#### main.page.ts
```ts
export function init(intValue: number, floatValue: number, minusValue: number): void {
    // output "3"
    console.log(intValue);
    // output "4.56"
    console.log(floatValue);
    // output "-3.005"
    console.log(minusValue);
}
```

## bool
I can't put bool values like string and number types.

Because the bool values are treated as string values.
But in C#, when I convert from a boolean "true" value to a string value, it will be a "True".

#### Index.cshtml
```html
@{
    var trueValue = true;
    var falseValue = false;
}
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Razor sample</title>
        <meta charset="utf-8">
    </head>
    <body>
        <script src="js/main.page.js"></script>
        <!-- I will get an error "Uncaught ReferenceError: True is not defined" -->
        <script>Page.init(@trueValue, @falseValue);</script>
    </body>
</html>
```

So I have to treat them as string values and set lower case manually.

#### Index.cshtml
```html
@{
    var trueValue = true;
    var falseValue = false;
}
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Razor sample</title>
        <meta charset="utf-8">
    </head>
    <body>
        <script src="js/main.page.js"></script>
        <!-- OK -->
        <script>Page.init(@trueValue.ToString().ToLower(), @falseValue.ToString().ToLower());</script>
    </body>
</html>
```

* [Trying to pass in a boolean C# variable to a javascript variable and set it to true - StackOverflow](https://stackoverflow.com/questions/656715/trying-to-pass-in-a-boolean-c-sharp-variable-to-a-javascript-variable-and-set-it)

## Date
I can put date values as string values.

#### Index.cshtml
```html
@{
    var dateValue = DateTime.Now;
}
<!DOCTYPE html>
<html lang="en">
...
    <body>
        <script src="js/main.page.js"></script>
        <!-- "3/1/2022 2:42:19 AM" -->
        <script>Page.init('@dateValue');</script>
    </body>
</html>
```

#### main.page.ts
```ts
import moment from "moment";
export function init(dateValue: Date): void {
    console.log(moment(dateValue).format("yyyy-MM-DD HH:mm:ss"));
}
```

## List, Array
I can't put list or array values directly.
Because they are also treated as string values.

#### Index.cshtml
```html
@{
    var ids = new List<int>
    {
        1, 2, 3
    };
}
<!DOCTYPE html>
<html lang="en">
...
    <body>
        <script src="js/main.page.js"></script>
        <!-- Because the value becomes "System.Collections.Generic.List`1[System.Int32]" -->
        <!-- so I will get an error: "Uncaught SyntaxError: Unexpected end of input" -->
        <script>Page.init('@ids');</script>
    </body>
</html>
```

Because I don't want to create string values like "[1, 2, 3]" manually, I use Newtonsoft.Json and serialize them as JSON values.

#### Index.cshtml
```html
@using Newtonsoft.Json
@{
    var ids = new List<int>
    {
        1, 2, 3
    };
    var idsJson = JsonConvert.SerializeObject(ids);
}
<!DOCTYPE html>
<html lang="en">
...
    <body>
        <script src="js/main.page.js"></script>
        <script>Page.init(@idsJson);</script>
    </body>
</html>
```

#### main.page.ts
```ts
export function init(ids: number[]): void {
    // [1, 2, 3]
    console.log(ids);
}
```