4

The Alert view that is rendered contains the layout

@model myModel

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

While using an action filter like so

 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);
        }
    }

the _Layout is not reendered at all. (Only the view is rendered) Why is this so? Should i change ViewResult to something else, or include also the _Layout in the action filter somehow?

Update: After inspecting the rendered page, i noticed that the page contains all info, including the _Layout, but chrome denies to render it

Update: The Layout contains other partial views

<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>

which do not seem to load at all, and that is the reason why the output is only

<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>
OrElse
  • 9,709
  • 39
  • 140
  • 253

3 Answers3

0

I've tested the following in Visual Studio 2017 .NET Core 2.1 and Visual Studio 2019 .NET Core 3.1.

As far as the action filter is concerned, I've registered it in the Startup:

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

and placed it on top of the index action:

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

    }

My Alert.cshtml contains only:

@model ErrorViewModel

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

and the content of such layout is exactly:

<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>

So, for the sake of simplicity, I've simplified it to just a single, trivial partial view _PageHeader:

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

and that header is shown as expected.

0

Define your PartialView as shown below (Do not define layout page for partialview):

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

Add the Action method to the Controller as shown below:

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

If you want to open another view e.g. when the request is not POST, etc. use the following approach:

[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
public ActionResult _DemoPartialView()
{ 
    if (HttpContext.Request.HttpMethod == "POST")
    {
        return PartialView();
    }
    else
    {
        return this.RedirectToAction("Index", "Home");
    }
}
Murat Yıldız
  • 11,299
  • 6
  • 63
  • 63
0

I wonder which business logic condition you are checking in CheckThisAttribute filter. Instead of overriding ViewName put condition for alert view in layout. You can detect condition 2 ways

  1. Create base model class for all models and add bool property IsAlert to it. Then you can set it from action filter.

  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);
                }

Then in your layout , refer 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. Second approach is to set TempData flag in use it in layout.

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

Access TemdData in layout.

 @if(TempData["IsAlert"]==1) 
                 {
                    <partial name="Alert" />
                 }
Ajay Kelkar
  • 4,591
  • 4
  • 30
  • 29