Как выставить глобальный объект, например @User, в виде бритвы?
Как/Где я могу объявить объект, такой как @User, чтобы он мог ссылаться глобально в любом виде бритвы, используя @?
Нечто похожее на:
_LoginPartial.cshtml:
@if(Request.IsAuthenticated) {
<text>Signed In As <strong>@User.Identity.Name</strong> |
но вместо этого ссылайтесь на мой объект:
@if(this && that) { <text>@MyObject.GetData</text> }
Ответы
Ответ 1
Вы можете изменить базовый тип страницы Razor на свой собственный, например:
public class UserAwareViewPage : System.Web.Mvc.WebViewPage
{
public IPrincipal User { get { return Thread.CurrentPrincipal; } }
}
И затем измените свой файл конфигурации следующим образом:
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory,
System.Web.Mvc, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="Your.Namespace.UserAwareViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
</namespaces>
</pages>
</system.web.webPages.razor>
Фил Хаак имеет очень хорошее сообщение в блоге об этом здесь.
В качестве альтернативы вы можете добавить метод расширения System.Web.Mvc.WebViewPage
(базовый тип для бритвенных страниц) и использовать его.
public static IPrincipal User(this System.Web.Mvc.WebViewPage page)
{
return Thread.CurrentPrincipal;
}
Что можно использовать так:
@if(Request.IsAuthenticated) {
<text>Signed In As <strong>@User().Identity.Name</strong>
Лично я предпочитаю первый подход, но думал, что я предоставил второй вариант для альтернативного варианта.
Ответ 2
Синтаксис @
никак не ссылается на значения, он просто указывает механизму представления, что вы начинаете блок кода на стороне сервера.
В этом нет ничего "глобального". В этом случае User
является свойством в абстрактном классе System.Web.WebPages.WebPageRenderingBase
, который используется механизмом просмотра при визуализации представлений как они наследуют от него.
Я предполагаю, что вы можете расширить классы WebViewPage
или WebViewPage<>
, чтобы добавить к ним свойства. Однако может быть лучший способ добиться того, что вы пытаетесь сделать, не изменяя их. Если вы пытаетесь передать данные в представление, не должны ли эти данные быть частью ViewModel?
В идеале вы должны предоставить все потребности View в пользовательской ViewModel, и View наследует от WebViewPage<CustomViewModel>
.
В синтаксисе Razor я думаю, что вы начнете CSHTML с чем-то вроде:
@model CustomViewModel
Затем вы получите доступ к свойствам, использующим свойство Model
:
@Model.SomeProperty
Ответ 3
Возможно, вы можете сделать что-то подобное в своем представлении:
@Html.ViewContext.HttpContext.User.Identity.Name
Я бы рекомендовал против этого, и добавьте эту информацию в ViewModel. Например:
public ActionResult SomeController()
{
var model = new MyViewModel
{
Username = User.Identity.Name
}
return View(model);
}
Теперь в представлении вы можете отобразить эту информацию:
@Model.Username
Ответ 4
Или для менее навязчивого подхода, и это работает для любой страницы Razor просто по умолчанию:
@Context.User.Identity.IsAuthenticated
Конечно, вы можете настроить быстрый псевдоним переменной, если вам нравится в верхней части вашего файла Razor (_Layout или иначе):
@{
var User = Context.User;
}
но на самом деле ненужно, если у вас нет объекта custome IPrincipal
в этом случае:
@{
var User = (MyAuthenticatedUser)Context.User;
}
и это работает, и я использую:)