mini-web-server icon indicating copy to clipboard operation
mini-web-server copied to clipboard

Support Razor in Mvc

Open daohainam opened this issue 1 year ago • 3 comments

Mvc sẽ sử dụng một phiên bản thu gọn của Asp.Net Core Razor, các tính năng được hỗ trợ bao gồm:

  • Nhúng các đoạn code C# sử dụng cú pháp: @() (dùng cho biểu thức) hoặc @{} (dùng cho khối lệnh).
  • Định nghĩa kiểu của Model sử dụng cú pháp @model .
  • Cho phép sử dụng using với cú pháp @using
  • Hỗ trợ DI sử dụng cú pháp @inject
  • Hỗ trợ các đối tượng ViewBag và ViewData.
  • Hỗ trợ Layout view (tham khảo: https://learn.microsoft.com/en-us/aspnet/core/mvc/views/layout?view=aspnetcore-7.0)

Các bước thực thi về cơ bản sẽ như sau:

  • Mvc middleware dịch mã razor thành một file C#.
  • Dùng Roslyn để dịch thành một Assembly.
  • Load assembly vào bộ nhớ và khởi tạo một object.
  • Gọi hàm InvokeAsync trên object đó.
  • Lấy kết quả trả về và tạo một ViewResultStreamContent.
  • Đưa content object vào response, đặt HTTP phù hợp (200 OK) và trả về cho Mini-Web-Server.

daohainam avatar Oct 19 '23 07:10 daohainam

File minirazor chúng ta cần dịch sang C# sẽ tương tự như sau:

@model RazorTest.Model.TestModel
@using RazorTest.Utils
@inject RazorTest.TimeService TimeService

<html>
<head>
	<title>
		Mini Razor Test 1
	</title>
</head>
Hello Mini Razor @(" world")!

@{
	int second = DateTime.Now.Second;
	int s100 = 100 * second;
}

<b>100 * @(second) = @(s100.ToString())</b>

Model.TotalValue = @(RazorTestUtils.ToMoneyString(@(Model.TotalValue)))

</html>

Sẽ được dịch ra dạng như sau:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using RazorTest.Utils;

public class MiniRazorView__[x]: MiniRazorView // [x] is a string identifying which view
{
	private readonly RazorTest.Model.TestModel __model;
	private Model => __model;

	private readonly RazorTest.TimeService TimeService;

	public MiniRazorView__[x] (IServiceProvider serviceProvider, RazorTest.Model.TestModel model) {
		__model = model;

		TimeService = serviceProvider.GetRequiredService<RazorTest.TimeService>();
	}

	public override void GenerateContent(StringBuilder sb)
	{
		sb.Append(@"
<html>
<head>
	<title>
	    Mini Razor Test 1
	</title>
</head>
Hello Mini Razor ");
		sb.Append(" world");
		sb.Append(@"!
");

		int second = TimeService.GetNow().Second;
		int s100 = 100 * second;
		sb.Append(@"
<b> 100 * "); sb.Append(second); sb.Append(@" = "); sb.Append(s100.ToString()); sb.Append(@"</b>

Model.TotalValue = "); sb.Append(RazorTestUtils.ToMoneyString(@(Model.TotalValue)));
		sb.Append(@"
</html>");
	}
}

daohainam avatar Oct 24 '23 08:10 daohainam

MiniRazorView needs some IMiniAppContext components, so you can access them from your script:

private readonly IMiniAppContext __context;

public MiniRazorView__[x] (IMiniAppContext context, IServiceProvider serviceProvider, RazorTest.Model.TestModel model) {
                __context = context;
		__model = model;

		TimeService = serviceProvider.GetRequiredService<RazorTest.TimeService>();
	}

protected IHttpRequest Request => context.Request;
protected IHttpResponse Response => context.Response;
protected ISession Session => context.Session;
protected ClaimsPrincipal? User => context.User;

daohainam avatar Oct 25 '23 06:10 daohainam

we should also support comments using @* *@

daohainam avatar Oct 25 '23 07:10 daohainam