Blazor WebAssembly 환경으로 이미 개발된 서비스가 있는 경우 .Net MAUI 를 사용해서 모바일 및 더 많은 환경을 지원하기 위해 추가 개발을 하는 경우
이미 작성된 razor 페이지 또는 라이브러리를 재활용하기 위한 샘플 소스를 만들어 보겠습니다.
참고로 Visual studio 2022 가 7.3 버전부터 MAUI 를 공식 지원하게 되면서 해당 버전 이후로 업데이트를 하게 되면 Preview 버전을 굳이 설치하지 않아도 된다고 합니다.
1부 – https://blog.kkomzi.net/26405
새 솔루션과 Blazor WebAssembly 형식의 프로젝트를 생성한 다음 기본 템플릿을 그대로 사용합니다.
RCL(Razor class library) 프로젝트를 추가한 다음 공유할 항목들을 RCL 프로젝트로 이동해서 참조하게 수정합니다.
.Net MAUI Blazor 프로젝트를 추가한 다음 RCL 프로젝트를 참조해서 동일한 UI 를 구성해 보겠습니다.
.Net MAUI Blazor 프로젝트 추가
MauiAppBlazor 프로젝트를 다시 빌드 하신 다음 Windows Machine 플랫폼으로 실행해 보면 다음과 같이 Blazor WebAssembly 의 기본 템플릿과 동일한 UI 로 실행이 됩니다.
MauiAppBlazor 프로젝트에서 RCL 프로젝트의 페이지를 참조하게 수정
MauiAppBlazor 프로젝트에서 불필요한 항목들을 삭제합니다.
MauiAppBlazor 프로젝트에서 Data, Pages, Shared 폴더를 삭제합니다.
MauiAppBlazor 프로젝트에서 wwwroot 폴더 하위의 항목 중에서 index.html 을 제외하고 모두 삭제합니다.
MauiAppBlazor 프로젝트에 RCL 프로젝트를 프로젝트 참조로 추가합니다.
그러면 다음과 같이 플랫폼 별로 프로젝트 참조가 추가된 것을 확인하실 수 있습니다.
MauiAppBlazor 프로젝트의 _Imports.razor 파일을 수정합니다.
@using System.Net.Http
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using MauiAppBlazor
@using RazorClassLibrary.Shared
MauiAppBlazor 프로젝트의 Main.razor 파일을 수정합니다.
AdditionalAssemblies=”new[] { typeof(MainLayout).Assembly}” 항목을 추가하였습니다
<Router AppAssembly="@typeof(Main).Assembly" AdditionalAssemblies="new[] { typeof(MainLayout).Assembly}">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
MauiAppBlazor 프로젝트의 index.html 파일을 수정합니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
<title>MauiAppBlazor</title>
<base href="/" />
<link rel="icon" type="image/x-icon" href="_content/RazorClassLibrary/favicon.ico">
<link href="_content/RazorClassLibrary/css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="_content/RazorClassLibrary/css/app.css" rel="stylesheet" />
<link href="MauiAppBlazor.styles.css" rel="stylesheet" />
</head>
<body>
<div class="status-bar-safe-area"></div>
<div id="app">Loading...</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.webview.js" autostart="false"></script>
</body>
</html>
WeatherForecastService 서비스 추가
FetchData 페이지에서 데이터를 조회하는 로직을 별도 서비스를 추가해서 공용으로 사용해 보겠습니다.
RCL 프로젝트에 Services 폴더를 생성 후 WeatherForecastService 를 추가합니다.
using BlazorWasm.Shared;
namespace RazorClassLibrary.Services
{
public class WeatherForecastService
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
public Task<WeatherForecast[]> GetForecastAsync(DateTime startDate)
{
return Task.FromResult(Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = startDate.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
}).ToArray());
}
}
}
MauiAppBlazor 프로젝트의 MauiProgram.cs 에서 서비스를 등록합니다.
using RazorClassLibrary.Services;
namespace MauiAppBlazor
{
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
});
builder.Services.AddMauiBlazorWebView();
#if DEBUG
builder.Services.AddBlazorWebViewDeveloperTools();
#endif
builder.Services.AddSingleton<WeatherForecastService>();
return builder.Build();
}
}
}
BlazorWasm.Client 프로젝트의 Program.cs 에서도 동일한 서비스를 등록합니다.
using BlazorWasm.Client;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using RazorClassLibrary.Services;
namespace BlazorWasm.Client
{
public class Program
{
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddSingleton<WeatherForecastService>();
await builder.Build().RunAsync();
}
}
}
RCL 프로젝트의 FetchData.razor 파일을 수정합니다.
@page "/fetchdata"
@inject WeatherForecastService WeatherForecast
@using RazorClassLibrary.Services
<PageTitle>Weather forecast</PageTitle>
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from the server.</p>
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
private WeatherForecast[]? forecasts;
protected override async Task OnInitializedAsync()
{
forecasts = await WeatherForecast.GetForecastAsync(DateTime.Now);
}
}
0 Comments