ASP.NET8 View Components Set Bar Baru untuk UI Web Reusability

oleh Mark Pelf23m2025/05/23
Read on Terminal Reader

Terlalu panjang; Untuk membaca

Cara mencipta ASP.NET8 View-Components, yang merupakan bentuk yang lebih berkuasa daripada seni bina komponen daripada Partial-Views yang popular.
featured image - ASP.NET8 View Components Set Bar Baru untuk UI Web Reusability
Mark Pelf HackerNoon profile picture
0-item

Cara mencipta ASP.NET8 View-Components, yang merupakan bentuk yang lebih berkuasa daripada seni bina komponen daripada Partial-Views yang popular.

Cara mencipta ASP.NET8 View-Components, yang merupakan bentuk yang lebih berkuasa daripada seni bina komponen daripada Partial-Views yang popular.

ASP.NET8 View-Components lebih berkuasa daripada Partial-Views

Sederhananya, ASP.NET8 View-Components serupa dengan Partial-Views, tetapi membolehkan tahap komponen dan fungsi yang lebih tinggi.

ASP.NET8 View-Components dimaksudkan untuk mencipta komponen yang boleh digunakan semula yang mempunyai fungsi View/Render, dan yang kerumitan yang lebih besar daripada Partial-Views biasa.

Kelebihan utama daripadaPerkhidmatan ASP.NETPenglihatan Bahagian ialah Penglihatan Bahagian mempunyaiBahagian komponen yang dijalankan oleh server-sidedan boleh mengakses semua mekanisme seni bina aplikasi, seperti Database Access Layer (contohnya EF) secara bebas daripada halaman tuan rumah di mana mereka dihoskan.

Bahagian komponen yang dijalankan oleh server-side

ASP.NET8 View-Components menerima parameter daripada kaedah panggilan (halaman tuan rumah atau bahkan kawalan secara langsung) dan bukan permintaan HTTP. Tetapi, tentu saja, tiada apa-apa yang menghalang penciptaan View-Components yang menerima HttpRequest sebagai parameter yang akan secara eksplisit dihantar kepada komponen.

Lihat komponen dalamPerkhidmatan ASP.NETAsas-asas telah ditakrifkan dengan baik dalam artikel [1], dan saya tidak akan mengulangi semuanya di sini. Rancangan ini adalah untuk menyediakan kod sampel C# yang berfungsi ("Pertama") tentang bagaimana komponen pandangan biasanya boleh digunakan. Kod boleh digunakan semula dengan contoh mudah ditunjukkan di bawah.

2. hasil akhir

Di sini kami menunjukkan hasil akhir. Ada ASP.NET8 halaman tuan rumah mempunyai 2 komponen dan 4 panggilan yang ditunjukkan pada imej. Komponen berwarna sengaja untuk menunjukkan di mana mereka berada. Dalam aplikasi sebenar, tentu saja, pewarna tidak akan digunakan. Berikut adalah apa contoh ini menunjukkan:

  • Div-0. Control in Host ASP.NET8 page

  • Div-1. View-Component-1 CustomerSearch, which is Async component, invoked with a method

  • Div-2. View-Component-1 CustomerSearch, which is Async component, invoked with Tag Helper

  • Div-3. View-Component-2 CustomerSearch2, which is Sync component, invoked with a method

  • Div-4. View-Component-2 CustomerSearch2, which is Sync component, invoked with Tag Helper


Kode sumber untuk contoh ini

Kod sumber dikomentari dengan baik, dan ia perlu menjadi penjelasan diri.

4.1 Bahagian C


//HomeController.cs=========================================
namespace Example1.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        public HomeController(ILogger<HomeController> logger)
        {
            _logger = logger;
        }

        public IActionResult Index()
        {
            return View();
        }

        //in this action we are testing the ViewComponent
        public IActionResult Test1(Test1_ViewModel model)
        {
            return View(model);
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

// CustomersSearchViewComponent_Model.cs ==========================
namespace Example1.ViewComponents.Models
{
    public class CustomersSearchViewComponent_Model
    {
        public string? Parameter1String { get; set; } = null;
        public int? Parameter2Int { get; set; } = null;
        public string? IdOfTargetInputField { get; set; } = null;
    }
}

// CustomersSearchViewComponent_ViewModel.cs ==========================
namespace Example1.ViewComponents.Models
{
    public class CustomersSearchViewComponent_ViewModel
    {
        public string? Parameter1String { get; set; } = null;
        public int? Parameter2Int { get; set; } = null;
        public string? IdOfTargetInputField { get; set; } = null;

        //this should come from DB in real application
        public SelectList? ListOfCustomers { get; set; }
    }
}

//CustomersSearch2ViewComponent.cs===================================================
namespace Example1.ViewComponents
{
    //it should inherit from ViewComponent class
    //this is Sync version of ViewComponent
    public class CustomersSearch2ViewComponent : ViewComponent
    {
        private readonly ILogger<CustomersSearch2ViewComponent>? _logger;

        // We are testing Dependency Injection (DI) to inject the logger 
        public CustomersSearch2ViewComponent(ILogger<CustomersSearch2ViewComponent> logger)
        {
            //note how useful is this, we are passing in this constructor
            //into view-component objects that are part of app DI container
            //you can pass here any form of reference to DataBase, for example
            //like EF DbContext or similar
            _logger = logger;
        }

        //The Invoke method for the View component
        public IViewComponentResult Invoke(
            CustomersSearchViewComponent_Model? model = null
        )
        {
            //this is neat, this parameters in CustomersSearchViewComponent_Model
            //are passed to the view-component from host form
            {
                //testing that DI worked - logger 
                string methodName = $"Type: {System.Reflection.MethodBase.GetCurrentMethod()?.DeclaringType?.FullName}, " +
                    $"Method: InvokeAsync; ";
                _logger?.LogWarning(methodName);
            }

            //preparing view-model
            CustomersSearchViewComponent_ViewModel viewModel = new();
            viewModel.Parameter1String = model?.Parameter1String;
            viewModel.Parameter2Int = model?.Parameter2Int;
            viewModel.IdOfTargetInputField = model?.IdOfTargetInputField;

            {
                //this should come from DB in real application
                SelectList list1 = new SelectList
                (new List<SelectListItem>
                {
                            new SelectListItem
                            {
                                Text = "John - 111",
                                Value = "111"
                            },

                           new SelectListItem
                            {
                                Text = "Mark - 222",
                                Value = "222"
                            },
                            new SelectListItem
                            {
                                Text = "Novak - 333",
                                Value = "333"
                            },
                }, "Value", "Text");

                viewModel.ListOfCustomers = list1;
            }

            //now render component view
            return View("Default", viewModel);
        }
    }
}

//CustomersSearchViewComponent.cs===================================================
namespace Example1.ViewComponents
{    
    //it should inherit from ViewComponent class
    //this is Async version of ViewComponent
    public class CustomersSearchViewComponent : ViewComponent
    {
        private readonly ILogger<CustomersSearchViewComponent>? _logger;

        // We are testing Dependency Injection (DI) to inject the logger
        public CustomersSearchViewComponent(ILogger<CustomersSearchViewComponent> logger)
        {
            //note how useful is this, we are passing in this constructor
            //into view-component objects that are part of app DI container
            //you can pass here any form of reference to DataBase, for example
            //like EF DbContext or similar
            _logger = logger;
        }

        //The Invoke method for the View component
        public async Task<IViewComponentResult> InvokeAsync(
            CustomersSearchViewComponent_Model? model=null
        )
        {
            //this is neat, this parameters in CustomersSearchViewComponent_Model
            //are passed to the view-component from host form
            {
                //testing that DI worked - logger 
                string methodName = $"Type: {System.Reflection.MethodBase.GetCurrentMethod()?.DeclaringType?.FullName}, " +
                    $"Method: InvokeAsync; ";
                _logger?.LogWarning(methodName);
            }

            await Task.Delay(0); // Simulate some async work

            //preparing view-model
            CustomersSearchViewComponent_ViewModel viewModel = new();
            viewModel.Parameter1String = model?.Parameter1String;
            viewModel.Parameter2Int = model?.Parameter2Int;
            viewModel.IdOfTargetInputField = model?.IdOfTargetInputField;

            {
                //this should come from DB in real application
                SelectList list1 = new SelectList
                (new List<SelectListItem>
                {
                            new SelectListItem
                            {
                                Text = "John - 111",
                                Value = "111"
                            },

                           new SelectListItem
                            {
                                Text = "Mark - 222",
                                Value = "222"
                            },
                            new SelectListItem
                            {
                                Text = "Novak - 333",
                                Value = "333"
                            },
                }, "Value", "Text");

                viewModel.ListOfCustomers= list1;
            }

            //now render component view
            return View("Default",viewModel);
        }
    }
} 

3.2 Bahagian Razor (.cshtml)


 <!--Test1.cshtml  --------------------------------------------------->
@using Example1.Models.Home;
@using Example1.ViewComponents;
@using Example1.ViewComponents.Models;
@using Example1
@using Example1.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Example1
@addTagHelper *, Example1.TagHelpers

@model Test1_ViewModel

@{
    ViewData["Title"] = "Test1";

    <!--Title  --------------------------------------------------->
    <h5 class="bg-primary text-left p-1 mt-1">
        <span class="d-inline-block ms-2">
            @ViewData["Title"]
        </span>
    </h5>

    <!-- Flexbox row1 -->
    <div class="d-flex" style="width:1100px">
        <!-- Div 0-------------------------------------------------->
        <div class="m-3 p-3">
            <fieldset class="border rounded-3 p-3 bg-light shadow" style="width:500px">
                <legend class="float-none w-auto px-3 border bg-light rounded-3 ">
                    Div - 0
                </legend>
                <!-- Form ----------------------------------------------------------------- -->
                <form id="form1" method="post" class="row">
                    <div class="form-group">
                        <label asp-for="ContractOwnerCustomer">
                            Customer Id
                        </label>
                        <input id="ContractOwnerCustomerId" class="form-control" asp-for="ContractOwnerCustomer" />
                    </div>
                </form>

                <hr />
                <!--Buttons ----------------------------------------------------- -->
                <div>
                    <button type="submit" form="form1" class="btn btn-primary mt-3 me-2 float-end"
                            href=''>
                        Submit
                    </button>
                </div>
            </fieldset>
        </div>
    </div>
    <!-- Flexbox row2 -->
    <div class="d-flex" style="width:1100px">
        <!-- Div 1----------------------------------------------- -->
        <div class="m-3 p-3">
            <h5 class="bg-secondary text-center p-1">
                Div1 - CustomersSearch, Async, invoked with method
            </h5>
            @{
                CustomersSearchViewComponent_Model myModel1 = new CustomersSearchViewComponent_Model();
                myModel1.Parameter1String = "Div1-Async, invoked with method";
                myModel1.Parameter2Int = 11111;
                myModel1.IdOfTargetInputField = "ContractOwnerCustomerId";

                //so, here we are using the ViewComponent
                @await Component.InvokeAsync("CustomersSearch", new
                    {
                        model = myModel1,
                    })  ;
            }
        </div>
        <!-- Div 2----------------------------------------------- -->
        <div class="m-3 p-3">
            <h5 class="bg-secondary text-center p-1">
                Div2 - CustomersSearch, Async, invoked with Tag Helper
            </h5>
            @{
                CustomersSearchViewComponent_Model myModel2 = new CustomersSearchViewComponent_Model();
                myModel2.Parameter1String = "Div2-Async, invoked with Tag Helper";
                myModel2.Parameter2Int = 22222;
                myModel2.IdOfTargetInputField = "ContractOwnerCustomerId";
            }

            <vc:customers-search model=myModel2>
            </vc:customers-search>
        </div>
    </div>
    <!-- Flexbox  row3-->
    <div class="d-flex" style="width:1100px">
        <!-- Div 3----------------------------------------------- -->
        <div class="m-3 p-3">
            <h5 class="bg-secondary text-center p-1">
                Div3 - CustomersSearch2, Sync, invoked with method
            </h5>
            @{
                CustomersSearchViewComponent_Model myModel3 = new CustomersSearchViewComponent_Model();
                myModel1.Parameter1String = "Div3-Sync, invoked with method";
                myModel1.Parameter2Int = 33333;
                myModel1.IdOfTargetInputField = "ContractOwnerCustomerId";

                //so, here we are using the ViewComponent
                //it looks strange, Sync component invoked with async method
                //but they want it this way
                @await Component.InvokeAsync("CustomersSearch2", new
                    {
                        model = myModel1,
                    })        ;
            }
        </div>
        <!-- Div 4----------------------------------------------- -->
        <div class="m-3 p-3">
            <h5 class="bg-secondary text-center p-1">
                Div4 - CustomersSearch2, Sync, invoked with Tag Helper
            </h5>
            @{
                CustomersSearchViewComponent_Model myModel4 = new CustomersSearchViewComponent_Model();
                myModel2.Parameter1String = "Div4- Sync, invoked with Tag Helper";
                myModel2.Parameter2Int = 44444;
                myModel2.IdOfTargetInputField = "ContractOwnerCustomerId";
            }

            <vc:customers-search2 model=myModel2>
            </vc:customers-search2>
        </div>
        <!--  ----------------------------------------------- -->
    </div>
}

<!--CustomersSearch\Default.cshtml  -------------------------------->
@using Example1.ViewComponents.Models

@model CustomersSearchViewComponent_ViewModel

<!--Visually, this div (color bg-info) is the component--->
<div id="ViewComponents1" class="bg-info p-3" style="width:400px">
    <!--Title  --------------------------------------------------->
    <h5 class="bg-primary text-center p-1 m-3">
        CustomersSearch - Async ViewComponent
    </h5>

    <p>
        Proof-of-concept, parameter from Host Form 
        <br/> Parameter1String: @Model.Parameter1String
    </p>
    <p>
        Proof-of-concept, parameter from Host Form
        <br /> Parameter2Int: @Model.Parameter2Int
    </p>

    <fieldset class="border rounded-3 p-3 m-2 shadow">
        <label>
            Proof-of-concept, list of customers from DB
        </label>
        <select id="customerSelect2" class="form-select"
                asp-items="@Model.ListOfCustomers">
        </select>

        <a class="btn btn-secondary mt-3 float-end"
           onclick="copyInputTextTo(this)">
            Copy Selected Customer ID to Form
        </a>
    </fieldset>
</div> <!-- End of <div id="ViewComponents1"  -->

<script>
    // This function will export selection value from the ViewComponent
    // to the main form and copy it to the input field
    function copyInputTextTo(anchor) {
        var root = anchor.closest('fieldset');
        var target = document.getElementById("@Model.IdOfTargetInputField");
        var source = root.querySelector('#customerSelect2') ;

        if (source && target) {
            target.value = source.value;
        }
        return false;
    }
</script>

<!--CustomersSearch2\Default.cshtml  -------------------------------->
@using Example1.ViewComponents.Models

@model CustomersSearchViewComponent_ViewModel

<!--Visually, this div (color bg-warning) is the component--->
<div id="ViewComponents1" class="bg-warning p-3" style="width:400px">
    <!--Title  --------------------------------------------------->
    <h5 class="bg-primary text-center p-1 m-3">
        CustomersSearch2 - Sync ViewComponent
    </h5>

    <p>
        Proof-of-concept, parameter from Host Form
        <br /> Parameter1String: @Model.Parameter1String
    </p>
    <p>
        Proof-of-concept, parameter from Host Form
        <br /> Parameter2Int: @Model.Parameter2Int
    </p>

    <fieldset class="border rounded-3 p-3 m-2 shadow">
        <label>
            Proof-of-concept, list of customers from DB
        </label>
        <select id="customerSelect2" class="form-select"
                asp-items="@Model.ListOfCustomers">
        </select>

        <a class="btn btn-secondary mt-3 float-end"
           onclick="copyInputTextTo(this)">
            Copy Selected Customer ID to Form
        </a>
    </fieldset>
</div> <!-- End of <div id="ViewComponents1"  -->

<script>
    // This function will export selection value from the ViewComponent
    // to the main form and copy it to the input field
    function copyInputTextTo(anchor) {
        var root = anchor.closest('fieldset');
        var target = document.getElementById("@Model.IdOfTargetInputField");
        var source = root.querySelector('#customerSelect2') ;

        if (source && target) {
            target.value = source.value;
        }
        return false;
    }
</script>

3.3 Lokasi fail dalam projek

4. kesimpulan

Lihat Komponen dalam ASP.NET8 adalah bentuk yang lebih tinggi daripada seni bina komponen, dan saya mendapati ia praktikal.Ia mengambil masa untuk membiasakan diri dengan mereka dan belajar bagaimana untuk mencipta / menggunakan mereka, tetapi mereka pasti berguna kepada sesiapa yang berpengalamanPerkhidmatan ASP.NETkepada program.

5 Referensi


[1] Memaparkan komponen dalam ASP.NET Core

https://learn.microsoft.com/en-us/aspnet/core/mvc/views/view-components?view=aspnetcore-9.0

[2] Lihat komponen dalam ASP.NET Core MVC

https://dotnettutorials.net/lesson/view-components-in-asp-net-core-mvc/

L O A D I N G
. . . comments & more!

About Author

Mark Pelf HackerNoon profile picture
Mark Pelf@markpelf
Mark Pelf is the pen name of a Software Engineer from Belgrade, Serbia. https://markpelf.com/

GANTUNG TANDA

ARTIKEL INI DIBENTANGKAN DALAM...

Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks