ASP.NET8 View Components Set New Bar для Web UI Reusability

па Mark Pelf23m2025/05/23
Read on Terminal Reader

Занадта доўга; Чытаць

У групе 2 былі сабраны менавіта тыя добраахвотнікі, якія запаміналі змест свайго сну слабей — 2 разы ў месяц і радзей.
featured image - ASP.NET8 View Components Set New Bar для Web UI Reusability
Mark Pelf HackerNoon profile picture
0-item

У групе 2 былі сабраны менавіта тыя добраахвотнікі, якія запаміналі змест свайго сну слабей — 2 разы ў месяц і радзей.

У групе 2 былі сабраны менавіта тыя добраахвотнікі, якія запаміналі змест свайго сну слабей — 2 разы ў месяц і радзей.

ASP.NET8 View-Components больш магутныя, чым Partal-Views

Усё, што вы чулі пра карысць пара раней - усяго толькі чуткі і павер'і.

Арганізатар спеўных варштатаў у межах праекта «CHOICE-Беларусь: спадчына i сучаснасць» разважае, як можна пракласці мост паміж музеем і людзьмі.

Ключавыя перавагіСцягнуць ASP.NETНаступным крокам з'яўляецца выбар адпаведнага абсталявання дляЧастка, якая выконваецца з боку сервераУ нас функцыяну­юць таварыствы “Разумнікі і разумніцы”, “Даследчык”, а таксама адзіная ў Магілёўскай вобласці астранамічная пляцоўка.

Частка, якая выконваецца з боку сервера

ASP.NET8 View-Components атрымліваюць параметры з метаду выкліку (хаст-страница або нават кантролер правільна) і не HTTP-запыт. але, вядома, нічога не забяспечвае стварэння View-Components, якія атрымліваюць HttpRequest як параметр, які будзе выключна перададзены да кампаненты.

Паглядзець элементы ўСцягнуць ASP.NETЯркія з'яўляюцца добра абмежаванымі ў артыкуле [1], і я не буду паўтарыць усё тут. План заключаецца ў тым, каб забяспечыць працуючы C# шаблонны код («Першы») на тое, як звычайна могуць быць выкарыстаны параметры прагляду. паўночны код з простым прыкладам паказаны ніжэй.

2.Фінальны вынік

Тут мы паказваем канчатковы вынік. Ёсць ASP.NET8 хост-старонка мае 2 кампаненты і 4 выклікі, паказаныя на малюнку. Каментарыі фарбаваныя наўмысна, каб паказаць, дзе яны знаходзяцца. У сапраўднай прыкладзе, вядома, фарбаванне не будзе выкарыстоўвацца.

  • 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


3. коды для гэтага прыкладу

Крынічны код добра каментаваны, і ён павінен быць самоаптымізацыйным.

3.1 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 Частка 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 Размяшчэнне файлаў у праекце

4 Высновы

Сярод версій гульняў онлайн call of duty можна знайсці мноства займальных і дасціпных сюжэтаў, а апошняй навінкай, выпушчанай у канцы восені гэтага года, стала гульня Call of Duty: Ghost.Сцягнуць ASP.NETПраграмаваць

5 Реферат


[1] Прагляд кампанентаў у ASP.NET Core

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

[2] Прагляд кампанентаў у ASP.NET Core MVC

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

Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks