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 之前实现细节可能会发生变化。参见