回发后 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*/);
}
我的问题是,在应用程序中的任何回发之后,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*/);
}