MVC 6 @inherit RazorPage
MVC 6 @inherit RazorPage
我正在尝试将 MVC 5 应用程序迁移到 ASP.NET 5 MVC 6 (Beta 7)。
同时使用 @inherits
和 @model
指令时出现问题。
单独使用时效果很好。
在我的 _ViewImports
中,我添加了 @inherits
指令以使用具有一些自定义用户属性的基页。
public abstract class BaseViewPage<TModel> : RazorPage<TModel>
{
protected MyPrincipal AppUser
{
get
{
return new MyPrincipal(this.User as ClaimsPrincipal);
}
}
}
_ViewImports.cshttml
@inherits CommonWeb.BaseViewPage<TModel>
@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
然后我就可以进入 AppUser. 我所有的观点。
如果我 不 使用强类型视图,这将起作用。如果我在任何视图中添加 @model
指令,继承的视图页面就会消失。
感谢帮助
更新:
我通过在先前版本的 web.config 中使用自定义 pageBaseType 成功地做到了这一点。
解决方法。
public class ViewHelper
{
ViewContext _context;
public ViewHelper(ViewContext context)
{
_context = context;
}
public MyPrincipal AppUser
{
get
{
return new MyPrincipal(_context.HttpContext.User as ClaimsPrincipal);
}
}
public string ControllerName
{
get
{
return _context.RouteData.Values["controller"].ToString();
}
}
}
查看:
@{ var viewHelper = new ViewHelper(ViewContext);}
有一种方法可以实现所有视图?
MVC 6 中有一个更好的方法,它现在支持 injecting dependencies 在视图上使用 @inject
指令。 (指令 @inject IFoo Foo
允许您在视图中使用类型为 IFoo
的名为 Foo
的 属性)
创建一个新界面IAppUserAccessor
来获取您的应用用户,例如:
public interface IAppUserAccessor
{
MyPrincipal GetAppUser();
}
创建一个 class AppUserAccessor
实现它:
public class AppUserAccessor : IAppUserAccessor
{
private IHttpContextAccessor httpContextProvider;
public AppUserAccessor(IHttpContextAccessor httpContextProvider)
{
this.httpContextProvider = httpContextProvider;
}
public MyPrincipal GetAppUser()
{
return new MyPrincipal (
httpContextProvider.HttpContext.User as ClaimsPrincipal);
}
}
通过在 Startup.cs:
的 ConfigureServices
方法中添加一个新条目,在服务容器中注册新接口
services.AddTransient<IAppUserAccessor, AppUserAccessor>();
最后使用 @inject
指令在您的视图中注入 IAppUserAccessor
。 如果您在 ViewImports.cshtml
中添加指令,那么它将在每个视图中可用 。
@inject WebApplication4.Services.IAppUserAccessor AppUserAccessor
有了上面的所有内容,您现在可以只在您的视图中使用它了:
@AppUserAccessor.GetAppUser()
更新
如果你需要检查路由值,比如控制器名称,你可以在你的 class 中注入一个 IActionContextAccessor
并按如下方式使用它:
public AppUserAccessor(IHttpContextAccessor httpContextProvider, IActionContextAccessor actionContextAccessor)
{
this.httpContextProvider = httpContextProvider;
this.actionContextAccessor = actionContextAccessor;
}
...
public string ControllerName
{
get { return actionContextAccessor.ActionContext.RouteData.Values["controller"].ToString(); }
}
当然,它看起来不再像 AppUserAccessor
,而且闻起来好像它有不同的职责。至少它需要一个更合适的名字:)
我会仔细检查我需要控制器名称做什么。可能有更好的方法来完成您的 objective。 (例如,如果您需要它来生成新的 links/urls,您可以只使用 IUrlHelper
)
正在访问 ViewContext
看起来 beta8 已经添加了对注入 ViewContext 的支持,尽管在 RC 之前实现细节可能会发生变化。参见
我正在尝试将 MVC 5 应用程序迁移到 ASP.NET 5 MVC 6 (Beta 7)。
同时使用 @inherits
和 @model
指令时出现问题。
单独使用时效果很好。
在我的 _ViewImports
中,我添加了 @inherits
指令以使用具有一些自定义用户属性的基页。
public abstract class BaseViewPage<TModel> : RazorPage<TModel>
{
protected MyPrincipal AppUser
{
get
{
return new MyPrincipal(this.User as ClaimsPrincipal);
}
}
}
_ViewImports.cshttml
@inherits CommonWeb.BaseViewPage<TModel>
@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
然后我就可以进入 AppUser. 我所有的观点。
如果我 不 使用强类型视图,这将起作用。如果我在任何视图中添加 @model
指令,继承的视图页面就会消失。
感谢帮助
更新:
我通过在先前版本的 web.config 中使用自定义 pageBaseType 成功地做到了这一点。
解决方法。
public class ViewHelper
{
ViewContext _context;
public ViewHelper(ViewContext context)
{
_context = context;
}
public MyPrincipal AppUser
{
get
{
return new MyPrincipal(_context.HttpContext.User as ClaimsPrincipal);
}
}
public string ControllerName
{
get
{
return _context.RouteData.Values["controller"].ToString();
}
}
}
查看:
@{ var viewHelper = new ViewHelper(ViewContext);}
有一种方法可以实现所有视图?
MVC 6 中有一个更好的方法,它现在支持 injecting dependencies 在视图上使用 @inject
指令。 (指令 @inject IFoo Foo
允许您在视图中使用类型为 IFoo
的名为 Foo
的 属性)
创建一个新界面IAppUserAccessor
来获取您的应用用户,例如:
public interface IAppUserAccessor
{
MyPrincipal GetAppUser();
}
创建一个 class AppUserAccessor
实现它:
public class AppUserAccessor : IAppUserAccessor
{
private IHttpContextAccessor httpContextProvider;
public AppUserAccessor(IHttpContextAccessor httpContextProvider)
{
this.httpContextProvider = httpContextProvider;
}
public MyPrincipal GetAppUser()
{
return new MyPrincipal (
httpContextProvider.HttpContext.User as ClaimsPrincipal);
}
}
通过在 Startup.cs:
的ConfigureServices
方法中添加一个新条目,在服务容器中注册新接口
services.AddTransient<IAppUserAccessor, AppUserAccessor>();
最后使用 @inject
指令在您的视图中注入 IAppUserAccessor
。 如果您在 ViewImports.cshtml
中添加指令,那么它将在每个视图中可用 。
@inject WebApplication4.Services.IAppUserAccessor AppUserAccessor
有了上面的所有内容,您现在可以只在您的视图中使用它了:
@AppUserAccessor.GetAppUser()
更新
如果你需要检查路由值,比如控制器名称,你可以在你的 class 中注入一个 IActionContextAccessor
并按如下方式使用它:
public AppUserAccessor(IHttpContextAccessor httpContextProvider, IActionContextAccessor actionContextAccessor)
{
this.httpContextProvider = httpContextProvider;
this.actionContextAccessor = actionContextAccessor;
}
...
public string ControllerName
{
get { return actionContextAccessor.ActionContext.RouteData.Values["controller"].ToString(); }
}
当然,它看起来不再像 AppUserAccessor
,而且闻起来好像它有不同的职责。至少它需要一个更合适的名字:)
我会仔细检查我需要控制器名称做什么。可能有更好的方法来完成您的 objective。 (例如,如果您需要它来生成新的 links/urls,您可以只使用 IUrlHelper
)
正在访问 ViewContext
看起来 beta8 已经添加了对注入 ViewContext 的支持,尽管在 RC 之前实现细节可能会发生变化。参见