diff --git a/blazor-toc.html b/blazor-toc.html index c4e0620f24..03a3368071 100644 --- a/blazor-toc.html +++ b/blazor-toc.html @@ -5447,6 +5447,9 @@
  • Windows Forms to Blazor
  • +
  • + ASP.NET Core MVC to Blazor +
  • Blazor Web App to MAUI Blazor Hybrid App
  • diff --git a/blazor/common/migration/core-mvc-to-blazor.md b/blazor/common/migration/core-mvc-to-blazor.md new file mode 100644 index 0000000000..420d2ef83f --- /dev/null +++ b/blazor/common/migration/core-mvc-to-blazor.md @@ -0,0 +1,582 @@ +--- +layout: post +title: Migrating ASP.NET Core MVC to Blazor | Syncfusion +description: Learn how to migrate ASP.NET Core MVC controls to Blazor components, including key concepts and a detailed migration approach. +platform: Blazor +control: Common +documentation: ug +--- + +# Migrating ASP.NET Core MVC Controls to Blazor + +Migrating enterprise applications from [ASP.NET Core MVC](https://learn.microsoft.com/en-us/aspnet/core/mvc/overview?view=aspnetcore-10.0) to [Blazor](https://learn.microsoft.com/en-us/aspnet/core/blazor/?view=aspnetcore-10.0) represents a transition from a controller driven, request response framework to a modern, component based web UI model built on .NET. This guide provides a **structured, step-by-step migration path** for [ASP.NET Core MVC controls](https://www.syncfusion.com/aspnet-mvc-ui-controls) to their [Blazor equivalents](https://www.syncfusion.com/blazor-components). + +## Why migrate from ASP.NET Core MVC to Blazor? + +ASP.NET Core MVC applications follow a **request response** model, where user requests are handled by controllers and rendered using views. UI updates often require full page reloads or additional techniques such as **partial views** or **AJAX**, which can increase complexity as applications become more interactive. + +Blazor introduces a **component based**, **event-driven UI model**, where user interactions trigger updates directly within components rather than full page reloads. It enables reusable UI components and aligns closely with modern .NET development practices. + +| Aspect | ASP.NET Core MVC | Blazor | +| --- | --- | --- | +| Execution model | Stateless request response | Blazor Web App (Server / WebAssembly / Auto render modes) | +| UI technology | Razor Views (`.cshtml`) with HTML and Tag Helpers | Razor components (`.razor`) with HTML and C# | +| UI definition | Views and partial views | Component based UI structure | +| Code structure | Controllers and ViewModels | `@code {}` block or `.razor.cs` file | +| Lifecycle model | Request based (per HTTP request) | Component lifecycle (`OnInitialized`, `OnParametersSet`, `OnAfterRender`, `Dispose`) | +| State management | stateless and session based options | Component state, cascading parameters, and DI services | +| User interaction | Full page reload or AJAX callback | Event driven UI updates | +| Event handling | Form post and AJAX | `EventCallback` and delegates | +| Dependency injection | Built-in (controller centric) | Built-in (component centric) | +| Routing and navigation | Controller based routing | SPA style routing using `@page` | +| Scalability | Limited by concurrent requests and vertical scaling typical | Server: scales to concurrent SignalR connections. WebAssembly: client-side execution eliminates server load | +| Application updates | Requires redeployment | Blazor Server: Instant updates. WebAssembly: Requires refresh | + +## Development Environment Setup + +### Prerequisites + +* [.NET 8 SDK or later](https://dotnet.microsoft.com/en-us/download/dotnet) +* [Visual Studio](https://visualstudio.microsoft.com/downloads/) 2022 or later, or [Visual Studio Code](https://code.visualstudio.com/) with [C# Dev Kit](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit) extension + +Verify installation using the following .NET CLI command, and ensure the .NET version is 8.0.0 or later. + +{% tabs %} +{% highlight bash tabtitle=".NET CLI" %} + +dotnet --version +dotnet --info + +{% endhighlight %} +{% endtabs %} + +### Project structure comparison + +The following table maps common **ASP.NET Core MVC application artifacts** to their **Blazor equivalents**, highlighting how application structure transitions from a request driven model to a component based architecture. + +| Concept | ASP.NET Core MVC artifact | Blazor equivalent | +| -----| ------ | ----- | +| UI definition | Razor Views (`Views/*.cshtml`) | Razor components (`Pages/*.razor`) | +| Request handling logic | `Controllers/*.cs` | Component code (`@code {}` or `.razor.cs`) | +| Application startup | `Program.cs` (MVC middleware) | `Program.cs` (Blazor hosting & services) | +| Layout | `_Layout.cshtml` | `MainLayout.razor` | +| Reusable UI | Partial Views | Razor components | +| Static assets | `wwwroot` | `wwwroot` | +| State handling | TempData / ViewData / Session | Component state, cascading values, DI services | +| Routing | `MapControllerRoute`, attributes | `@page` directive | +| Business & data layer | Models, Services, Repositories | Reused via dependency injection | + +N> Existing domain models, data access layers, and business services can typically be reused in Blazor applications. However, code tightly coupled to MVC features such as controllers, HttpContext, or TempData. + +## Creating a Blazor project + +### Creating a Blazor Web App with Interactive Server + +For ASP.NET Core MVC migrations, create a **Blazor Web App with Interactive Server** option, which runs server-side and preserves the familiar server hosted execution model with real time interactivity via SignalR. + +{% tabs %} +{% highlight bash tabtitle=".NET CLI" %} + +dotnet new blazor -n MyBlazorApp --interactivity Server +cd MyBlazorApp + +{% endhighlight %} +{% endtabs %} + +N> The `--interactivity Server` flag configures SignalR based interactivity providing immediate UI updates. + +## Migrating Components from ASP.NET Core MVC to Blazor + +The following shared setup applies to all components and covers the common configuration required before proceeding to the [component specific migration steps](#add-syncfusion-datagrid-component). + +### Package installation + +In ASP.NET Core MVC, controls are typically installed using a single combined package, such as [Syncfusion.EJ2.AspNet.Core](https://www.nuget.org/packages/Syncfusion.EJ2.AspNet.Core). + +In Blazor applications, components are available as individual NuGet packages as well as a complete package [Syncfusion.Blazor](https://www.nuget.org/packages/Syncfusion.Blazor). The individual packages are organized based on component usage and namespace, allowing you to install only the components required for your application. The combined `Syncfusion.Blazor` package is also available and continues to be supported (not deprecated). However, for better performance and optimized application size, it is recommended to use individual component packages whenever possible. + +To explore the complete list of Blazor component packages, refer to [Blazor NuGet packages](https://blazor.syncfusion.com/documentation/nuget-packages). + +Additionally, install the following package for styling support [Syncfusion.Blazor.Themes](https://www.nuget.org/packages/Syncfusion.Blazor.Themes). + +N> Install `Syncfusion.Blazor.Themes` once at the application level. This package is required for the Blazor components used in this migration guide. + +### Service registration + +In ASP.NET Core MVC, UI components are rendered as part of the view, and additional scripts and styles are included manually. There is no DI-based registration model specifically for UI components. + +In Blazor, components rely on the built-in dependency injection (DI) system. UI libraries like Syncfusion must be registered in the service container so that required services (such as rendering, localization, and JavaScript interop) are available to components. + +In the `Program.cs` file, add the Blazor namespace and register services. + +{% tabs %} +{% highlight c# tabtitle="Program.cs" %} + +using Syncfusion.Blazor; +... +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddRazorComponents() + .AddInteractiveServerComponents(); +builder.Services.AddSyncfusionBlazor(); // Register Syncfusion services +var app = builder.Build(); +... + +{% endhighlight %} +{% endtabs %} + +### Add import namespaces + +In ASP.NET Core MVC, namespaces are imported into Razor views using `~/_ViewImports.cshtml`, primarily to enable Tag Helpers and HTML helper extensions. + +Add the required namespace in `~/_ViewImports.cshtml`. + +{% tabs %} +{% highlight cshtml tabtitle="~/_ViewImports.cshtml" %} + +@using WebApplication1 +@using WebApplication1.Models +@using Syncfusion.EJ2 +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers + +{% endhighlight %} +{% endtabs %} + +In Blazor, `~/_Imports.razor` serves a similar purpose but applies to Razor components. It allows components to access namespaces globally without requiring repeated `@using` statements in each `.razor` file. + +Import the required required namespaces in the `~/_Imports.razor` file. + +| Component | Required namespaces | +|---|---| +| DataGrid | `@using Syncfusion.Blazor`
    `@using Syncfusion.Blazor.Grids` | +| Scheduler | `@using Syncfusion.Blazor`
    `@using Syncfusion.Blazor.Schedule` | +| RichTextEditor | `@using Syncfusion.Blazor`
    `@using Syncfusion.Blazor.RichTextEditor` | + +### Theme and script configuration + +In ASP.NET Core MVC, scripts and styles are manually referenced in the shared layout (`_Layout.cshtml`). In addition, controls require the `@Html.EJS().ScriptManager()` helper, which initializes the required JavaScript controls at runtime. + +In Blazor, scripts and styles are included once at the application level (such as in `App.razor` file) and are served from static web assets. This approach ensures consistent styling and avoids duplicate references across pages. + +**ASP.NET Core MVC approach** + +{% tabs %} +{% highlight html tabtitle="_Layout.cshtml" %} + + + ... + + + + + + +{% endhighlight %} +{% endtabs %} + +Also, register the script manager `EJS().ScriptManager()` at the end of `` in the `~/Views/Shared/_Layout.cshtml` file as follows. + +{% tabs %} +{% highlight cshtml tabtitle="~/_Layout.cshtml" %} + + + ... + + @Html.EJS().ScriptManager() + + +{% endhighlight %} +{% endtabs %} + +**Blazor equivalent** + +{% tabs %} +{% highlight razor tabtitle="App.razor" %} + + + ... + + + ... + + + ... + + + ... + + +{% endhighlight %} +{% endtabs %} + +### Add DataGrid component + +For detailed explanation, refer to the [Blazor DataGrid getting started guide](https://blazor.syncfusion.com/documentation/datagrid/getting-started-with-server-app) and [ASP.NET Core MVC DataGrid getting started guide](https://ej2.syncfusion.com/aspnetmvc/documentation/grid/getting-started-mvc). + +| Aspect | MVC (`Grid` - ASP.NET Core wrappers) | Blazor (`SfGrid / SfGrid`) | +| -------- | --------- | ---------- | +| Package (NuGet) | [Syncfusion.EJ2.AspNet.Core](https://www.nuget.org/packages/Syncfusion.EJ2.AspNet.Core/) | [Syncfusion.Blazor.Grid](https://www.nuget.org/packages/Syncfusion.Blazor.Grid) | +| Namespace | Views: Tag Helpers / HTML Helpers (`@addTagHelper`, `@using`) | Razor: `@using Syncfusion.Blazor.Grids` | +| Component declaration | HTML Helper (`@Html.EJS().Grid()`) | Razor component (``) | +| Data binding | Model / ViewBag / DataManager | Bound to component property (`DataSource="@..."`) | +| Collection type | Server-side models (`IEnumerable`, ViewModel) | `List<>` / `IEnumerable<>` | +| Events & interactions | JavaScript based client events | `EventCallback` and async handlers | +| UI refresh | Client-side rendering | Automatic (component re-rendering) | +| Columns | Defined using (`.Columns(col => { ... })`) | `` | +| Editing & API | [EditSettings](https://help.syncfusion.com/cr/aspnetmvc-js2/Syncfusion.EJ2.Grids.Grid.html#Syncfusion_EJ2_Grids_Grid_EditSettings) | [EditSettings](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Grids.SfGrid-1.html#Syncfusion_Blazor_Grids_SfGrid_1_EditSettings), [GridEvents](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Grids.GridEvents-1.html), `@ref` async APIs | +| Theming & assets | Scripts and styles in `_Layout.cshtml` | Static web assets via `_content`, service registration (`AddSyncfusionBlazor`) | +| Paging / virtualization |[AllowPaging](https://help.syncfusion.com/cr/aspnetmvc-js2/Syncfusion.EJ2.Grids.Grid.html#Syncfusion_EJ2_Grids_Grid_AllowPaging), [PageSettings](https://help.syncfusion.com/cr/aspnetmvc-js2/Syncfusion.EJ2.Grids.Grid.html#Syncfusion_EJ2_Grids_Grid_PageSettings), [EnableVirtualization](https://help.syncfusion.com/cr/aspnetmvc-js2/Syncfusion.EJ2.Grids.Grid.html#Syncfusion_EJ2_Grids_Grid_EnableVirtualization) | [AllowPaging](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Grids.SfGrid-1.html#Syncfusion_Blazor_Grids_SfGrid_1_AllowPaging), [PageSettings](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Grids.SfGrid-1.html#Syncfusion_Blazor_Grids_SfGrid_1_PageSettings), [EnableVirtualization](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Grids.SfGrid-1.html#Syncfusion_Blazor_Grids_SfGrid_1_EnableVirtualization) | +| Filtering | [AllowFiltering](https://help.syncfusion.com/cr/aspnetmvc-js2/Syncfusion.EJ2.Grids.Grid.html#Syncfusion_EJ2_Grids_Grid_AllowFiltering) | [AllowFiltering](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Grids.SfGrid-1.html#Syncfusion_Blazor_Grids_SfGrid_1_AllowFiltering) | +| Grouping | [AllowGrouping](https://help.syncfusion.com/cr/aspnetmvc-js2/Syncfusion.EJ2.Grids.Grid.html#Syncfusion_EJ2_Grids_Grid_AllowGrouping), [GroupSettings](https://help.syncfusion.com/cr/aspnetmvc-js2/Syncfusion.EJ2.Grids.Grid.html#Syncfusion_EJ2_Grids_Grid_GroupSettings) | [AllowGrouping](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Grids.SfGrid-1.html#Syncfusion_Blazor_Grids_SfGrid_1_AllowGrouping), [GroupSettings](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Grids.SfGrid-1.html#Syncfusion_Blazor_Grids_SfGrid_1_GroupSettings) | +| Lifecycle & refs | Controller actions, model binding, HTTP lifecycle | `OnInitialized[Async]`, DI, `@ref`, component lifecycle | + +In ASP.NET Core MVC, the Grid is defined using HTML Helper APIs, where [Columns](https://help.syncfusion.com/cr/aspnetmvc-js2/Syncfusion.EJ2.Grids.Grid.html#Syncfusion_EJ2_Grids_Grid_Columns) configured through property during component initialization. + +In Blazor, the DataGrid component is defined in Razor markup, and its structure is built using declarative [Columns](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Grids.SfGrid-1.html#Syncfusion_Blazor_Grids_SfGrid_1_Columns) while binding to data through the [DataSource](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Grids.SfGrid-1.html#Syncfusion_Blazor_Grids_SfGrid_1_DataSource) property. + +**MVC approach** + +{% tabs %} +{% highlight cshtml %} + +@(Html.EJS().Grid("Grid").DataSource((IEnumerable)Model).Columns(col => +{ + col.Field("OrderID").HeaderText("Order ID").Width("120").TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Add(); + col.Field("CustomerID").HeaderText("Customer Name").Width("150").Add(); + col.Field("OrderDate").HeaderText("Order Date").Width("130").TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Format("yMd").Add(); + col.Field("ShipCountry").HeaderText("Ship Country").Width("120").Add(); +}).Render()) + +{% endhighlight %} + +{% highlight cs tabtitle="HomeController.cs" %} + +public class HomeController : Controller +{ + public ActionResult Index() + { + return View(OrdersDetails.GetAllRecords()); + } +} +public class OrdersDetails +{ + public static List order = new List(); + public OrdersDetails() + { + + } + public OrdersDetails(int OrderID, string CustomerId, int EmployeeId, double Freight, bool Verified, DateTime OrderDate, string ShipCity, string ShipName, string ShipCountry, DateTime ShippedDate, string ShipAddress) + { + this.OrderID = OrderID; + this.CustomerID = CustomerId; + this.EmployeeID = EmployeeId; + this.Freight = Freight; + this.ShipCity = ShipCity; + this.Verified = Verified; + this.OrderDate = OrderDate; + this.ShipName = ShipName; + this.ShipCountry = ShipCountry; + this.ShippedDate = ShippedDate; + this.ShipAddress = ShipAddress; + } + public static List GetAllRecords() + { + if (order.Count == 0) + { + int code = 10000; + for (int i = 1; i < 5; i++) + { + order.Add(new OrdersDetails(code + 1, "ALFKI", i + 0, 2.3 * i, false, new DateTime(1991, 05, 15), "Berlin", "Simons bistro", "Denmark", new DateTime(1996, 7, 16), "Kirchgasse 6")); + order.Add(new OrdersDetails(code + 2, "ANATR", i + 2, 3.3 * i, true, new DateTime(1990, 04, 04), "Madrid", "Queen Cozinha", "Brazil", new DateTime(1996, 9, 11), "Avda. Azteca 123")); + order.Add(new OrdersDetails(code + 3, "ANTON", i + 1, 4.3 * i, true, new DateTime(1957, 11, 30), "Cholchester", "Frankenversand", "Germany", new DateTime(1996, 10, 7), "Carrera 52 con Ave. Bolívar #65-98 Llano Largo")); + order.Add(new OrdersDetails(code + 4, "BLONP", i + 3, 5.3 * i, false, new DateTime(1930, 10, 22), "Marseille", "Ernst Handel", "Austria", new DateTime(1996, 12, 30), "Magazinweg 7")); + order.Add(new OrdersDetails(code + 5, "BOLID", i + 4, 6.3 * i, true, new DateTime(1953, 02, 18), "Tsawassen", "Hanari Carnes", "Switzerland", new DateTime(1997, 12, 3), "1029 - 12th Ave. S.")); + code += 5; + } + } + return order; + } + public int? OrderID { get; set; } + public string CustomerID { get; set; } + public int? EmployeeID { get; set; } + public double? Freight { get; set; } + public string ShipCity { get; set; } + public bool Verified { get; set; } + public DateTime OrderDate { get; set; } + public string ShipName { get; set; } + public string ShipCountry { get; set; } + public DateTime ShippedDate { get; set; } + public string ShipAddress { get; set; } +} + +{% endhighlight %} + +{% endtabs %} + +**Blazor equivalent** + +{% tabs %} +{% highlight razor tabtitle="Home.razor" %} + +@page "/grid" +@using Syncfusion.Blazor.Grids +@rendermode InteractiveServer + + + + + + + + + + +@code { + private List orderData = new(); + + protected override void OnInitialized() + { + orderData = OrdersDetails.GetAllRecords(); + } + public class OrdersDetails + { + public static List order = new List(); + + public static List GetAllRecords() + { + if (order.Count == 0) + { + int code = 10000; + for (int i = 1; i < 5; i++) + { + order.Add(new OrdersDetails(code + 1, "ALFKI", i + 0, 2.3 * i, false, new DateTime(1991, 05, 15), "Berlin", "Simons bistro", "Denmark", new DateTime(1996, 7, 16), "Kirchgasse 6")); + order.Add(new OrdersDetails(code + 2, "ANATR", i + 2, 3.3 * i, true, new DateTime(1990, 04, 04), "Madrid", "Queen Cozinha", "Brazil", new DateTime(1996, 9, 11), "Avda. Azteca 123")); + order.Add(new OrdersDetails(code + 3, "ANTON", i + 1, 4.3 * i, true, new DateTime(1957, 11, 30), "Cholchester", "Frankenversand", "Germany", new DateTime(1996, 10, 7), "Carrera 52 con Ave. Bolívar #65-98 Llano Largo")); + order.Add(new OrdersDetails(code + 4, "BLONP", i + 3, 5.3 * i, false, new DateTime(1930, 10, 22), "Marseille", "Ernst Handel", "Austria", new DateTime(1996, 12, 30), "Magazinweg 7")); + order.Add(new OrdersDetails(code + 5, "BOLID", i + 4, 6.3 * i, true, new DateTime(1953, 02, 18), "Tsawassen", "Hanari Carnes", "Switzerland", new DateTime(1997, 12, 3), "1029 - 12th Ave. S.")); + code += 5; + } + } + return order; + } + public int? OrderID { get; set; } + public string? CustomerID { get; set; } + public int? EmployeeID { get; set; } + public double? Freight { get; set; } + public string? ShipCity { get; set; } + public bool Verified { get; set; } + public DateTime OrderDate { get; set; } + public string? ShipName { get; set; } + public string? ShipCountry { get; set; } + public DateTime ShippedDate { get; set; } + public string? ShipAddress { get; set; } + } +} + +{% endhighlight %} +{% endtabs %} + +### Add Scheduler component + +For detailed explanation, refer to the [Blazor Scheduler getting started guide](https://blazor.syncfusion.com/documentation/scheduler/getting-started-with-server-app) and [ASP.NET Core MVC Scheduler getting started guide](https://ej2.syncfusion.com/aspnetmvc/documentation/schedule/getting-started). + +| Aspect | MVC (`Schedule` – ASP.NET Core wrappers) | Blazor (`SfSchedule`) | +| ---- | ----- | ---- | +| Package (NuGet) | [Syncfusion.EJ2.AspNet.Core](https://www.nuget.org/packages/Syncfusion.EJ2.AspNet.Core) | [Syncfusion.Blazor.Schedule](https://www.nuget.org/packages/Syncfusion.Blazor.Schedule) | +| Namespace | Views: `@using Syncfusion.EJ2` | Razor: `@using Syncfusion.Blazor.Schedule` | +| Component declaration | HTML Helper (`@Html.EJS().Schedule()`) | Razor component (``) | +| Appointment model | [EventSettings](https://help.syncfusion.com/cr/aspnetmvc-js2/Syncfusion.EJ2.Schedule.Schedule.html#Syncfusion_EJ2_Schedule_Schedule_EventSettings) | [ScheduleEventSettings](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Schedule.ScheduleEventSettings-1.html) | +| Views configuration | [CurrentView](https://help.syncfusion.com/cr/aspnetmvc-js2/Syncfusion.EJ2.Schedule.Schedule.html#Syncfusion_EJ2_Schedule_Schedule_CurrentView), [Views](https://help.syncfusion.com/cr/aspnetmvc-js2/Syncfusion.EJ2.Schedule.Schedule.html#Syncfusion_EJ2_Schedule_Schedule_Views) | [``](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Schedule.ScheduleView.html) collection | +| Events & interactions | Client-side events with optional server calls (AJAX) | `EventCallback` and component events | +| State management | Stateless (per request) | Stateful component instance | +| UI refresh | AJAX refresh or full reload | Automatic component re-rendering | +| Theming & assets | CSS/JS + `ScriptManager` in `_Layout.cshtml` | Static assets via `_content`, service registration (`AddSyncfusionBlazor`) | +| Lifecycle & refs | Controller lifecycle, HTTP requests | `OnInitialized[Async]`, DI, `@ref` APIs | + +In ASP.NET Core MVC, the Scheduler is configured with [Views](https://help.syncfusion.com/cr/aspnetmvc-js2/Syncfusion.EJ2.Schedule.Schedule.html#Syncfusion_EJ2_Schedule_Schedule_Views) options such as Day, Week, and Month, and [EventSettings](https://help.syncfusion.com/cr/aspnetmvc-js2/Syncfusion.EJ2.Schedule.Schedule.html#Syncfusion_EJ2_Schedule_Schedule_EventSettings) are applied to control how appointments are displayed and managed. + +In Blazor, the Scheduler component defines views using the [ScheduleViews](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Schedule.ScheduleViews.html) collection and binds event data through [ScheduleEventSettings](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Schedule.ScheduleEventSettings-1.html) to handle appointments within the component. + +**ASP.NET Core MVC approach** + +{% tabs %} +{% highlight cshtml tabtitle="Index.cshtml" %} + +@using Syncfusion.EJ2 + +
    + @(Html.EJS().Schedule("Schedule") + .Height("650px") + .CurrentView(Syncfusion.EJ2.Schedule.View.Week) + .EventSettings(e => e.DataSource(ViewBag.Meeting)) + .Render()) +
    + +{% endhighlight %} + +{% highlight c# tabtitle="HomeController.cs" %} + +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; + +public class HomeController : Controller +{ + public IActionResult Index() + { + ViewBag.Meeting = new List + { + new Meeting + { + Id = 1, + Subject = "Meeting", + StartTime = DateTime.Now, + EndTime = DateTime.Now.AddHours(1) + } + }; + + return View(); + } +} + +public class Meeting +{ + public int Id { get; set; } + public string Subject { get; set; } + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } +} + +{% endhighlight %} +{% endtabs %} + +**Blazor equivalent** + +{% tabs %} +{% highlight razor tabtitle="Home.razor" %} + +@page "/schedule" + +@using Syncfusion.Blazor.Schedule +@rendermode InteractiveServer + + + + + + + + + + + +@code { + private List Meetings = new() + { + new Meeting + { + Id = 1, + Subject = "Meeting", + StartTime = DateTime.Now, + EndTime = DateTime.Now.AddHours(1) + } + }; + + public class Meeting + { + public int Id { get; set; } + public string? Subject { get; set; } + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } + } +} + +{% endhighlight %} +{% endtabs %} + +N> The `Meeting` class uses the default property names expected by the Scheduler. If your data uses different field names, you can map them using the `Fields` property in `ScheduleEventSettings`. + +### Add Rich Text Editor component + +For detailed explanation, refer to the [Blazor Rich Text Editor getting started guide](https://blazor.syncfusion.com/documentation/rich-text-editor/getting-started-with-server-app) and [ASP.NET Core MVC Rich Text Editor getting started guide](https://ej2.syncfusion.com/aspnetmvc/documentation/rich-text-editor/getting-started). + +| Aspect | MVC (`RichTextEditor` – ASP.NET Core wrappers) | Blazor (`SfRichTextEditor`) | +| ---------- | ------ | --------- | +| Package (NuGet) | [Syncfusion.EJ2.AspNet.Core](https://www.nuget.org/packages/Syncfusion.EJ2.AspNet.Core) | [Syncfusion.Blazor.RichTextEditor](https://www.nuget.org/packages/Syncfusion.Blazor.RichTextEditor) | +| Namespace | Views: `@using Syncfusion.EJ2` | Razor: `@using Syncfusion.Blazor.RichTextEditor` | +| Component declaration | HTML Helper (`@Html.EJS().RichTextEditor()`) | Razor component (``) | +| Content binding | Model, ViewBag, or form post (`Value`) | `Value` / `@bind-Value` bound to component state | +| Toolbar configuration | [ToolbarSettings](https://help.syncfusion.com/cr/aspnetmvc-js2/Syncfusion.EJ2.RichTextEditor.RichTextEditor.html#Syncfusion_EJ2_RichTextEditor_RichTextEditor_ToolbarSettings) | [``](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.RichTextEditor.RichTextEditorToolbarSettings.html) with predefined/custom items | +| Events & interactions | Form post or AJAX callbacks | `EventCallback<>` and component events | +| State management | Stateless (per request) | Stateful component instance | +| Theming & assets | CSS/JS + `ScriptManager` in `_Layout.cshtml` | Static assets via `_content`, service registration (`AddSyncfusionBlazor`) | +| Lifecycle & refs | Controller lifecycle, HTTP requests | `OnInitialized[Async]`, DI, `@ref` APIs | + +In ASP.NET Core MVC, the editor is initialized with configurable toolbar settings and supports content formatting through predefined tools and customization options. + +In Blazor, the Rich Text Editor component is defined in Razor markup, where content is managed using the Value or @bind-Value property and toolbar items can be customized declaratively. + +**ASP.NET Core MVC approach** + +{% tabs %} +{% highlight cshtml %} + +@using Syncfusion.EJ2 + +@Html.EJS().RichTextEditor("editor").Value(ViewBag.Value).Render() + +{% endhighlight %} + +{% highlight c# tabtitle="HomeController.cs" %} + +using Microsoft.AspNetCore.Mvc; + +public class HomeController : Controller +{ + public ActionResult Index() + { + ViewBag.Value = @"

    Welcome to Blazor Rich Text Editor

    "; + return View(); + } +} + +{% endhighlight %} +{% endtabs %} + +**Blazor equivalent** + +{% tabs %} +{% highlight razor tabtitle="Home.razor" %} + +@page "/rte" +@using Syncfusion.Blazor.RichTextEditor +@rendermode InteractiveServer + + + +@code { + private string Content = "

    Welcome to Blazor Rich Text Editor

    "; +} + +{% endhighlight %} +{% endtabs %} + +## Run the application + +Press Ctrl+F5 (Windows) or +F5 (macOS) to launch the application. + +Alternatively, run the application using the following .NET CLI command from the project root directory. + +{% tabs %} +{% highlight bash tabtitle=".NET CLI" %} + +dotnet run + +{% endhighlight %} +{% endtabs %} + +## See also + +* [Getting started with Blazor Server App](https://blazor.syncfusion.com/documentation/getting-started/blazor-server-side-visual-studio) +* [Getting started with Blazor DataGrid](https://blazor.syncfusion.com/documentation/datagrid/getting-started-with-server-app) +* [Getting started with Blazor Scheduler](https://blazor.syncfusion.com/documentation/scheduler/getting-started-with-server-app) +* [Getting started with Blazor Rich Text Editor](https://blazor.syncfusion.com/documentation/rich-text-editor/getting-started-with-server-app)