【问题标题】:Partial views on _Layout not rendered when Actionfilter invoked调用 Actionfilter 时未呈现 _Layout 上的部分视图
【发布时间】:2020-05-14 06:49:43
【问题描述】:

呈现的Alert 视图包含布局

@model myModel

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

当使用像这样的动作过滤器时

 public class CheckThisAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            filterContext.Result = new ViewResult
            {
                ViewName = "Alert",
                ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelBinding.ModelStateDictionary())
                {
                    Model = new myModel()
                }
            };

            base.OnActionExecuting(filterContext);
        }
    }

_Layout 根本不会重新渲染。 (仅渲染视图) 为什么会这样? 我应该将ViewResult 更改为其他内容,还是 在动作过滤器中也包含_Layout

更新:检查渲染页面后,我注意到页面包含所有信息,包括_Layout,但chrome拒绝渲染它

更新:布局包含其他部分视图

<div class="page-wrapper">
    <div class="page-inner">
        <partial name="_LeftPanel" />
        <div class="page-content-wrapper">
            <partial name="_PageHeader" />
            <main id="js-page-content" role="main" class="page-content">
                @RenderBody()
            </main>
            <partial name="_PageContentOverlay" />
            <partial name="_PageFooter" />
        </div>
    </div>
</div>

似乎根本没有加载,这就是为什么输出只有

<div class="page-wrapper">
        <div class="page-inner">
            <div class="page-content-wrapper">
                <main id="js-page-content" role="main" class="page-content">
                   <div class="alert alert-warning" role="alert">
                     <strong>Alert!</strong> This is what only is displayed
                   </div>
                </main>
                <div class="page-content-overlay" data-action="toggle" data-class="mobile-nav-on"></div>
            </div>
        </div>
    </div>

【问题讨论】:

  • 我测试了您的代码,但它运行良好并呈现了所有 .您是否尝试创建一个新的简单项目来测试操作过滤器?如果您希望社区审查和调试代码,您能否分享有关视图和应用过滤器方式的更多详细信息?
  • @XueliChen 你能检查一下更新吗?
  • @Giulio 它呈现 _Layout 但不呈现其中包含的部分视图。刚刚更新了,谢谢

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


【解决方案1】:

如下图定义你的PartialView(不要为partialview定义布局页面):

<div>
    < ... partial view content goes here >
</div>   

在Controller中添加Action方法如下图:

[HttpPost]
public PartialViewResult _DemoPartialView(/* additional parameters */)
{
    return PartialView();
}

如果您想打开另一个视图,例如当请求不是POST等时使用以下方法:

[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
public ActionResult _DemoPartialView()
{ 
    if (HttpContext.Request.HttpMethod == "POST")
    {
        return PartialView();
    }
    else
    {
        return this.RedirectToAction("Index", "Home");
    }
}

【讨论】:

    【解决方案2】:

    我在 Visual Studio 2017 .NET Core 2.1 和 Visual Studio 2019 .NET Core 3.1 中测试了以下内容。

    就动作过滤器而言,我已经在Startup注册了:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddScoped<CheckThisAttribute>();
    }
    

    并将其放在 index 操作的顶部:

    public class HomeController : Controller
    {
        [ServiceFilter(typeof(CheckThisAttribute))]
        public IActionResult Index()
        {
            return View();
    
        }
    

    我的Alert.cshtml 仅包含:

    @model ErrorViewModel
    
    @{
        Layout = "~/Views/Shared/_Layout.cshtml";
    }
    <div class="alert alert-warning" role="alert">
        <strong>Alert!</strong> This is what only is displayed
    </div>
    

    而这种布局的内容正是:

    <div class="page-wrapper">
        <div class="page-inner">
            <div class="page-content-wrapper">
                <partial name="_PageHeader" />
                <main id="js-page-content" role="main" class="page-content">
                    @RenderBody()
                </main>
            </div>
        </div>
    </div>
    

    因此,为了简单起见,我将其简化为一个简单的局部视图_PageHeader

    <header>
        <h2>Page Header</h2>
    </header>
    

    并且该标题按预期显示。

    【讨论】:

      【解决方案3】:

      我想知道您在 CheckThisAttribute 过滤器中检查的是哪个业务逻辑条件。 而不是覆盖 ViewName 在布局中放置警报视图的条件。 您可以通过 2 种方式检测条件

      1. 为所有模型创建基础模型类并为其添加布尔属性 IsAlert。然后你可以从动作过滤器中设置它。

        public override void OnActionExecuting(ActionExecutingContext filterContext)
                          {
                              filterContext.Result = new ViewResult
                              {
                                  ViewName = "Alert",
                                  ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelBinding.ModelStateDictionary())
                                  {
                                      Model = new myModel();
                                      Model.IsAlter=true;
                                  }
                              };
                              base.OnActionExecuting(filterContext);
                      }

      然后在你的布局中,参考this

      **@model ViewModelBase**
          <div class="page-wrapper">
              <div class="page-inner">
                  <partial name="_LeftPanel" />
                  <div class="page-content-wrapper">
                      <partial name="_PageHeader" />
                      <main id="js-page-content" role="main" class="page-content">
                          @RenderBody()
                      </main>
                      @if(Model.IsAlert) 
                       {
                          <partial name="Alert" />
                       }
                      <partial name="_PageContentOverlay" />
                      <partial name="_PageFooter" />
                  </div>
              </div>
          </div>
      
      1. 第二种方法是设置 TempData 标志在布局中使用它。

       public class CheckThisAttribute : ActionFilterAttribute
          {
              public override void OnActionExecuting(ActionExecutingContext filterContext)
              {
                   filterContext.Controller.TempData.Add("IsAlert","1");
                   base.OnActionExecuting(filterContext);
              }
          }

      在布局中访问 TemdData。

       @if(TempData["IsAlert"]==1) 
                       {
                          <partial name="Alert" />
                       }
      

      【讨论】:

        猜你喜欢
        • 2014-02-09
        • 1970-01-01
        • 2013-06-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多