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

124

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 le modèle de toutes les pages doit fournir comme le titre de la page, le nom de la page et l'emplacement où nous nous trouvons réellement pour un assistant HTML que j'ai fait qui effectue une action. De plus, chaque page a ses propres propriétés de modèle de vue.

Comment puis-je faire ceci? Il semble que ce soit une mauvaise idée de taper une mise en page mais comment puis-je transmettre ces informations?

Rushino
la source
10
Pour toute personne lisant les réponses ici, veuillez consulter stackoverflow.com/a/21130867/706346 où vous verrez une solution beaucoup plus simple et plus soignée que tout ce qui est posté ici.
Avrohom Yisroel
5
@AvrohomYisroel bonne suggestion. Cependant je préfère l'approche de @Colin Bacon car il est typé fort et pas dans le ViewBag. Peut-être une question de préférences. A voté pour votre commentaire
JP Hellemons
pour mvc 5 voir cette réponse: stackoverflow.com/a/46783375/5519026
Laz Ziya

Réponses:

143

Si vous devez transmettre les mêmes propriétés à chaque page, il serait judicieux de créer un modèle de vue de base utilisé par tous vos modèles de vue. Votre page de mise en page peut alors prendre ce modèle de base.

Si une logique est requise derrière ces données, celle-ci doit être placée dans un contrôleur de base utilisé par tous vos contrôleurs.

Il y a beaucoup de choses que vous pouvez faire, l'approche importante étant de ne pas répéter le même code à plusieurs endroits.

Edit: mise à jour à partir des commentaires ci-dessous

Voici un exemple simple pour démontrer le concept.

Créez un modèle de vue de base dont tous les modèles de vue hériteront.

public abstract class ViewModelBase
{
    public string Name { get; set; }
}

public class HomeViewModel : ViewModelBase
{
}

Votre page de mise en page peut prendre cela comme modèle.

@model ViewModelBase
<!DOCTYPE html>
<html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Test</title>
    </head>
    <body>
        <header>
            Hello @Model.Name
        </header>
        <div>
            @this.RenderBody()
        </div>
    </body>
</html>

Enfin, définissez les données dans la méthode d'action.

public class HomeController
{
    public ActionResult Index()
    {
        return this.View(new HomeViewModel { Name = "Bacon" });
    }
}
Colin Bacon
la source
12
Mais les données sont utilisées dans la mise en page. Comment puis-je transmettre les données à la mise en page?
Rushino
2
Parfait! J'ai vu mon erreur. J'ai oublié de passer le modèle à la vue .. quelle erreur boiteuse. Merci!
Rushino
7
le problème avec cette approche est que parfois toutes les vues n'ont pas de ViewModel, donc cela ne fonctionnera pas dans ce cas: O /
Cacho Santa
17
Mais cela n'exigerait-il pas que chaque contrôleur et chaque action incluent le code {Name = "Bacon"}? Et si je voulais ajouter une autre propriété à ViewModelBase, je devrais accéder à chaque contrôleur et à chaque action et ajouter le code pour remplir cette propriété? Vous avez mentionné "Si une logique est requise [...], celle-ci doit être placée dans un contrôleur de base [...]". Comment cela fonctionnerait-il pour éliminer ce code répété dans chaque contrôleur et chaque action?
Lee
5
@Lee S'il s'agit de données communes à toutes les pages, un contrôleur de base est l'endroit où vous les placeriez. Vos contrôleurs héritent alors de ce contrôleur de base. par exemple public class HomeController : BaseController. De cette façon, le code commun n'a besoin d'être écrit qu'une seule fois et peut être appliqué à tous les contrôleurs.
Colin Bacon
73

J'ai utilisé l'assistant html RenderAction pour razor dans la mise en page.

@{
   Html.RenderAction("Action", "Controller");
 }

J'en avais besoin pour une chaîne simple. Donc, mon action renvoie une chaîne et l'écrit facilement. Mais si vous avez besoin de données complexes, vous pouvez renvoyer PartialViewResult et model.

 public PartialViewResult Action()
    {
        var model = someList;
        return PartialView("~/Views/Shared/_maPartialView.cshtml", model);
    }

Il vous suffit de mettre votre modèle au début de la vue partielle '_maPartialView.cshtml' que vous avez créée

@model List<WhatEverYourObjeIs>

Ensuite, vous pouvez utiliser les données du modèle dans cette vue partielle avec html.

Burk
la source
18
C'est de loin la meilleure réponse!
gingerbreadboy
@gingerbreadboy a convenu qu'il favorise une bonne encapsulation et une séparation des préoccupations.
A-Dubb
35

Une autre option consiste à créer une classe LayoutModel distincte avec toutes les propriétés dont vous aurez besoin dans la mise en page, puis à remplir une instance de cette classe dans ViewBag. J'utilise la méthode Controller.OnActionExecuting pour le remplir. Ensuite, au début de la mise en page, vous pouvez retirer cet objet de ViewBag et continuer à accéder à cet objet fortement typé.

DenNukem
la source
1
Cela ressemble en fait à la solution la moins douloureuse, y a-t-il des inconvénients? +1
formatc
2
Certainement la meilleure solution et je ne vois aucun inconvénient.
Wiktor Zychla
7
Je ne vois pas ce que ça te donne. Si vous avez une classe avec toutes les propriétés dont vous avez besoin pour la mise en page, pourquoi l'ajouter au ViewBag seulement pour avoir à la relancer? Utilisez le modèle dans la vue de mise en page, vous pouvez toujours remplir le modèle dans OnActionExecuting. L'utilisation de ViewBag signifie également que vous perdez la sécurité du type dans votre contrôleur, ce n'est jamais une bonne chose.
Colin Bacon
3
Ce que cela me donne, c'est la possibilité d'ajouter un modèle pour la mise en page, sans avoir à restructurer tous les modèles pour hériter du seul "super" modèle dans toutes les méthodes de tous les contrôleurs, dans un projet qui existe déjà. Si vous partez de zéro, vous pouvez choisir de dériver tous vos modèles de la racine commune à la place.
DenNukem
5
@ColinBacon un autre avantage de cette option est que vos actions n'ont pas besoin de toujours avoir des modèles de vue. De plus, je dirais que les développeurs qui ont besoin de savoir qu'ils doivent toujours hériter de leurs modèles de vue d'une base est un inconvénient.
Josh Noe
28

Vraisemblablement, le cas d'utilisation principal pour cela est d'obtenir un modèle de base dans la vue pour toutes (ou la majorité) des actions de contrôleur.

Compte tenu de cela, j'ai utilisé une combinaison de plusieurs de ces réponses, le soutien principal de la réponse de Colin Bacon.

Il est exact qu'il s'agit toujours de la logique du contrôleur car nous remplissons un modèle de vue pour revenir à une vue. Ainsi, le bon endroit pour le mettre est dans le contrôleur.

Nous voulons que cela se produise sur tous les contrôleurs car nous l'utilisons pour la page de mise en page. Je l'utilise pour des vues partielles qui sont rendues dans la page de mise en page.

Nous souhaitons également bénéficier de l'avantage supplémentaire d'un ViewModel fortement typé

Ainsi, j'ai créé un BaseViewModel et un BaseController. Tous les contrôleurs ViewModels hériteront respectivement de BaseViewModel et BaseController.

Le code:

BaseController

public class BaseController : Controller
{
    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);

        var model = filterContext.Controller.ViewData.Model as BaseViewModel;

        model.AwesomeModelProperty = "Awesome Property Value";
        model.FooterModel = this.getFooterModel();
    }

    protected FooterModel getFooterModel()
    {
        FooterModel model = new FooterModel();
        model.FooterModelProperty = "OMG Becky!!! Another Awesome Property!";
    }
}

Notez l'utilisation de OnActionExecuted comme tiré de ce message SO

AccueilContrôleur

public class HomeController : BaseController
{
    public ActionResult Index(string id)
    {
        HomeIndexModel model = new HomeIndexModel();

        // populate HomeIndexModel ...

        return View(model);
    }
}

BaseViewModel

public class BaseViewModel
{
    public string AwesomeModelProperty { get; set; }
    public FooterModel FooterModel { get; set; }
}

HomeViewModèle

public class HomeIndexModel : BaseViewModel
{

    public string FirstName { get; set; }

    // other awesome properties
}

Modèle de pied de page

public class FooterModel
{
    public string FooterModelProperty { get; set; }
}

Layout.cshtml

@model WebSite.Models.BaseViewModel
<!DOCTYPE html>
<html>
<head>
    < ... meta tags and styles and whatnot ... >
</head>
<body>
    <header>
        @{ Html.RenderPartial("_Nav", Model.FooterModel.FooterModelProperty);}
    </header>

    <main>
        <div class="container">
            @RenderBody()
        </div>

        @{ Html.RenderPartial("_AnotherPartial", Model); }
        @{ Html.RenderPartial("_Contact"); }
    </main>

    <footer>
        @{ Html.RenderPartial("_Footer", Model.FooterModel); }
    </footer>

    < ... render scripts ... >

    @RenderSection("scripts", required: false)
</body>
</html>

_Nav.cshtml

@model string
<nav>
    <ul>
        <li>
            <a href="@Model" target="_blank">Mind Blown!</a>
        </li>
    </ul>
</nav>

Espérons que cela aide.

drizzie
la source
2
J'ai utilisé cette approche, mais je préfère hériter d'une interface plutôt que d'une classe de base. J'ai donc fait: var model = filterContext.Controller.ViewData.Model as IBaseViewModel if (model! = Null) {model.AwesomeModelProperty = "Awesome Property Value"; }
Tom Gerken
2
excellente réponse, j'ai préféré celui-ci à tous les autres.
Jynn
1
Excellente réponse, mais j'ai une question. "Et si j'ai des vues qui n'ont pas de ViewModels ...?"
Isma Haro
J'ai essayé ceci mais sur l'action d'index, OnActionExecuted remplit le FooterModel, puis un nouveau HomeIndexModel est créé avec un FooterModel nul :(
SteveCav
1
@drizzie: dans votre contrôleur de base, model est une variable locale dans la méthode Filter: var model = filterContext.Controller.ViewData.Model as BaseViewModel. Je ne comprends pas comment MVC comprend que cette variable locale est la même que le modèle que HomeController envoie à afficher.
Hooman Bahreini le
9

Vous n'avez pas à vous soucier des actions ou à modifier le modèle, utilisez simplement un contrôleur de base et transtypez le contrôleur existant à partir du contexte de la vue de disposition.

Créez un contrôleur de base avec les données communes souhaitées (titre / page / emplacement, etc.) et l'initialisation de l'action ...

public abstract class _BaseController:Controller {
    public Int32 MyCommonValue { get; private set; }

    protected override void OnActionExecuting(ActionExecutingContext filterContext) {

        MyCommonValue = 12345;

        base.OnActionExecuting(filterContext);
    }
}

Assurez-vous que chaque contrôleur utilise le contrôleur de base ...

public class UserController:_BaseController {...

Castez le contrôleur de base existant à partir du contexte de vue de votre _Layout.cshmlpage ...

@{
    var myController = (_BaseController)ViewContext.Controller;
}

Vous pouvez maintenant faire référence aux valeurs de votre contrôleur de base à partir de votre page de mise en page.

@myController.MyCommonValue

METTRE À JOUR

Vous pouvez également créer une extension de page qui vous permettrait d'utiliser this.

//Allows typed "this.Controller()." in cshtml files
public static class MyPageExtensions {
    public static _BaseController Controller(this WebViewPage page) => Controller<_BaseController>(page);
    public static T Controller<T>(this WebViewPage page) where T : _BaseController => (T)page.ViewContext.Controller;
}

Ensuite, vous ne devez vous rappeler de l'utiliser que this.Controller()lorsque vous voulez le contrôleur.

@{
    var myController = this.Controller(); //_BaseController
}

ou contrôleur spécifique qui hérite de _BaseController...

@{
    var myController = this.Controller<MyControllerType>();
}
Carter Medlin
la source
Quel est l'équivalent de cela dans .net core? Comme ViewContext.Controller n'est pas présent et il y a un changement dans la chaîne d'héritage
Jayanth Thyagarajan
4

si vous voulez passer un modèle entier, procédez comme suit dans la mise en page:

@model ViewAsModelBase
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta charset="utf-8"/>
    <link href="/img/phytech_icon.ico" rel="shortcut icon" type="image/x-icon" />
    <title>@ViewBag.Title</title>
    @RenderSection("styles", required: false)    
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
    @RenderSection("scripts", required: false)
    @RenderSection("head", required: false)
</head>
<body>
    @Html.Action("_Header","Controller", new {model = Model})
    <section id="content">
        @RenderBody()
    </section>      
    @RenderSection("footer", required: false)
</body>
</html>

et ajoutez ceci dans le contrôleur:

public ActionResult _Header(ViewAsModelBase model)
Manoir Yakir
la source
4

Je ne pense pas qu'aucune de ces réponses ne soit suffisamment flexible pour une application de niveau grande entreprise. Je ne suis pas fan de la surutilisation du ViewBag, mais dans ce cas, pour plus de flexibilité, je ferais une exception. Voici ce que je ferais ...

Vous devriez avoir un contrôleur de base sur tous vos contrôleurs. Ajoutez vos données de mise en page OnActionExecuting dans votre contrôleur de base (ou OnActionExecuted si vous souhaitez différer cela) ...

public class BaseController : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext     
        filterContext)
    {
        ViewBag.LayoutViewModel = MyLayoutViewModel;
    }
}

public class HomeController : BaseController
{
    public ActionResult Index()
    {
        return View(homeModel);
    }
}

Ensuite, dans votre _Layout.cshtml, tirez votre ViewModel du ViewBag ...

@{
  LayoutViewModel model = (LayoutViewModel)ViewBag.LayoutViewModel;
}

<h1>@model.Title</h1>

Ou...

<h1>@ViewBag.LayoutViewModel.Title</h1>

Cela n'interfère pas avec le codage des contrôleurs de votre page ou des modèles d'affichage.

Jack Sutherland
la source
J'aime votre idée mais qu'en est-il si vous avez une méthode MyLayoutViewModelcréée dynamiquement, comment puis-je passer certains paramètres à la OnActionExecutingméthode?
Rajmond Burgaj
1
Euh, vous en avez encore besoin base.OnActionExecuting(filterContext)dans votre OnActionExecutingméthode !!!
ErikE
4

Créer une vue de base qui représente le modèle de vue Mise en page est une approche terrible. Imaginez que vous vouliez avoir un modèle qui représente la navigation définie dans la mise en page. Feriez-vous CustomersViewModel : LayoutNavigationViewModel? Pourquoi? Pourquoi devriez-vous transmettre les données du modèle de navigation à chaque modèle de vue unique que vous avez dans la solution?

Le modèle de vue Mise en page doit être dédié, seul et ne doit pas forcer le reste des modèles de vue à en dépendre.

Au lieu de cela, vous pouvez le faire dans votre _Layout.cshtmlfichier:

@{ var model = DependencyResolver.Current.GetService<MyNamespace.LayoutViewModel>(); }

Plus important encore, nous n'en avons pas besoin new LayoutViewModel()et nous obtiendrons toutes les dépendances qui LayoutViewModelont été résolues pour nous.

par exemple

public class LayoutViewModel
{
    private readonly DataContext dataContext;
    private readonly ApplicationUserManager userManager;

    public LayoutViewModel(DataContext dataContext, ApplicationUserManager userManager)
    {
    }
}
Hyankov
la source
Où remplissez-vous ce modèle? Dans un BaseController également?
ndberg
J'imagine que ce serait également une bonne idée pour un Scopedobjet de modèle de disposition dans ASP..Net Core.
James Wilkins
Je n'aurais pas la vue d'aller chercher une dépendance. Ce n'est certainement pas "MVC". Service Locator est un anti-pattern .
Jiveman le
Contrairement à la croyance populaire, Service Locator n'est pas un anti-pattern et en fait cela n'a rien à voir avec MVC, lancez-vous juste des mots à la mode @Jiveman? blog.gauffin.org/2012/09/service-locator-is-not-an-anti-pattern
hyankov
Le point principal de Jgauffin dans cet article semble être que le terme «anti-pattern» ne devrait pas être appliqué à Service Locator, car il peut y avoir au moins quelques utilisations valides de SL. Un bon point. Cependant, comme cela est évident dans certains de ses propres commentaires de discussion, il suggère que si SL peut être une approche valable lors de la construction de bibliothèques et de cadres, elle n'est pas nécessairement recommandée lors de la construction d'applications (ce que je considérerais comme la question d'OP et cette discussion ici tournant autour).
Jiveman
3

D'autres réponses ont couvert à peu près tout sur la façon dont nous pouvons transmettre le modèle à notre page de mise en page. Mais j'ai trouvé un moyen de transmettre dynamiquement des variables à votre page de mise en page sans utiliser de modèle ni de vue partielle dans votre mise en page. Disons que vous avez ce modèle -

public class SubLocationsViewModel
{
    public string city { get; set; }
    public string state { get; set; }
}

Et vous voulez obtenir dynamiquement la ville et l'état. Pour par exemple

dans votre index.cshtml vous pouvez mettre ces deux variables dans ViewBag

@model  MyProject.Models.ViewModel.SubLocationsViewModel
@{
    ViewBag.City = Model.city;
    ViewBag.State = Model.state;
}

Et puis dans votre layout.cshtml, vous pouvez accéder à ces variables viewbag

<div class="text-wrap">
    <div class="heading">@ViewBag.City @ViewBag.State</div>
</div>
Chirag K
la source
cela fonctionne très bien, @stun_Gravy y a-t-il une chute en utilisant ViewBag pour transmettre des données comme le rôle ou le niveau d'accès des utilisateurs?
3not3
3

Il existe une autre façon de gérer cela. Ce n'est peut-être pas le moyen le plus propre d'un point de vue architectural, mais cela évite beaucoup de douleur associée aux autres réponses. Injectez simplement un service dans la disposition Razor, puis appelez une méthode qui obtient les données nécessaires:

@inject IService myService

Puis plus tard dans la vue de mise en page:

@if (await myService.GetBoolValue()) {
   // Good to go...
}

Encore une fois, pas propre en termes d'architecture (évidemment le service ne doit pas être injecté directement dans la vue), mais il fait le travail.

Andrew
la source
Pas la manière la plus propre? Je ne suis pas d'accord. Je pense que c'est aussi propre que possible: l'objet est passé de l'endroit où il est créé directement à l'endroit où vous voulez qu'il soit, sans «polluer» les autres contrôleurs avec des éléments qu'ils n'ont pas besoin de voir. L'utilisation @injectest la meilleure solution, à mon avis.
dasblinkenlight
1
En y réfléchissant davantage, vous avez peut-être raison. Le fait que cette méthode évite tant de douleur est un signe que c'est peut-être la manière la plus propre. J'ai travaillé sur une très grande application ASP.NET Core et j'utilise ce modèle pour des choses comme la logique de navigation dans le fil d'Ariane, les données d'en-tête qui se trouvent sur la plupart des pages, des choses comme ça. J'ai évité tellement de douleur en le faisant de cette façon à la place.
Andrew
2

Vous pouvez également utiliser RenderSection , il vous aide à injecter vos Modeldonnées dans la _Layoutvue.

Vous pouvez injecter des View Modeldonnées, Json, Script, CSS, HTMLetc.

Dans cet exemple, j'injecte Jsonde ma Indexvue à Layoutvue.

Index.chtml

@section commonLayoutData{

    <script>

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

    </script>

    }

_Layout.cshtml

@RenderSection("commonLayoutData", false)

Cela élimine le besoin de créer une base séparée View Model .

L'espoir aide quelqu'un.

shaijut
la source
1
Solution parfaite lorsque vous ne devez rendre quelque chose de spécifique pour quelques points de vue.
Kunal
1

ce que j'ai fait est très simple et ça marche

Déclarez la propriété Static dans n'importe quel contrôleur ou vous pouvez créer une classe de données avec des valeurs statiques si vous le souhaitez:

public static username = "Admin";
public static UserType = "Administrator";

Ces valeurs peuvent être mises à jour par les contrôleurs en fonction des opérations. plus tard, vous pourrez les utiliser dans votre _Layout

Dans _layout.cshtml

@project_name.Controllers.HomeController.username
@project_name.Controllers.HomeController.UserType
Affaires électroniques
la source
1
Il est toujours utile d'ajouter quelques explications à votre réponse, pour la rendre plus claire et compréhensible. Veuillez lire stackoverflow.com/help/how-to-answer .
32cupo le
0

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

Option 1

Cela me semble de loin la solution la moins intrusive et la plus simple au problème. Pas de chaînes codées en dur. Aucune restriction imposée. 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 2

Une autre option, facilitant la déclaration du champ.

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éfinissez 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 3

Ensuite, vous pouvez combiner cela avec le renvoi d'un seul objet 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 que c'est la meilleure option dans la plupart des cas:

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

  • 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 ViewData (par exemple, mise en page, en-tête, navigation).

  • Autorise du code et une logique supplémentaires dans la classe LayoutData.

PS N'oubliez pas d'ajouter l'espace de noms de ViewDataExtensions dans _ViewImports.cshtml

Etienne Charland
la source
0

Vous pouvez créer un fichier rasoir dans le dossier App_Code, puis y accéder à partir de vos pages d'affichage.

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> Views / Shared / _Layout.cshtml (ou tout autre fichier .cshtml)

<div>
    @IdentityRepositoryViewFunctions.GetCurrentUserName
</div>
Joël Wiklund
la source
-1

au lieu de passer par là, vous pouvez toujours utiliser une autre approche qui est également rapide

créer une nouvelle vue partielle dans le répertoire partagé et appeler votre vue partielle dans votre mise en page comme

@Html.Partial("MyPartialView")

dans votre vue partielle, vous pouvez appeler votre base de données et effectuer ce que vous voulez faire

@{
    IEnumerable<HOXAT.Models.CourseCategory> categories = new HOXAT.Models.HOXATEntities().CourseCategories;
}

<div>
//do what ever here
</div>

en supposant que vous avez ajouté votre base de données Entity Framework

Asad Ali
la source
1
Downcasting car il ne devrait jamais être de la responsabilité de la vue d'obtenir son propre modèle.
Oxonhammer
-1

C'est incroyable que personne n'ait dit cela ici. Passer un viewmodel à travers un contrôleur de base est un gâchis. Nous utilisons les revendications des utilisateurs pour transmettre des informations à la page de mise en page (pour afficher les données de l'utilisateur sur la barre de navigation par exemple). Il y a un autre avantage. Les données sont stockées via des cookies, il n'est donc pas nécessaire de récupérer les données dans chaque demande via des partiels. Faites juste quelques "revendications d'identité asp net" sur Google.

Makore
la source
@CodeSmith quoi? Je propose une solution.
makore
Mon mauvais, j'ai pensé que c'était une question mais voyez que c'est une réponse maintenant, supprimée.
CodeSmith
S'il s'agit d'une tentative de répondre à la question, il convient de le clarifier. Le commentaire est toléré mais il ne devrait pas dominer toute la réponse; De plus, les conseils sur ce qu'il faut google ne constituent pas une réponse valable.
triple
-6

Vous pouvez utiliser comme ceci:

 @{ 
    ApplicationDbContext db = new ApplicationDbContext();
    IEnumerable<YourModel> bd_recent = db.YourModel.Where(m => m.Pin == true).OrderByDescending(m=>m.ID).Select(m => m);
}
<div class="col-md-12">
    <div class="panel panel-default">
        <div class="panel-body">
            <div class="baner1">
                <h3 class="bb-hred">Recent Posts</h3>
                @foreach(var item in bd_recent)
                {
                    <a href="/BaiDangs/BaiDangChiTiet/@item.ID">@item.Name</a>
                }
            </div>
        </div>
    </div>
</div>
Ngô Đức Tuấn
la source
7
Se connecter avec la base de données en vue est vraiment une mauvaise idée.
1_bug