【问题标题】:MVC 6 @inherit RazorPageMVC 6 @inherit RazorPage
【发布时间】:2015-09-26 02:20:54
【问题描述】:

我正在尝试将 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);}

为所有视图实现此目的的方法?

【问题讨论】:

标签: asp.net asp.net-mvc asp.net-core asp.net-core-mvc


【解决方案1】:

在 MVC 6 中有一个更好的方法,它现在通过 @inject 指令在视图上支持 injecting dependencies。 (指令@inject IFoo Foo 允许您在视图中使用名为Foo 类型为IFoo 的属性)

创建一个新接口IAppUserAccessor 用于获取您的应用用户,例如:

public interface IAppUserAccessor
{
    MyPrincipal GetAppUser();
}

创建一个类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.csConfigureServices方法中添加新条目,在服务容器中注册新接口:

services.AddTransient<IAppUserAccessor, AppUserAccessor>();

最后使用@inject 指令在你的视图中注入IAppUserAccessor如果您在ViewImports.cshtml 中添加指令,那么它将在每个视图中都可用

@inject WebApplication4.Services.IAppUserAccessor AppUserAccessor

有了以上所有部分,您现在可以在视图中使用它:

@AppUserAccessor.GetAppUser()

更新

如果您需要检查路由值,例如控制器名称,您可以将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 了,而且闻起来像是有不同的责任。至少它需要一个更合适的名字:)

我会仔细检查我需要控制器名称来做什么。可能有更好的方法来实现您的目标。 (例如,如果您需要它来生成新的链接/网址,您可以只使用IUrlHelper

访问 ViewContext

看起来 beta8 增加了对注入 ViewContext 的支持,尽管实现细节在 RC 之前可能会发生变化。见this question

【讨论】:

  • 谢谢@daniel-j-g,它干净多了!现在差不多了!我需要 ViewContext 来获取 Route 值等。想不出来注入它。
  • 你已经在每个视图中都有 ViewContext 可用,使用@ViewContext
  • @daniel-j-g 是的,但是我必须像现在这样在每个视图中更新我的 ViewHelper,对吗?注入 ViewContext 会很好,这样我就可以获取路由来填充我的 ControllerName 和 ActionName 属性等(请参阅我的更新)。我无法通过我认为的普通 HttpContext 得到它?
  • 我不知道有任何 ViewContextAccessor 并且您不能只向构造函数添加新的 ViewContext 依赖项,因为框架不知道如何解决它。你需要它做什么?如果它是用于创建新链接/url 或访问当前 url(但不是当前路由值),那么您可以将 IUrlHelper 的依赖项添加到您的助手中。您还可以创建可在您的视图中使用的扩展方法
  • 实际上,我刚刚意识到您可以将IActionContextAccessor 注入到您的类中,并使用它来获取路由值(包括控制器名称),如actionContextAccessor.ActionContext.RouteData.Values["controller"].ToString()。会更新答案
猜你喜欢
  • 2023-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-13
  • 1970-01-01
  • 1970-01-01
  • 2019-01-07
相关资源
最近更新 更多