Injektáž závislostí do zobrazení v ASP.NET Core

ASP.NET Core podporuje injektáž závislostí do zobrazení. To může být užitečné pro služby specifické pro zobrazení, jako je lokalizace nebo data požadovaná pouze pro naplnění prvků zobrazení. Většina zobrazení dat by měla být předána ze kontroleru.

Zobrazení nebo stažení ukázkového kódu (postup stažení)

Injektáž konfigurace

Hodnoty v souborech nastavení, například appsettings.json a appsettings.Development.json, lze vložit do zobrazení. Podívejte se na appsettings.Development.jsonukázkový kód:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "MyRoot": {
    "MyParent": {
      "MyChildName": "Joe"
    }
  }
}

Následující kód zobrazí konfigurační hodnotu v Razor zobrazení Stránky:

@page
@model PrivacyModel
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration
@{
    ViewData["Title"] = "Privacy RP";
}
<h1>@ViewData["Title"]</h1>

<p>PR Privacy</p>

<h2>
   MyRoot:MyParent:MyChildName: @Configuration["MyRoot:MyParent:MyChildName"]
</h2>

Následující kód zobrazí konfigurační hodnotu v zobrazení MVC:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration
@{
    ViewData["Title"] = "Privacy MVC";
}
<h1>@ViewData["Title"]</h1>

<p>MVC Use this page to detail your site's privacy policy.</p>

<h2>
   MyRoot:MyParent:MyChildName: @Configuration["MyRoot:MyParent:MyChildName"]
</h2>

Další informace najdete v tématu Konfigurace v ASP.NET Core

Injektáž služby

Službu lze vložit do zobrazení pomocí direktivy @inject .

@using System.Threading.Tasks
@using ViewInjectSample.Model
@using ViewInjectSample.Model.Services
@model IEnumerable<ToDoItem>
@inject StatisticsService StatsService
<!DOCTYPE html>
<html>
<head>
    <title>To Do Items</title>
</head>
<body>
    <div>
        <h1>To Do Items</h1>
        <ul>
            <li>Total Items: @StatsService.GetCount()</li>
            <li>Completed: @StatsService.GetCompletedCount()</li>
            <li>Avg. Priority: @StatsService.GetAveragePriority()</li>
        </ul>
        <table>
            <tr>
                <th>Name</th>
                <th>Priority</th>
                <th>Is Done?</th>
            </tr>
            @foreach (var item in Model)
            {
                <tr>
                    <td>@item.Name</td>
                    <td>@item.Priority</td>
                    <td>@item.IsDone</td>
                </tr>
            }
        </table>
    </div>
</body>
</html>

Toto zobrazení zobrazuje seznam ToDoItem instancí spolu se souhrnem zobrazující celkové statistiky. Souhrn se vyplní ze vloženého StatisticsServicesouboru . Tato služba je registrována pro injektáž závislostí v ConfigureServicesProgram.cs:

using ViewInjectSample.Helpers;
using ViewInjectSample.Infrastructure;
using ViewInjectSample.Interfaces;
using ViewInjectSample.Model.Services;

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddTransient<IToDoItemRepository, ToDoItemRepository>();
builder.Services.AddTransient<StatisticsService>();
builder.Services.AddTransient<ProfileOptionsService>();
builder.Services.AddTransient<MyHtmlHelper>();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.MapRazorPages();

app.MapDefaultControllerRoute();


app.Run();

Provede StatisticsService některé výpočty sady ToDoItem instancí, ke kterým přistupuje prostřednictvím úložiště:

using System.Linq;
using ViewInjectSample.Interfaces;

namespace ViewInjectSample.Model.Services
{
    public class StatisticsService
    {
        private readonly IToDoItemRepository _toDoItemRepository;

        public StatisticsService(IToDoItemRepository toDoItemRepository)
        {
            _toDoItemRepository = toDoItemRepository;
        }

        public int GetCount()
        {
            return _toDoItemRepository.List().Count();
        }

        public int GetCompletedCount()
        {
            return _toDoItemRepository.List().Count(x => x.IsDone);
        }

        public double GetAveragePriority()
        {
            if (_toDoItemRepository.List().Count() == 0)
            {
                return 0.0;
            }

            return _toDoItemRepository.List().Average(x => x.Priority);
        }
    }
}

Ukázkové úložiště používá kolekci v paměti. Implementace v paměti by neměla být použita pro velké a vzdáleně přístupné datové sady.

Ukázka zobrazí data z modelu vázaného na zobrazení a službu vloženou do zobrazení:

To Do view listing total items, completed items, average priority, and a list of tasks with their priority levels and boolean values indicating completion.

Naplnění vyhledávacích dat

Injektáž zobrazení může být užitečná k naplnění možností v prvech uživatelského rozhraní, jako jsou rozevírací seznamy. Představte si formulář profilu uživatele, který obsahuje možnosti pro určení pohlaví, stavu a dalších předvoleb. Vykreslení takového formuláře pomocí standardního přístupu může vyžadovat, aby kontroler nebo Razor stránka:

  • Požádejte o služby pro přístup k datům pro každou sadu možností.
  • Naplňte model nebo ViewBag každou sadu možností, které se mají svázat.

Alternativní přístup vloží služby přímo do zobrazení pro získání možností. Tím se minimalizuje množství kódu požadovaného kontrolerem nebo stránkou razor Page a přesune se tato logika konstrukce prvku zobrazení do samotného zobrazení. Akce kontroleru nebo Razor Stránka pro zobrazení formuláře pro úpravy profilu stačí předat pouze formulář instanci profilu:

using Microsoft.AspNetCore.Mvc;
using ViewInjectSample.Model;

namespace ViewInjectSample.Controllers;

public class ProfileController : Controller
{
    public IActionResult Index()
    {
        // A real app would up profile based on the user.
        var profile = new Profile()
        {
            Name = "Rick",
            FavColor = "Blue",
            Gender = "Male",
            State = new State("Ohio","OH")
        };
        return View(profile);
    }
}

Formulář HTML použitý k aktualizaci předvoleb obsahuje rozevírací seznamy pro tři vlastnosti:

Update Profile view with a form allowing the entry of name, gender, state, and favorite Color.

Tyto seznamy jsou naplněny službou, která byla vložena do zobrazení:

@using System.Threading.Tasks
@using ViewInjectSample.Model.Services
@model ViewInjectSample.Model.Profile
@inject ProfileOptionsService Options
<!DOCTYPE html>
<html>
<head>
    <title>Update Profile</title>
</head>
<body>
<div>
    <h1>Update Profile</h1>
    Name: @Html.TextBoxFor(m => m.Name)
    <br/>
    Gender: @Html.DropDownList("Gender",
           Options.ListGenders().Select(g => 
                new SelectListItem() { Text = g, Value = g }))
    <br/>

    State: @Html.DropDownListFor(m => m.State!.Code,
           Options.ListStates().Select(s => 
                new SelectListItem() { Text = s.Name, Value = s.Code}))
    <br />

    Fav. Color: @Html.DropDownList("FavColor",
           Options.ListColors().Select(c => 
                new SelectListItem() { Text = c, Value = c }))
    </div>
</body>
</html>

Jedná se ProfileOptionsService o službu na úrovni uživatelského rozhraní navrženou tak, aby poskytovala pouze data potřebná pro tento formulář:

namespace ViewInjectSample.Model.Services;

public class ProfileOptionsService
{
    public List<string> ListGenders()
    {
        // Basic sample
        return new List<string>() {"Female", "Male"};
    }

    public List<State> ListStates()
    {
        // Add a few states
        return new List<State>()
        {
            new State("Alabama", "AL"),
            new State("Alaska", "AK"),
            new State("Ohio", "OH")
        };
    }

    public List<string> ListColors()
    {
        return new List<string>() { "Blue","Green","Red","Yellow" };
    }
}

Všimněte si, že neregistrovaný typ vyvolá výjimku za běhu, protože poskytovatel služeb je interně dotazován prostřednictvím GetRequiredService.

Přepsání služeb

Kromě vkládání nových služeb lze tuto techniku použít k přepsání dříve vloženého služeb na stránce. Následující obrázek ukazuje všechna pole dostupná na stránce použité v prvním příkladu:

Intellisense contextual menu on a typed @ symbol listing Html, Component, StatsService, and Url fields

Výchozí pole zahrnují Html, Componenta Url. Chcete-li nahradit výchozí pomocné rutiny HTML vlastní verzí, použijte @inject:

@using System.Threading.Tasks
@using ViewInjectSample.Helpers
@inject MyHtmlHelper Html
<!DOCTYPE html>
<html>
<head>
    <title>My Helper</title>
</head>
<body>
    <div>
        Test: @Html.Value
    </div>
</body>
</html>

Viz také

ASP.NET Core podporuje injektáž závislostí do zobrazení. To může být užitečné pro služby specifické pro zobrazení, jako je lokalizace nebo data požadovaná pouze pro naplnění prvků zobrazení. Měli byste se pokusit zachovat oddělení obav mezi kontrolery a zobrazeními. Většina dat, která se zobrazí, by se měla předat ze kontroleru.

Zobrazení nebo stažení ukázkového kódu (postup stažení)

Injektáž konfigurace

appsettings.json hodnoty lze vložit přímo do zobrazení.

appsettings.json Příklad souboru:

{
   "root": {
      "parent": {
         "child": "myvalue"
      }
   }
}

Syntaxe pro @inject: @inject <type> <name>

Příklad použití @inject:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration
@{
   string myValue = Configuration["root:parent:child"];
   ...
}

Injektáž služby

Službu lze vložit do zobrazení pomocí direktivy @inject . Můžete si představit @inject přidání vlastnosti do zobrazení a naplnění vlastnosti pomocí DI.

@using System.Threading.Tasks
@using ViewInjectSample.Model
@using ViewInjectSample.Model.Services
@model IEnumerable<ToDoItem>
@inject StatisticsService StatsService
<!DOCTYPE html>
<html>
<head>
    <title>To Do Items</title>
</head>
<body>
    <div>
        <h1>To Do Items</h1>
        <ul>
            <li>Total Items: @StatsService.GetCount()</li>
            <li>Completed: @StatsService.GetCompletedCount()</li>
            <li>Avg. Priority: @StatsService.GetAveragePriority()</li>
        </ul>
        <table>
            <tr>
                <th>Name</th>
                <th>Priority</th>
                <th>Is Done?</th>
            </tr>
            @foreach (var item in Model)
            {
                <tr>
                    <td>@item.Name</td>
                    <td>@item.Priority</td>
                    <td>@item.IsDone</td>
                </tr>
            }
        </table>
    </div>
</body>
</html>

Toto zobrazení zobrazuje seznam ToDoItem instancí spolu se souhrnem zobrazující celkové statistiky. Souhrn se vyplní ze vloženého StatisticsServicesouboru . Tato služba je registrována pro injektáž závislostí v ConfigureServicesStartup.cs:

public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

Provede StatisticsService některé výpočty sady ToDoItem instancí, ke kterým přistupuje prostřednictvím úložiště:

using System.Linq;
using ViewInjectSample.Interfaces;

namespace ViewInjectSample.Model.Services
{
    public class StatisticsService
    {
        private readonly IToDoItemRepository _toDoItemRepository;

        public StatisticsService(IToDoItemRepository toDoItemRepository)
        {
            _toDoItemRepository = toDoItemRepository;
        }

        public int GetCount()
        {
            return _toDoItemRepository.List().Count();
        }

        public int GetCompletedCount()
        {
            return _toDoItemRepository.List().Count(x => x.IsDone);
        }

        public double GetAveragePriority()
        {
            if (_toDoItemRepository.List().Count() == 0)
            {
                return 0.0;
            }

            return _toDoItemRepository.List().Average(x => x.Priority);
        }
    }
}

Ukázkové úložiště používá kolekci v paměti. Výše uvedená implementace (která pracuje se všemi daty v paměti) se nedoporučuje pro velké a vzdáleně přístupné datové sady.

Ukázka zobrazí data z modelu vázaného na zobrazení a službu vloženou do zobrazení:

To Do view listing total items, completed items, average priority, and a list of tasks with their priority levels and boolean values indicating completion.

Naplnění vyhledávacích dat

Injektáž zobrazení může být užitečná k naplnění možností v prvech uživatelského rozhraní, jako jsou rozevírací seznamy. Představte si formulář profilu uživatele, který obsahuje možnosti pro určení pohlaví, stavu a dalších předvoleb. Vykreslení takového formuláře pomocí standardního přístupu MVC by vyžadovalo, aby kontroler požádal o služby přístupu k datům pro každou z těchto sad možností a pak naplnil model nebo ViewBag každou sadu možností, které mají být svázané.

Alternativní přístup vloží služby přímo do zobrazení pro získání možností. Tím se minimalizuje množství kódu vyžadovaného kontrolerem a přesune se tato logika konstrukce prvku zobrazení do samotného zobrazení. Akce kontroleru, která zobrazí formulář pro úpravy profilu, musí předat pouze formulář instanci profilu:

using Microsoft.AspNetCore.Mvc;
using ViewInjectSample.Model;

namespace ViewInjectSample.Controllers
{
    public class ProfileController : Controller
    {
        [Route("Profile")]
        public IActionResult Index()
        {
            // TODO: look up profile based on logged-in user
            var profile = new Profile()
            {
                Name = "Steve",
                FavColor = "Blue",
                Gender = "Male",
                State = new State("Ohio","OH")
            };
            return View(profile);
        }
    }
}

Formulář HTML použitý k aktualizaci těchto předvoleb obsahuje rozevírací seznamy pro tři vlastnosti:

Update Profile view with a form allowing the entry of name, gender, state, and favorite Color.

Tyto seznamy jsou naplněny službou, která byla vložena do zobrazení:

@using System.Threading.Tasks
@using ViewInjectSample.Model.Services
@model ViewInjectSample.Model.Profile
@inject ProfileOptionsService Options
<!DOCTYPE html>
<html>
<head>
    <title>Update Profile</title>
</head>
<body>
<div>
    <h1>Update Profile</h1>
    Name: @Html.TextBoxFor(m => m.Name)
    <br/>
    Gender: @Html.DropDownList("Gender",
           Options.ListGenders().Select(g => 
                new SelectListItem() { Text = g, Value = g }))
    <br/>

    State: @Html.DropDownListFor(m => m.State.Code,
           Options.ListStates().Select(s => 
                new SelectListItem() { Text = s.Name, Value = s.Code}))
    <br />

    Fav. Color: @Html.DropDownList("FavColor",
           Options.ListColors().Select(c => 
                new SelectListItem() { Text = c, Value = c }))
    </div>
</body>
</html>

Jedná se ProfileOptionsService o službu na úrovni uživatelského rozhraní navrženou tak, aby poskytovala pouze data potřebná pro tento formulář:

using System.Collections.Generic;

namespace ViewInjectSample.Model.Services
{
    public class ProfileOptionsService
    {
        public List<string> ListGenders()
        {
            // keeping this simple
            return new List<string>() {"Female", "Male"};
        }

        public List<State> ListStates()
        {
            // a few states from USA
            return new List<State>()
            {
                new State("Alabama", "AL"),
                new State("Alaska", "AK"),
                new State("Ohio", "OH")
            };
        }

        public List<string> ListColors()
        {
            return new List<string>() { "Blue","Green","Red","Yellow" };
        }
    }
}

Důležité

Nezapomeňte zaregistrovat typy, které požadujete prostřednictvím injektáže závislostí .Startup.ConfigureServices Neregistrovaný typ vyvolá výjimku za běhu, protože poskytovatel služeb je interně dotazován prostřednictvím GetRequiredService.

Přepsání služeb

Kromě vkládání nových služeb lze tuto techniku použít také k přepsání dříve vloženého služeb na stránce. Následující obrázek ukazuje všechna pole dostupná na stránce použité v prvním příkladu:

Intellisense contextual menu on a typed @ symbol listing Html, Component, StatsService, and Url fields

Jak můžete vidět, výchozí pole zahrnují Html, Componenta Url (stejně jako StatsService vložené pole). Pokud byste například chtěli nahradit výchozí pomocné rutiny HTML vlastními, můžete to snadno provést pomocí @inject:

@using System.Threading.Tasks
@using ViewInjectSample.Helpers
@inject MyHtmlHelper Html
<!DOCTYPE html>
<html>
<head>
    <title>My Helper</title>
</head>
<body>
    <div>
        Test: @Html.Value
    </div>
</body>
</html>

Pokud chcete rozšířit stávající služby, můžete tuto techniku jednoduše použít při zdědění stávající implementace nebo zabalení vlastní implementace.

Viz také