回发后 RenderAction 方法参数为空

RenderAction method parameters are null after a postback

我的问题是,在应用程序中的任何回发之后,RenderAction GET 方法中的参数值为空(见下文)。你能帮我找出问题所在或者如何更好地构建布局代码吗?我正在考虑将 ViewBag 更多地用于 id 而不是 URL 参数,但希望现在能更快地修复。

_Layout.cshtml

<!DOCTYPE html>

<html lang="nl">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>@ViewBag.Title</title>
    @Styles.Render("~/Content/css")
</head>
<body>
    @{ Html.RenderAction("LayoutMenu", "Example", new { pageTitle = ViewBag.Title }); }

    <div class="...">
        @RenderBody()
    </div>
    <footer class="...">
        @* ... *@
    </footer>

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/jqueryval")
    @* ... *@
</body>
</html>

_LayoutMenu.cshtml

@model namespace.Models.LayoutMenu

<header class="...">
    <div class="">
        <div class="">
            <a href="@Url.Action("Index", "Home")"></a>
        </div>
        @if (Model != null && Model.Entities != null)
        {
            Html.RenderPartial("_Entities", Model.Entities);
        }
        <div class="">
            <nav class="">
                @{
                    var controller = ViewContext.ParentActionViewContext.RouteData.Values["Controller"].ToString();
                    var action = ViewContext.ParentActionViewContext.RouteData.Values["Action"].ToString();
                    var id1 = ViewContext.ParentActionViewContext.RouteData.Values["id1"];
                    var id2 = ViewContext.ParentActionViewContext.RouteData.Values["id2"];
                    var id3 = ViewContext.ParentActionViewContext.RouteData.Values["id3"];
                }
                <div>
                    <div class="@(controller == "Home" && action == "Index" ? "item--active" : "")">
                        @Html.ActionLink("Home", "Index", "Home", null, new { @class = "itemlink" })
                    </div>

                    <div class="@(controller == "Example" && action == "Index" ? "item--active" : "")">
                        @Html.ActionLink("Example", "Index", "Example", null, new { @class = "itemlink" })
                    </div>
                </div>
            </nav>
        </div>
    </div>
</header>
<div class="...">
    @if (!String.IsNullOrEmpty(Model.ExampleName))
    {
        <h2>@("Example - " + Model.ExampleName)</h2>
        @Html.ActionLink(Model.SelectedEntityName, "Index", "Home", null, new { @class = "..." })
        @Html.ActionLink(Model.ExampleName, "SomeEntities", "Example", null, new { @class = "..." })
    }
</div>
<div class="...">
    @if (id3 != null)
    {
        <div class="">
            <div class="@(controller == "Example" && action == "ExampleProperties" ? "tab-active" : "tab-line")">
                @Html.ActionLink("Properties", "ExampleProperties", "Example", null, new { @class = "itemlink" })
            </div>
            <div class="@(controller == "Example" && action == "OtherExampleProperties" ? "tab-active" : "tab-line")">
                @Html.ActionLink("Other Properties", "OtherExampleProperties", "Example", null, new { @class = "itemlink" })
            </div>
            @*...*@
        </div>
    }
    else if (id1 !=  null)
    {
        <div class="">
            <div class="@(controller == "Example" && action == "SomeExamples" ? "tab-active" : "tab-line")">
                @Html.ActionLink("Some Examples", "SomeExamples", "Example", null, new { @class = "itemlink" })
            </div>
            @*...*@
        </div>
    }
</div>

_LayoutMenu 操作获取方法

[HttpGet]
[ChildActionOnly]
public ActionResult LayoutMenu(string selectedEntity, Guid? id1 = null, Guid? id2 = null, Guid? id3 = null)
{
    // my problem: id1, id2, id3 are null after a postback
    var result = new LayoutMenu();
    var entities = _entityHelper.GetEntities();

    if (!String.IsNullOrWhiteSpace(selectedEntity))
    {
        if (entities.Any(entity => entity.GetKey().Equals(selectedEntity)))
        {
            result.SelectedEntityName = entities.First(entity => entity.GetKey().Equals(selectedEntity))?.Name;
        }
        else
        {
            selectedEntity = null;
            result.SelectedEntityName = entities.First().Name;
        }
    }
    else
    {
        result.SelectedEntityName = entities.First().Name;
    }

    result.Entities = new Entities
    {
        EntitiesList = entities,
        SelectedEntity = selectedEntity
    };

    result.ExampleName = id1.HasValue ? _api.GetExample(id1.Value).Name : "";

    if (id2.HasValue && id3.HasValue)
    {
        var data = _api.GetData(id2.Value, id3.Value);
        // result.SomeMoreData = ...
    }

    return PartialView("_LayoutMenu", result);
}

回发简化视图

@model namespace.Models.AddData

<div>
    @using (Html.BeginForm())
    {
        @*1st form input fields*@
        <input class="button" type="submit" name="submit" value="Search" />
        @*2nd form input fields in a table*@
        <input class="button" type="submit" name="submit" value="Create" />
    }
</div>

回发简化操作方法

[HttpPost]
public async Task<ActionResult> AddData(Guid id1, AddData model, string submit)
{
    if (!String.IsNullOrEmpty(submit))
    {
        ModelState.Clear();

        if (submit.Equals("Create"))
        {
            // model state checks...

            if (ModelState.IsValid)
            {
                // process and add data.

                // return new statuses
                return View(await CreateModel(id1));
            }

            return View(model);
        }
        else
        {
            // return search
            return View(await CreateModel(id1));
        }
    }
return RedirectToAction(nameof(AddData));
}

显然,LayoutMenu 操作方法中参数的顺序很重要,因为当我先放置 id,然后放置 selectedEntity 和 pageTitle(在我的本地版本中)时,它起作用了!

LayoutMenu post 方法(如下所示)似乎是在 postback 上调用的,它返回了 id1、id2 和 id3 为空值的 get 方法。一旦我在 post 方法上添加了这些参数并在底部返回它们,它就起作用了!

[HttpPost]
public ActionResult LayoutMenu(string selectedEntity, string pageTitle, bool? isEntityChange/*, Guid? id1, Guid? id2, Guid? id3*/)
{
    if (isEntityChange.HasValue && isEntityChange.Value)
    {
        if (!String.IsNullOrWhiteSpace(selectedEntity))
        {
            // set selected entity and go to home.
            // ...
            return Redirect(Url.Action("Index", "Home"));
        }
    }

    // this was the faulty code.
    return LayoutMenu(selectedEntity/*,id1, id2, id3*/);
}