Using an @section inside a ChildAction to add addi

2019-09-16 11:16发布

问题:

I've got a MVC View which is made up of a main view and some additional content added via @Html.Action.

In the additional content (which is a ChildOnlyAction) I want to be able to add some JS to the page, but I want to add it to the @RenderSection("Scripts") block which I've defined in the layout.

Can my Child Action's View use this:

@section Scripts {
    //Add scripts
}

So far I haven't been able to get it to work, so if it doesn't what would be an alternative approach?

回答1:

Sections do not work in partial views. You could use a conjunction of extension methods that I illustrated here: https://stackoverflow.com/a/9663249/29407

So in your _Layout.cshtml you will have at some location:

@Html.RegisteredScripts()

and then in your partial:

@{Html.RegisterScript("~/scripts/foo.js");}


回答2:

I was willing today to create a global dialog that would open under some conditions, I needed the script to be at bottom of the page. As others have already mention, a @section inside a child action is not possible.

I had the same problem as you did, the solultion to use custom helpers and js files should work, but I don't like, because usually I operate the javascript with razor and files make the requests longer to load.

the solution at https://stackoverflow.com/a/9663249/29407 is valid if you like that, for me no thanks.

I came with a new solution that is clean, the problem if you analyze it is that we have one controller and a view with 2 parts that have to be injected at different position in the final result.

After my analysis I realize that we have 2 views but one controller that has to control them once per request, below is how I did it, I moved the javascript to a new view with same name endig with script.

XDialogController.cs
XDialog.cshtml
XDialogScript.cshtml

Then before returning the ActionResult from the child action method, one sets the model or values for the other view inside the TempData object.

for example:

[ChildActionOnly]
public ActionResult Popup()
{
// pass variable or model if you need it to script view.
TempData[TempDataKeys.ScriptXDialogModel] = new ModelScriptX();

// pass variable or model to regular view.
return PartialView("XDialog", new ModelX());
}

Inside your ...Script.cshtml file you can read the variable or model as you need.

for example:

@if((TempData[TempDataKeys.DisplayXDialog] as bool?) == true)
{
    <script type="text/javascript">
      ...jquery functions ....
    </script>
}

Remember that TempData can only be read only once, one can keep the value inside a variable inside the view.

To invoke my dialog in the layout page I do the following:

<body>

@RenderBody()

@Html.Action("Popup", "XDialog")

@Scripts.Render("~/Scripts/core")
@RenderSection("ExtraScripts", required: false)

@Html.Partial("XDialogScript")

</body>

I hope that can help anybody.