모든 페이지에 공통적 인 레이아웃으로 데이터 전달


124

레이아웃 페이지가있는 웹 사이트가 있습니다. 그러나이 레이아웃 페이지에는 모든 페이지 모델이 이러한 페이지 제목, 페이지 이름 및 일부 작업을 수행하는 HTML 도우미에 대한 실제 위치를 제공해야하는 데이터가 있습니다. 또한 각 페이지에는 고유 한보기 모델 속성이 있습니다.

어떻게 할 수 있습니까? 레이아웃을 입력하는 것은 나쁜 생각 인 것 같지만이 정보를 어떻게 전달합니까?


10
여기에서 답글을 읽는 사람은 stackoverflow.com/a/21130867/706346을 참조하십시오. 여기에 게시 된 것보다 훨씬 간단하고 깔끔한 솔루션을 볼 수 있습니다.
Avrohom Yisroel

5
@AvrohomYisroel 좋은 제안입니다. 그러나 @Colin Bacon의 접근 방식을 선호하는 이유는 ViewBag. 아마도 선호도의 문제 일 것입니다. Upvoted 귀하의 코멘트하지만
JP Hellemons

MVC (5)이 대답을 참조하십시오 stackoverflow.com/a/46783375/5519026
라즈 Ziya

답변:


143

각 페이지에 동일한 속성을 전달해야하는 경우 모든 뷰 모델에서 사용하는 기본 뷰 모델을 만드는 것이 좋습니다. 그러면 레이아웃 페이지에서이 기본 모델을 사용할 수 있습니다.

이 데이터 뒤에 로직이 필요한 경우 모든 컨트롤러에서 사용하는 기본 컨트롤러에이를 입력해야합니다.

여러분이 할 수있는 일이 많이 있으며, 중요한 접근 방식은 여러 곳에서 동일한 코드를 반복하지 않는 것입니다.

편집 : 아래 댓글에서 업데이트

다음은 개념을 보여주는 간단한 예입니다.

모든 뷰 모델이 상속 할 기본 뷰 모델을 만듭니다.

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

public class HomeViewModel : ViewModelBase
{
}

레이아웃 페이지는이를 모델로 사용할 수 있습니다.

@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>

마지막으로 액션 메서드에서 데이터를 설정합니다.

public class HomeController
{
    public ActionResult Index()
    {
        return this.View(new HomeViewModel { Name = "Bacon" });
    }
}

12
그러나 데이터는 레이아웃에 사용됩니다. 데이터를 레이아웃에 어떻게 전달할 수 있습니까?
Rushino 2011

2
완전한! 내 오류를 보았다. 보기에 모델을 전달하는 것을 잊었습니다. 감사!
Rushino 2011

7
이 접근 방식의 문제는 때때로 모든 뷰에 ViewModel이있는 것은 아니므로이 경우에는 작동하지 않습니다. O /
Cacho Santa

16
하지만 이렇게하려면 모든 컨트롤러와 모든 작업에 {Name = "Bacon"} 코드가 포함되어야하지 않습니까? ViewModelBase에 다른 속성을 추가하려면 모든 컨트롤러와 모든 작업으로 이동하여 해당 속성을 채우는 코드를 추가해야합니까? "만약 로직이 필요한 경우 [...] 이것은 기본 컨트롤러에 넣어야합니다 [...]"라고 언급하셨습니다. 모든 컨트롤러와 모든 작업에서 반복되는 코드를 제거하기 위해 어떻게 작동할까요?
Lee

5
@Lee 모든 페이지에서 공통 데이터 인 경우 기본 컨트롤러가 여기에 있습니다. 그러면 컨트롤러가이 기본 컨트롤러에서 상속됩니다. 예 : public class HomeController : BaseController. 이렇게하면 공통 코드를 한 번만 작성하면 모든 컨트롤러에 적용 할 수 있습니다.
Colin Bacon

73

레이아웃에서 면도기에 RenderAction html 도우미를 사용했습니다.

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

간단한 문자열에 필요했습니다. 그래서 내 행동은 문자열을 반환하고보기에 쉽게 기록합니다. 그러나 복잡한 데이터가 필요한 경우 PartialViewResult 및 모델을 반환 할 수 있습니다.

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

생성 한 부분보기 '_maPartialView.cshtml'로 시작하는 모델을 넣으면됩니다.

@model List<WhatEverYourObjeIs>

그런 다음 html로 부분보기에서 모델의 데이터를 사용할 수 있습니다.


18
이것은 단연코 최고의 답변입니다!
gingerbreadboy

@gingerbreadboy는 좋은 캡슐화와 우려 사항 분리를 촉진하는 데 동의했습니다.
A-Dubb

35

또 다른 옵션은 레이아웃에 필요한 모든 속성을 포함하는 별도의 LayoutModel 클래스를 만든 다음이 클래스의 인스턴스를 ViewBag에 채우는 것입니다. Controller.OnActionExecuting 메서드를 사용하여 채 웁니다. 그런 다음 레이아웃 시작시 ViewBag에서이 개체를 다시 가져 와서이 강력한 형식의 개체에 계속 액세스 할 수 있습니다.


1
이것은 실제로 가장 고통스럽지 않은 해결책처럼 들립니다. 단점이 있습니까? +1
formatc 2015

2
확실히 최고의 솔루션이며 단점은 없습니다.
Wiktor Zychla

7
나는 이것이 당신에게주는 것을 보지 못합니다. 레이아웃에 필요한 모든 속성이있는 클래스가있는 경우 ViewBag에 추가하여 다시 캐스팅해야하는 이유는 무엇입니까? 레이아웃보기에서 모델을 사용하여에서 모델을 채울 수 있습니다 OnActionExecuting. ViewBag를 사용하면 컨트롤러의 유형 안전성이 느슨해지며 결코 좋지 않습니다.
Colin Bacon

3
이것이 내게주는 것은 이미 존재하는 프로젝트에서 모든 컨트롤러의 모든 방법에서 단일 "수퍼"모델로부터 상속하기 위해 모든 모델을 재구성하지 않고도 레이아웃 용 모델을 추가 할 수 있다는 것입니다. 처음부터 시작하는 경우 대신 공통 루트에서 모든 모델을 파생하도록 선택할 수 있습니다.
DenNukem

5
@ColinBacon이 옵션의 또 다른 장점은 액션이 항상 뷰 모델을 가질 필요가 없다는 것입니다. 또한 개발자가 항상 기본에서 뷰 모델을 상속해야한다는 것을 알아야하는 것은 단점이라고 생각합니다.
Josh Noe 2015

28

아마도 이것의 주요 사용 사례는 모든 (또는 대부분의) 컨트롤러 작업에 대한보기에 기본 모델을 가져 오는 것입니다.

이를 감안할 때 저는 이러한 답변 중 몇 가지를 조합하여 사용했습니다. Colin Bacon의 답변에 대한 기본 지원입니다.

뷰로 돌아 가기 위해 뷰 모델을 채우고 있기 때문에 이것이 여전히 컨트롤러 로직이라는 것은 맞습니다. 따라서 이것을 놓을 올바른 위치는 컨트롤러에 있습니다.

우리는 레이아웃 페이지에 이것을 사용하기 때문에 모든 컨트롤러에서 이것이 일어나기를 원합니다. 레이아웃 페이지에서 렌더링되는 부분보기에 사용하고 있습니다.

우리는 또한 강력한 형식의 ViewModel의 추가 이점을 원합니다.

따라서 BaseViewModel과 BaseController를 만들었습니다. 모든 ViewModels 컨트롤러는 BaseViewModel 및 BaseController에서 각각 상속됩니다.

코드:

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!";
    }
}

이 SO 게시물 에서 가져온 OnActionExecuted 사용에 유의하십시오.

HomeController

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; }
}

HomeViewModel

public class HomeIndexModel : BaseViewModel
{

    public string FirstName { get; set; }

    // other awesome properties
}

FooterModel

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>

도움이 되었기를 바랍니다.


2
이 접근 방식을 사용했지만 기본 클래스보다는 인터페이스에서 상속하는 것을 선호합니다. 그래서 저는 다음과 같이했습니다. var model = filterContext.Controller.ViewData.Model as IBaseViewModel if (model! = null) {model.AwesomeModelProperty = "Awesome Property Value"; }
Tom Gerken

2
좋은 대답, 나는 다른 모든 것보다 이것을 선호했습니다.
Jynn

1
좋은 대답이지만 질문이 있습니다. "ViewModels가없는 뷰가있는 경우 ...?"
Isma Haro

이 시도하지만 색인 작업에 OnActionExecuted는 :( 널 FooterModel으로 FooterModel을 채우고 다음 새 HomeIndexModel가 생성
SteveCav

1
@drizzie : 기본 컨트롤러에서 model은 Filter 메서드의 로컬 변수입니다. var model = filterContext.Controller.ViewData.Model as BaseViewModel. MVC 가이 지역 변수가 HomeController 가보기에 보내는 모델과 동일하다는 것을 어떻게 이해하는지 이해하지 못합니다.
Hooman Bahreini

9

액션을 엉망으로 만들거나 모델을 변경할 필요가 없습니다. 기본 컨트롤러를 사용하고 레이아웃 뷰 컨텍스트에서 기존 컨트롤러를 캐스팅하면됩니다.

원하는 공통 데이터 (제목 / 페이지 / 위치 등) 및 작업 초기화로 기본 컨트롤러를 만듭니다.

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

    protected override void OnActionExecuting(ActionExecutingContext filterContext) {

        MyCommonValue = 12345;

        base.OnActionExecuting(filterContext);
    }
}

모든 컨트롤러가 기본 컨트롤러를 사용하는지 확인하십시오 ...

public class UserController:_BaseController {...

_Layout.cshml페이지 의보기 컨텍스트에서 기존 기본 컨트롤러를 캐스트 하십시오.

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

이제 레이아웃 페이지에서 기본 컨트롤러의 값을 참조 할 수 있습니다.

@myController.MyCommonValue

최신 정보

을 (를) 사용할 수있는 페이지 확장을 만들 수도 있습니다 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;
}

그런 다음 this.Controller()컨트롤러를 원할 때만 사용하는 것을 기억 하면됩니다.

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

또는 상속받은 특정 컨트롤러 _BaseController...

@{
    var myController = this.Controller<MyControllerType>();
}

.net 코어에서 이것과 동등한 것은 무엇입니까? ViewContext.Controller가 존재하지 않고 상속 체인에 약간의 변경이 있기 때문에
Jayanth Thyagarajan

4

전체 모델을 전달하려면 레이아웃에서 다음과 같이 이동하십시오.

@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>

컨트롤러에 다음을 추가합니다.

public ActionResult _Header(ViewAsModelBase model)

4

이러한 답변 중 어떤 것도 대기업 수준의 응용 프로그램에 충분히 유연하다고 생각하지 않습니다. 나는 ViewBag를 남용하는 것을 좋아하지 않지만,이 경우 유연성을 위해 예외를 만들 것입니다. 내가 할 일은 ...

모든 컨트롤러에 기본 컨트롤러가 있어야합니다. 기본 컨트롤러에 레이아웃 데이터 OnActionExecuting을 추가합니다 (또는 연기하려는 경우 OnActionExecuted).

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

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

그런 다음 _Layout.cshtml에서 ViewBag에서 ViewModel을 가져옵니다.

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

<h1>@model.Title</h1>

또는...

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

이렇게해도 페이지의 컨트롤러 또는 뷰 모델에 대한 코딩이 방해되지 않습니다.


나는 당신의 아이디어를 좋아하지만 MyLayoutViewModel동적으로 생성 된 경우 어떻게 매개 변수를 OnActionExecuting메서드에 전달할 수 있습니까?
Rajmond Burgaj

1
어, 당신은 여전히 base.OnActionExecuting(filterContext)당신의 OnActionExecuting방법에 필요 합니다 !!!
ErikE apr

4

레이아웃보기 모델을 나타내는 기본보기를 만드는 것은 끔찍한 접근 방식입니다. 레이아웃에 정의 된 탐색을 나타내는 모델을 갖고 싶다고 상상해보십시오. 하시겠습니까 CustomersViewModel : LayoutNavigationViewModel? 왜? 솔루션에있는 모든 단일보기 모델을 통해 탐색 모델 데이터를 전달해야하는 이유는 무엇입니까?

레이아웃 뷰 모델은 그 자체로 전용이어야하며 나머지 뷰 모델이 의존하도록 강요해서는 안됩니다.

대신 _Layout.cshtml파일 에서 다음을 수행 할 수 있습니다 .

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

가장 중요한 것은 그럴 필요가 없으며 해결 된 new LayoutViewModel()모든 종속성을 얻을 수 있다는 LayoutViewModel것입니다.

예 :

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

    public LayoutViewModel(DataContext dataContext, ApplicationUserManager userManager)
    {
    }
}

이 모델을 어디에 채우십니까? BaseController에서도?
ndberg

ScopedASP..Net Core 의 레이아웃 모델 개체에도 이것이 좋은 생각이라고 생각 합니다.
James Wilkins

나는 전망이 의존성을 가져 오지 않을 것입니다. 그것은 확실히 "MVC"가 아닙니다. 서비스 로케이터는 안티 패턴 입니다.
Jiveman

대중적인 믿음과는 달리, Service Locator는 안티 패턴이 아니며 실제로 이것은 MVC와 관련이 없습니다. @Jiveman이라는 유행어를 던지고 있습니까? blog.gauffin.org/2012/09/service-locator-is-not-an-anti-pattern
hyankov

이 기사에서 Jgauffin의 요점은 "반 패턴"이라는 용어가 서비스 로케이터에 적용되어서는 안된다는 것 같습니다. SL의 유효한 사용이 적어도 일부있을 수 있기 때문입니다. 공정한 요점. 그러나 자신의 토론 의견 중 일부에서 분명히 알 수 있듯이 SL은 라이브러리와 프레임 워크를 구축 할 때 유효한 접근 방식 일 수 있지만 응용 프로그램을 구축 할 때 반드시 권장되는 것은 아니라고 제안합니다 (OP의 질문과이 논의는 여기에서 회전).
Jiveman

3

다른 답변은 레이아웃 페이지에 모델을 전달하는 방법에 대한 거의 모든 것을 다룹니다. 그러나 레이아웃에서 모델이나 부분보기를 사용하지 않고 변수를 레이아웃 페이지에 동적으로 전달할 수있는 방법을 찾았습니다. 이 모델이 있다고 가정 해 봅시다.

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

그리고 당신은 동적으로 도시와 주를 얻고 싶습니다. 예를 들어

index.cshtml에서이 두 변수를 ViewBag에 넣을 수 있습니다.

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

그런 다음 layout.cshtml에서 해당 뷰백 변수에 액세스 할 수 있습니다.

<div class="text-wrap">
    <div class="heading">@ViewBag.City @ViewBag.State</div>
</div>

이것은 훌륭하게 작동합니다. @stun_Gravy ViewBag를 사용하여 역할 또는 사용자 액세스 수준과 같은 데이터를 전달하는 데 실패가 있습니까?
3not3 2017-08-30

3

이것을 처리하는 다른 방법이 있습니다. 아키텍처 관점에서 볼 때 가장 깨끗한 방법은 아니지만 다른 답변과 관련된 많은 고통을 피할 수 있습니다. Razor 레이아웃에 서비스를 삽입 한 다음 필요한 데이터를 가져 오는 메서드를 호출하기 만하면됩니다.

@inject IService myService

그런 다음 나중에 레이아웃보기에서 :

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

다시 말하지만, 아키텍처 측면에서 깨끗하지는 않지만 (분명히 서비스는 뷰에 직접 삽입되어서는 안됩니다) 작업이 완료됩니다.


가장 깨끗한 방법이 아닙니까? 동의하지 않습니다. 나는 이것이 얻을 수있는 것처럼 깨끗하다고 ​​생각한다. 객체는 그들이 볼 필요가없는 아이템으로 다른 컨트롤러를 "오염"시키지 않고, 그것이 생성 된 곳에서 원하는 곳으로 곧바로 전달된다. @inject제 생각에는 사용 이 최선의 해결책입니다.
dasblinkenlight

1
이것에 대해 더 생각하면 아마도 당신이 맞을 것입니다. 이 방법이 너무 많은 고통을 피한다는 사실은 아마도 가장 깨끗한 방법이라는 신호입니다. 저는 매우 큰 ASP.NET Core 앱에서 작업 해 왔으며 탐색 탐색 경로 논리, 대부분의 페이지에있는 헤더 데이터 등과 같은 작업에이 패턴을 사용하고 있습니다. 대신 이런 식으로 그렇게함으로써 많은 고통을 피했습니다.
Andrew

2

RenderSection 을 사용할 수도 있습니다. 뷰에 Model데이터 를 삽입하는 데 도움이됩니다 _Layout.

당신은 삽입 할 수 View Model데이터, Json, Script, CSS, HTML

이 예에서는 뷰에서 뷰로 주입 Json하고 있습니다.IndexLayout

Index.chtml

@section commonLayoutData{

    <script>

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

    </script>

    }

_Layout.cshtml

@RenderSection("commonLayoutData", false)

이렇게하면 별도의 Base를 만들 필요가 없습니다 View Model.

희망은 누군가를 돕습니다.


1
당신은 완벽한 솔루션 에만 몇 뷰 뭔가 특정 렌더링 할 필요가있다.
Kunal

1

내가 한 일은 매우 간단하고 작동합니다

컨트롤러에서 Static 속성을 선언하거나 다음과 같이 원하는 경우 정적 값으로 데이터 클래스를 만들 수 있습니다.

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

이러한 값은 작업에 따라 컨트롤러에서 업데이트 할 수 있습니다. 나중에 _Layout에서 사용할 수 있습니다.

_layout.cshtml에서

@project_name.Controllers.HomeController.username
@project_name.Controllers.HomeController.UserType

1
더 명확하고 이해하기 쉽게 답변에 설명을 추가하는 것은 항상 도움이됩니다. stackoverflow.com/help/how-to-answer를 읽어 보세요.
32cupo

0

왜 아무도 ViewData에 대한 확장 방법을 제안하지 않았습니까?

옵션 1

문제에 대한 가장 덜 방해가되지 않고 가장 간단한 해결책 인 것 같습니다. 하드 코딩 된 문자열이 없습니다. 부과 된 제한이 없습니다. 매직 코딩이 없습니다. 복잡한 코드가 없습니다.

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] ?? "";
}

페이지에서 데이터 설정

ViewData.SetTitle("abc");

옵션 # 2

필드 선언을 더 쉽게 만드는 또 다른 옵션입니다.

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;
    }
}

페이지에서 데이터를 설정합니다. 선언은 첫 번째 옵션보다 쉽지만 사용 구문은 약간 더 깁니다.

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

옵션 # 3

그런 다음 모든 레이아웃 관련 필드를 기본값으로 포함하는 단일 개체를 반환하는 것과 결합 할 수 있습니다.

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; } = "";
}

페이지에서 데이터 설정

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

이 세 번째 옵션에는 몇 가지 이점이 있으며 대부분의 경우 최상의 옵션이라고 생각합니다.

  • 필드 및 기본값의 가장 간단한 선언.

  • 여러 필드를 설정할 때 가장 간단한 사용 구문입니다.

  • ViewData에서 다양한 종류의 데이터를 설정할 수 있습니다 (예 : Layout, Header, Navigation).

  • LayoutData 클래스 내에서 추가 코드 및 로직을 허용합니다.

추신 : _ViewImports.cshtml에 ViewDataExtensions의 네임 스페이스를 추가하는 것을 잊지 마십시오.


0

App_Code 폴더에 razor 파일을 만든 다음보기 페이지에서 액세스 할 수 있습니다.

프로젝트> 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;
        }
    }
}

프로젝트> 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;
        }
    }
}

Project> Views / Shared / _Layout.cshtml (또는 기타 .cshtml 파일)

<div>
    @IdentityRepositoryViewFunctions.GetCurrentUserName
</div>

-1

이 과정을 거치지 않고 항상 빠른 다른 접근 방식을 사용할 수 있습니다.

공유 디렉토리에 새 부분보기를 만들고 레이아웃에서 부분보기를 다음과 같이 호출합니다.

@Html.Partial("MyPartialView")

부분보기에서 db를 호출하고 원하는 작업을 수행 할 수 있습니다.

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

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

Entity Framework 데이터베이스를 추가했다고 가정합니다.


1
자체 모델을 획득하는 것이 뷰의 책임이되어서는 안되는 다운 캐스팅.
Oxonhammer

-1

여기에서 아무도 이것을 말하지 않았다는 것이 놀랍습니다. 기본 컨트롤러를 통해 뷰 모델을 전달하는 것은 엉망입니다. 사용자 클레임 을 사용 하여 레이아웃 페이지에 정보를 전달합니다 (예 : navbar에 사용자 데이터 표시). 또 하나의 이점이 있습니다. 데이터는 쿠키를 통해 저장되므로 부분을 통해 각 요청에서 데이터를 검색 할 필요가 없습니다. 인터넷 검색 "asp net identity claim"을 수행하십시오.


@CodeSmith 뭐? 나는 해결책을 제공하고 있습니다.
makore

내 잘못은 이것이 질문이라고 생각했지만 지금은 답변이 삭제되었습니다.
CodeSmith

이것이 질문에 답하려는 시도라면 명확히해야합니다. 주석은 용인되지만 전체 답변을 지배해서는 안됩니다. 또한 Google에 대한 도움말은 유효한 답변이 아닙니다.
tripleee

-6

다음과 같이 사용할 수 있습니다.

 @{ 
    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>

7
보기에서 데이터베이스와 연결하는 것은 정말 나쁜 생각입니다.
1_bug
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.