Sdílet prostřednictvím


Injektáž závislostí do pohledů 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í. Zvažte appsettings.Development.json z ukázkového kódu:

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

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

@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

Injektování 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();

StatisticsService provádí některé výpočty na sadě instancí ToDoItem, 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 uloženou 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í:

Chcete-li zobrazit výpis celkových položek, dokončených položek, průměrné priority a seznamu úkolů s jejich úrovněmi priority a logickými hodnotami označujícími dokončení.

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 spočívá ve vložení služeb přímo do zobrazení, aby se získaly možnosti. Tím se minimalizuje množství kódu, který vyžaduje kontroler nebo stránka Razor Page, a tato logika konstrukce prvku zobrazení se přesune do samotného zobrazení. Ovladač nebo Razor Stránka pro zobrazení formuláře pro úpravy profilu potřebuje předat formuláři pouze 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:

Aktualizujte zobrazení profilu pomocí formuláře, který umožňuje zadání jména, pohlaví, stavu a oblíbené barvy.

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é služby na stránce. Následující obrázek ukazuje všechna pole dostupná na stránce použité v prvním příkladu:

Kontextová nabídka IntelliSense pro zadaný symbol @ s výpisem položek Html, Component, StatsService a Url

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í zodpovědností 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í)

Vkládání 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 jako přidání vlastnosti do zobrazení a její naplnění 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 je naplněn z vloženého StatisticsService. 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();

StatisticsService provádí některé výpočty nad sadou instancí ToDoItem, 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ý repozitář používá paměťovou kolekci. 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í:

Chcete-li zobrazit výpis celkových položek, dokončených položek, průměrné priority a seznamu úkolů s jejich úrovněmi priority a logickými hodnotami označujícími dokončení.

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 řadiče, která zobrazí formulář pro úpravy profilu, musí pouze předat instanci profilu formuláři.

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:

Aktualizujte zobrazení profilu pomocí formuláře, který umožňuje zadání jména, pohlaví, stavu a oblíbené barvy.

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 injektování závislostí v Startup.ConfigureServices. Neregistrovaný typ vyvolá výjimku za běhu, protože poskytovatel služeb je interně dotazován prostřednictvím GetRequiredService.

Překrytí služeb

Kromě vkládání nových služeb lze tuto techniku také použít k přepsání dříve vložených 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:

Kontextová nabídka IntelliSense u napsaného znaku @ s výpisem položek Html, Component, StatsService a Url

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, a to buď zděděním ze stávající implementace, nebo zabalením stávající implementace do vlastní.

Viz také