재우니의 블로그

ASP.NET CORE 6.0 - Single ASP.NET Core Application 에서 MVC, Razor Pages, Blazor, API Controllers, Minimal APIs 전부 사용해 보기

 

[번역본]

 

출처 : http://www.binaryintellect.net/articles/55355722-96b6-4bbc-a110-999e5e61235e.aspx

 

몇 년 전 ASP.NET Core 2.0 MVC, Razor Pages 및 Web API가 단일 웹 애플리케이션에서 공존할 수 있는 방법을 설명하는 기사를 작성했습니다 . 그 이후로 ASP.NET Core는 제품군에 몇 가지 새로운 구성원을 추가했습니다. 이제 단일 프로젝트에서 ASP.NET Core 6.0 MVC, Razor Pages, Blazor Server, API 컨트롤러 및 minimal  API를 함께 사용하는 유사한 웹 애플리케이션을 다시 빌드해야 합니다. 

 

일반적으로 개발자는 MVC 또는 Blazor와 같은 특정 프로젝트 템플릿을 기반으로 새 ASP.NET Core 프로젝트를 만듭니다. 그러나 단일 개발 옵션으로 제한되지 않습니다. ASP.NET Core는 여러 개발 옵션을 제공하며 요구 사항에 따라 단일 프로젝트에서 이를 활용할 수 있습니다.

 

이 연습에서는 빈 프로젝트로 시작하여 MVC, Razor Pages, Blazor Server, API 컨트롤러 및 minimal API를 하나씩 추가합니다. 이렇게 하면 어떤 구성이 필요한지, 이러한 상황에서 다양한 파일이 구성되는 방식을 이해하는 데 도움이 됩니다.

빈 프로젝트 템플릿을 기반으로 AspNetCoreAllInOne 이라는 ASP.NET Core 를 만들어 시작하겠습니다.

 

 

솔루션 탐색기에서 새로 생성된 프로젝트는 아래와 같습니다

ASP.NET Core MVC 추가하기

 

먼저 프로젝트에 MVC를 추가합니다. 따라서 Program.cs 파일을 열고 다음 코드를 추가합니다

var builder = WebApplication.CreateBuilder(args);

//추가
builder.Services.AddControllersWithViews();

var app = builder.Build();

//추가 3개
app.UseStaticFiles();
app.UseRouting();
app.MapDefaultControllerRoute();

app.Run();

 

AddControllersWithViews()를 호출하여 DI 컨테이너에 MVC 서비스를 등록합니다. 

UseStaticFiles() 호출은 지원하는 정적 파일(이미지, JS 파일 등)을 앱에 추가합니다. 
UseRouting() 및 MapDefaultControllerRoute() 메서드는 앱에서 사용하는 MVC 라우팅을 처리합니다. 이 예에서는 경로에 대해 기본 /controller/action/id 패턴을 사용할 것이므로 다른 경로 패턴을 지정하지 않았습니다.

 

이제 Models, Views, Controllers 및 wwwroot라는 4개의 폴더를 프로젝트에 추가합니다.
그런 다음 New Item 추가 대화 상자를 사용하여 Models 폴더에 AppModel 이라는 새 클래스를 추가합니다.

 

 

 

AppModel.cs 파일에 다음 코드를 작성합니다.

namespace AspNetCoreAllInOne.Models
{
    public class AppModel
    {
        public string Message { get; set; }
    }
}

 

AppModel 클래스에는 Message라는 속성이 하나만 있습니다.

그런 다음 HomeController 라는 새 컨트롤러 클래스를 Controllers 폴더에 추가합니다.

 

 

HomeController 클래스에 다음 코드를 작성합니다

using Microsoft.AspNetCore.Mvc;
using AspNetCoreAllInOne.Models;


namespace AspNetCoreAllInOne.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            AppModel data = new AppModel()
            { 
                Message = "Hello World!" 
            };
            return View(data);
        }
    }
}

 

HomeController 클래스에는 Index() action 이 포함되어 있습니다. Index() action 은 AppModel 개체를 만들고 해당 Message 속성을 Hello World! 로 설정합니다. 그리고 해당 model object 를 Index view 에 전달합니다.

Create Views > Home folder 를 만들고 그 안에 Index.cshtml 이라는 새 Razor view 파일을 추가합니다. 

 

 

 

Index.cshtml 파일에 다음 코드를 작성합니다.

@model AspNetCoreAllInOne.AppModel

<h1>@Model.Message</h1>

 

여기서 우리는 단순히 브라우저에서 Message 속성을 출력합니다.

wwwroot 폴더에 Default.html이라는 새 HTML 페이지를 추가합니다. 이 예제의 뒷부분에서 이 페이지를 사용합니다. 당분간은 그냥 비워두세요.

이 단계에서 프로젝트는 다음과 같습니다.

 

 

 

응용 프로그램을 실행하면 다음과 같은 출력이 표시됩니다.

 

ASP.NET Core Razor Pages 추가하기

 

이제 MVC가 프로젝트에 추가되었으므로 Razor Pages를 추가해 보겠습니다.

Program.cs 파일을 다시 열고 다음 코드를 추가합니다.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();

//추가
builder.Services.AddRazorPages();

var app = builder.Build();

app.UseStaticFiles();
app.UseRouting();
app.MapDefaultControllerRoute();

//추가
app.MapRazorPages();

app.Run();

 

Razor Pages를 지원하기 위해 AddRazorPages() 및 MapRazorPages()라는 두 가지 호출을 더 추가했습니다.

그런 다음 프로젝트 루트 아래에 Pages 폴더를 추가합니다. 그리고 Index.cshtml 이라는 새 Razor 페이지를 추가합니다.

 

 

Index.cshtml.cs 의 page model class 를 열고 다음 코드를 추가합니다.

public class IndexModel : PageModel
{
    public AppModel Data = new AppModel();

    public void OnGet()
    {
        Data.Message = "Hello Galaxy!";
    }
}

 

AppModel 의 개체를 만들고 OnGet() page handler 에서 Message 속성을 Hello Galaxy로 설정합니다! .

그런 다음 Index.cshtml 페이지를 열고 아래와 같이 Message 속성을 출력합니다.

@page
@model AspNetCoreAllInOne.Pages.IndexModel

<h1>@Model.Data.Message</h1>

 

애플리케이션을 실행하면 다음과 같은 출력이 표시됩니다. 

 

 

 

Razor Pages 를 추가한 후 웹 응용 프로그램의 기본 페이지가 /Home/Index(MVC 기본값)에서 /Index(Razor Pages 기본값)로 변경되었습니다. 물론 원하는 URL로 수동으로 이동하고 필요에 따라 MVC 또는 Razor Pages 를 호출할 수 있습니다.

 

 

Blazor Server 추가하기

 

Blazor 서버를 추가하는 것은 MVC 및 Razor Page를 추가하는 것보다 약간 더 복잡합니다. 계속해서 그렇게 합시다.

Program.cs 파일을 열고 다음 코드를 추가합니다.

 

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();

//추가
builder.Services.AddServerSideBlazor();

var app = builder.Build();

app.UseStaticFiles();
app.UseRouting();

app.MapDefaultControllerRoute();
app.MapRazorPages();

//아래 2개 추가
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

 

 

먼저 AddServerSideBlazor()를 호출하여 Blazor 서버 서비스를 등록합니다. 그런 다음 MapBlazorHub() 및 MapFallbackToPage() 메서드를 사용하여 Blazor 및 fallback page 를 설정합니다.

다음으로 프로젝트의 root 폴더에 Blazor의 root component 인 App.razor 를 추가합니다.

 

 

 

 

root 폴더에 새로 생성한 App.razor 의 코드는 다음과 같습니다.

@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web

<Router AppAssembly="@typeof(App).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" />
    </Found>
    <NotFound>
        <PageTitle>Not found</PageTitle>
        <LayoutView>
            <p>Sorry, there's 
nothing at this address.</p>
            <a href="/Default.html">Go to Default page</a>
        </LayoutView>
    </NotFound>
</Router>

 

여기서는 기본적으로 Blazor의 router 를 설정합니다. router 가 URL을 찾을 수 없으면 오류 메시지가 표시되고 사용자가 Default.html 페이지로 이동할 수 있습니다(이 예제의 앞부분에서 MVC를 구성하는 동안 Default.html 페이지를 추가했습니다).

 

App.razor component  는 _Host.cshtml 파일에서 로드됩니다. 따라서 Pages 폴더에 _Host.cshtml 이라는 새 Razor View 파일을 추가합니다.

 

_Host.cshtml 파일에 다음 코드를 추가합니다.

 

@page

@using Microsoft.AspNetCore.Components.Web
@using AspNetCoreAllInOne
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, 
initial-scale=1.0" />
    <base href="~/" />
    <component type="typeof(HeadOutlet)" 
render-mode="ServerPrerendered" />
</head>
<body>
    <component type="typeof(App)" render-mode="ServerPrerendered" />
    <script src="_framework/blazor.server.js"></script>
</body>
</html>

 

<component> 구문을 사용하여 App.razor component 를 렌더링합니다. 또한 </body> 태그 바로 앞에 blazor.server.js에 대한 <script> 참조를 추가합니다.

다음으로 두 개의 간단한 Razor component 를 추가합니다. 먼저 프로젝트 root 아래에 Shared 라는 새 폴더를 만듭니다. 그리고 WelcomeMessage.razor 라는 새로운 razor component 를 추가합니다.

WelcomeMessage component 내부에 다음 코드를 작성합니다.

 

@code{

    [Parameter]
    public string Message { get; set; }

}

<h1>@Message</h1>

 

 

보시다시피 parent component 에서 message 를 지정하는 데 사용할 Message 매개 변수 속성이 있습니다. 지정된 메시지는 단순히 페이지에 출력됩니다.

WelcomeMessage.razor component 는 Index.razor component 에서 사용됩니다. 따라서 Pages 폴더에 Index.razor component  를 추가합니다. 이 예의 앞부분에서 Index Razor Page를 만드는 동안 이미 Pages 폴더를 추가했습니다.

Index.razor 파일에 다음 코드를 작성합니다.

 

@page "/"
@page "/IndexBlazor"
@using AspNetCoreAllInOne.Shared

<WelcomeMessage Message="Hello Universe!" /> 

We used the WelcomeMessage component and specify the Message to be Hello Universe!. Notice that we have also used @page directive to specify a route /IndexBlazor. This way the Index component can be accessed at /IndexBlazor. We already have Index.cshtml file in the Pages folder. Therefore, we can't assign /Index route to the newly added razor component.

These two components are shown in the Solution Explorer below:

 

WelcomeMessage component  를 사용하고 메시지를 Hello Universe!로 지정했습니다. @page 지시문을 사용하여 /IndexBlazor 경로를 지정했습니다. 이 방법으로 Index component 는 /IndexBlazor 에서 액세스할 수 있습니다. 

 

Pages 폴더에 이미 Index.cshtml 파일이 존재하므로 새로 추가된 razor component  에 /Index 경로를 사용할 수 없습니다.

 

이 두 component 는 아래 솔루션 탐색기에 표시됩니다.

 

 

애플리케이션을 실행하고 /IndexBlazor 로 이동합니다. 

이 단계에서 Razor Pages 기본 페이지가 브라우저에 표시됩니다. Blazor 앱을 기본 default 로 사용하려면 어떻게 해야 할까요? 그걸하자.

 

Index.cshtml 의 이름을 IndexRazorPages.cshtml로 바꿉니다. 그리고 아래와 같이 _Host.cshtml을 수정합니다.

 

@page "/"

@using Microsoft.AspNetCore.Components.Web
@using AspNetCoreAllInOne
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, 
initial-scale=1.0" />
    <base href="~/" />
    <component type="typeof(HeadOutlet)" 
render-mode="ServerPrerendered" />
</head>
<body>
    <component type="typeof(App)" render-mode="ServerPrerendered" />
    <script src="_framework/blazor.server.js"></script>
</body>
</html>

 

@page 지시문은 이제 경로를 /로 지정합니다. (@page "/")

이 변경을 수행한 후 앱을 실행하면 Index.razor component 의 출력이 직접 표시됩니다.

 

 

물론 /IndexBlazor를 사용하여 component 에 액세스할 수도 있습니다

 

API controller 추가하기

 

이제 프로젝트에 API 컨트롤러를 추가해 보겠습니다. Program.cs를 다시 열고 다음 코드 줄을 추가합니다.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();

//추가
builder.Services.AddControllers();

var app = builder.Build();
app.UseStaticFiles();
app.UseRouting();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

//추가
app.MapControllers();

app.Run();

 

AddControllers() 및 MapControllers() 를 호출하며, 이는 Web API 관련 기능을 처리합니다.

이제 Controllers 폴더에 ValuesController 라는 API 컨트롤러를 추가합니다.

 

 

ValuesController.cs 에 다음 코드를 작성합니다

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    [HttpGet]
    public IActionResult Get()
    {
        string[] data = new string[] {
            "Hello World!",
            "Hello Galaxy!",
            "Hello Universe!"
        };
        return Ok(data);
    }
}

 

 

예를 들어 ValuesController 에 하나의 action  만 추가했습니다. Get() 작업은 [HttpGet] 속성으로 표시되며 Hello World!, Hello Galaxy!, Hello Universe! 라는 세 가지 문자열 값의 배열을 반환합니다.

애플리케이션을 실행하고 /api/Values로 이동하여 Get() 작업을 호출합니다. 출력은 다음과 같습니다

 

 

예상대로 브라우저는 세 개의 문자열 요소가 있는 배열을 보여줍니다.

 

 

minimal API 추가하기

 

minimal  의 API를 추가하는 것은 매우 간단합니다. Program.cs 파일을 열고 app.Run() 바로 앞에 다음 MapGet() 호출을 추가합니다.

app.MapGet("/minimalapi/values", () =>
{
    string[] data = new string[] {
                "Hello World!",
                "Hello Galaxy!",
                "Hello Universe!"
            };
    return Results.Ok(data);
});

 

 

보시다시피 MapGet() 호출은 끝점 URL을 /minimalapi/values로 지정하고 핸들러 함수는 단순히 문자열 값의 배열을 반환합니다.

앱을 다시 실행하고 /minimalapi/values로 이동합니다. 출력은 다음과 같습니다.

 

 

보시다시피 출력은 API 컨트롤러와 동일하지만 다른 endpoint  (/minimalapi/values)을 사용하여 minimal  API를 호출했습니다.

 

Default.html page 사용하기

 

wwwroot 폴더에 Default.html 페이지를 추가했습니다. 지금까지 만든 모든 endpoint  에 대한 URL을 포함하는 데 사용하겠습니다. Default.html 을 열고 다음 코드를 추가합니다.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <h1>This is default page!</h1>

    <h3><a href="/Home/Index">
Go to ASP.NET Core MVC</a></h3>

    <h3><a href="/IndexRazorPages">
Go to ASP.NET Core Razor Pages</a></h3>

    <h3><a href="/IndexBlazor">
Go to ASP.NET Core Blazor</a></h3>

    <h3><a href="/Api/Values">
Go to ASP.NET Core API Controller</a></h3>

    <h3><a href="/MinimalApi/Values">
Go to ASP.NET Core Minimal API</a></h3>

</body>
</html>

 

이것은 하이퍼링크가 포함된 간단한 페이지이며 브라우저에서 다음과 같이 보입니다.

 

 

이제 Index.razor component 를 열고 다음과 같이 이를 제거 합니다.

@page "/"

 

삭제 후 Index.razor 는 더 이상 default component 가 아니며 앱을 실행한 후, 이 오류가 발생합니다.

 

 

Go to Default page 를 클릭하면 Default.html 페이지로 이동합니다.

link  를 클릭하고 올바른 출력을 얻는지 확인해 보세요.

 

 

 

AspNetCoreAllinOne.zip
0.01MB

 

번역 사이트 

 

http://www.binaryintellect.net/articles/55355722-96b6-4bbc-a110-999e5e61235e.aspx

 

Use MVC, Razor Pages, Blazor, API Controllers, and Minimal APIs in a single ASP.NET Core application | BinaryIntellect Knowledge

Usually developers create a new ASP.NET Core project based on a particular project template such as MVC or Blazor. But you are not restricted to a single development option. ASP.NET Core offers multiple development options and you can utilize them in a sin

www.binaryintellect.net