135 votes

Transmettre des données à la mise en page qui sont communes à toutes les pages

J'ai un site web qui a une page de mise en page. Cependant, cette page de mise en page contient des données que toutes les pages doivent fournir, comme le titre de la page, le nom de la page et l'emplacement où nous nous trouvons actuellement pour une aide HTML que j'ai créée et qui effectue une action. De plus, chaque page a ses propres propriétés de modèle de vue.

Comment puis-je faire cela ? Il semble que ce ne soit pas une bonne idée de taper une mise en page mais comment puis-je passer ces informations ?

12 votes

Pour tous ceux qui lisent les réponses ici, veuillez voir stackoverflow.com/a/21130867/706346 où vous verrez une solution beaucoup plus simple et plus propre que tout ce qui a été posté ici.

5 votes

@AvrohomYisroel bonne suggestion. Cependant, je préfère l'approche de @Colin Bacon parce qu'elle est fortement typée et qu'elle n'est pas dans l'approche de la ViewBag . Peut-être une question de préférences. J'ai quand même upvoted votre commentaire

0 votes

Pour mvc 5 voir cette réponse : stackoverflow.com/a/46783375/5519026

2voto

stom Points 2477

Vous pouvez également utiliser RenderSection il vous aide à injecter votre Model dans le _Layout vue.

Vous pouvez injecter View Model Données, Json , Script , CSS , HTML etc.

Dans cet exemple, j'injecte Json de mon Index Voir à Layout Voir.

Index.chtml

@section commonLayoutData{

    <script>

        var products = @Html.Raw(Json.Encode(Model.ToList()));

    </script>

    }

_Layout.cshtml

@RenderSection("commonLayoutData", false)

Il n'est donc pas nécessaire de créer une base distincte. View Model .

J'espère que cela aidera quelqu'un.

1voto

Etienne Charland Points 475

Pourquoi personne n'a suggéré des méthodes d'extension sur les ViewData ?

Option 1

Il me semble que c'est de loin la solution la moins intrusive et la plus simple au problème. Pas de chaînes codées en dur. Pas de restrictions imposées. Pas de codage magique. Pas de code complexe.

public static class ViewDataExtensions
{
    private const string TitleData = "Title";
    public static void SetTitle<T>(this ViewDataDictionary<T> viewData, string value) => viewData[TitleData] = value;
    public static string GetTitle<T>(this ViewDataDictionary<T> viewData) => (string)viewData[TitleData] ?? "";
}

Définir les données dans la page

ViewData.SetTitle("abc");

Option n° 2

Une autre option, qui facilite la déclaration sur le terrain.

public static class ViewDataExtensions
{
    public static ViewDataField<string, V> Title<V>(this ViewDataDictionary<V> viewData) => new ViewDataField<string, V>(viewData, "Title", "");
}

public class ViewDataField<T,V>
{
    private readonly ViewDataDictionary<V> _viewData;
    private readonly string _field;
    private readonly T _defaultValue;

    public ViewDataField(ViewDataDictionary<V> viewData, string field, T defaultValue)
    {
        _viewData = viewData;
        _field = field;
        _defaultValue = defaultValue;
    }

    public T Value {
        get => (T)(_viewData[_field] ?? _defaultValue);
        set => _viewData[_field] = value;
    }
}

Définir les données dans la page. La déclaration est plus facile que la première option, mais la syntaxe d'utilisation est légèrement plus longue.

ViewData.Title().Value = "abc";

Option n° 3

Vous pouvez ensuite combiner cela avec le retour d'un objet unique contenant tous les champs liés à la mise en page avec leurs valeurs par défaut.

public static class ViewDataExtensions
{
    private const string LayoutField = "Layout";
    public static LayoutData Layout<T>(this ViewDataDictionary<T> viewData) => 
        (LayoutData)(viewData[LayoutField] ?? (viewData[LayoutField] = new LayoutData()));
}

public class LayoutData
{
    public string Title { get; set; } = "";
}

Définir les données dans la page

var layout = ViewData.Layout();
layout.Title = "abc";

Cette troisième option présente plusieurs avantages et je pense qu'elle est la meilleure dans la plupart des cas :

  • Déclaration la plus simple des champs et des valeurs par défaut.

  • La syntaxe d'utilisation la plus simple lors de la définition de plusieurs champs.

  • Permet de définir différents types de données dans les ViewData (par exemple, Layout, Header, Navigation).

  • Permet d'ajouter du code et de la logique dans la classe LayoutData.

P.S. N'oubliez pas d'ajouter l'espace de nom de ViewDataExtensions dans _ViewImports.cshtml

0voto

Joel Wiklund Points 1173

Vous pourriez créer un fichier razor dans le dossier App_Code, puis y accéder à partir de vos pages de visualisation.

Projet>Repository/IdentityRepository.cs

namespace Infrastructure.Repository
{
    public class IdentityRepository : IIdentityRepository
    {
        private readonly ISystemSettings _systemSettings;
        private readonly ISessionDataManager _sessionDataManager;

        public IdentityRepository(
            ISystemSettings systemSettings
            )
        {
            _systemSettings = systemSettings;
        }

        public string GetCurrentUserName()
        {
            return HttpContext.Current.User.Identity.Name;
        }
    }
}

Projet>App_Code/IdentityRepositoryViewFunctions.cshtml :

@using System.Web.Mvc
@using Infrastructure.Repository
@functions
{
    public static IIdentityRepository IdentityRepositoryInstance
    {
        get { return DependencyResolver.Current.GetService<IIdentityRepository>(); }
    }

    public static string GetCurrentUserName
    {
        get
        {
            var identityRepo = IdentityRepositoryInstance;
            if (identityRepo != null)
            {
                return identityRepo.GetCurrentUserName();
            }
            return null;
        }
    }
}

Projet>Vues/Partagées/_Layout.cshtml (ou tout autre fichier .cshtml)

<div>
    @IdentityRepositoryViewFunctions.GetCurrentUserName
</div>

0voto

Adam C Points 66

Dans .NET Core, vous pouvez utiliser les composants de vue pour ce faire.

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

A partir du lien ci-dessus, ajoutez une classe héritant de ViewComponent

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ViewComponentSample.Models;

namespace ViewComponentSample.ViewComponents
{
    public class PriorityListViewComponent : ViewComponent
    {
        private readonly ToDoContext db;

        public PriorityListViewComponent(ToDoContext context)
        {
            db = context;
        }

        public async Task<IViewComponentResult> InvokeAsync(
        int maxPriority, bool isDone)
        {
            var items = await GetItemsAsync(maxPriority, isDone);
            return View(items);
        }
        private Task<List<TodoItem>> GetItemsAsync(int maxPriority, bool isDone)
        {
            return db.ToDo.Where(x => x.IsDone == isDone &&
                                 x.Priority <= maxPriority).ToListAsync();
        }
    }
}

Ensuite, dans votre vision ( _layout dans mon cas)

@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })

Si vous avez besoin d'une vue, créez un dossier à l'adresse suivante ~/Views/Shared/Components/<Component Name>/Default.cshtml . Vous devez créer le dossier Components puis dans celui-ci, créez un dossier avec le nom de votre composant. Dans l'exemple ci-dessus, PriorityList .

0voto

Zeeshan Abbas Points 31

La meilleure façon d'utiliser des chaînes statiques telles que le titre de la page, le nom de la page et l'emplacement, etc., est de les définir via ViewData. Il suffit de définir la ViewData requise dans ViewStart.cshtml

@{
    Layout = "_Layout";
    ViewData["Title"] = "Title";
    ViewData["Address"] = "1425 Lane, Skardu,<br> Pakistan";
}

et appeler chaque fois que nécessaire comme

<div class="rn-info-content">
     <h2 class="rn-contact-title">Address</h2>
         <address>
             @Html.Raw(ViewData["Address"].ToString())
         </address>
</div>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X