假设要求是在ASP.NET MVC控制器中成功保存模型后重定向到另一个页面:
[HttpPost]
public ActionResult Index(ViewModel viewModel)
{
if (ModelState.IsValid)
{
// Do save;
return RedirectToAction("whatever"); // <--- here's the problem
}
// display validation errors and so
return View(viewModel);
}
除非控制器呈现为Child Action:
,否则这样可以正常工作@{
Layout = "my layout";
Html.RenderAction("something else, a view for example");
Html.RenderAction("Index action of the above controller"); // <----
}
在这种情况下,RedirectResult类将检查并查看上下文是子操作并抛出异常:&#34;不允许子操作执行重定向操作&#34;。
我理解写入Response流已经在进行中并且不能在此处进行重定向,但是在控制器中的服务器端操作之后,即使该操作是子操作,也必须能够重定向到其他页面。我们使用Layouts和RenderActions来重用页面设计的共享部分。
如何在这样的控制器中实现这样的重定向?
编辑:
主要目标是重复使用执行特定作业的视图/控制器,并将其拆分为逻辑概念,如显示某些数据或提供编辑表单。我的方法是使用RenderAction将其结果呈现到容器中。容器视图(主页的索引操作)充当传统的asp.net页面,其布局视图作为主页面,编辑和查看控制器/视图等同于用户控件(模块)。问题是在写完一些内容之后无法重定向响应:
答案 0 :(得分:1)
如果我理解正确你有一个接受saveAction的父控制器,并且在渲染视图时你将另一个(?)saveAction称为孩子。
这个流程对我来说感觉不自然。
父操作和只有父操作应该处理save命令。
你可以根据需要渲染任意数量的子操作,只要它们仅用于渲染一些html (因为这是视图所做的)。
不要让他们处理重定向或保存,这种工作方式对于大学或未来的你来说都是透明的
控制器控制流程,而不是视图。
编辑:
正常设置将有2个动作,例如:Index和Put。
public ActionResult Index(){
//fill model with dropdown data etc
return View();
}
public ActionResult Put(viewModel data){
if (ModelState.IsValid)
{
// Do save;
return RedirectToAction("whatever"); // <--- here's the problem
}
// display validation errors and so
return View("Index",viewModel);
}
EDIT2:
如果返回View(“Index”,viewModel),您将使用它的布局生成索引视图,验证消息将位于模型状态中。
但是,您的视图应该只有1个子操作(如果有多个,则更多,只要它不是保存操作)。
您的索引视图可能如下所示:
@{
Layout = "my layout";
}
Html.RenderAction("something else, a view for example");
@Html.BeginForm("Put","YourController"){
//all your input controls which will also show the validation errors
}
编辑3:
如果要重用html代码,则应使用@ Html.Partial或Html帮助程序扩展方法。请注意,如果您未传递任何模型,则会传递父模型,但您可以传递子模型以匹配部分模型的类型安全性。
它看起来像这样:
@{
Layout = "my layout";
}
Html.RenderAction("something else, a view for example");
Html.RenderPartial("shared\yourUserControl", Model.PropertyOrSomething);
答案 1 :(得分:1)
我会提交一个新答案,以保持清洁
正常的mvc流程如下:
Http命令到达1个控制器,它充当choirmaster(aka控制器)并调用几个逻辑容器(例如services / commandHandlers):
public ActionResult Index(){
var data = _yourService.FetchData();
return View(data);
}
此控制器呈现1个视图,该视图可以包含多个部分
@{
Layout = "my layout";
}
<p>Some html</p>
Html.RenderPartial("A shared partial");
Html.RenderPartial("shared\yourUserControl", Model.PropertyOrSomething);
如果部分包含太多逻辑而无法生成,则可以添加RenderAction或创建htmlHelper扩展名。
但是这些都不能控制你的请求流,保存或者可以重定向的东西在我看来永远不会从视图内部调用。
我假设您想要在控制器中重复使用代码,因为它变得非常大
我的建议是尽可能通过尽可能多地委托逻辑来尽可能地清除控制器。
只需通过查看控制器方法5秒钟,你应该知道这个动作会做什么,如果不是这样的话:重构它! :)
答案 2 :(得分:0)
尝试在视图中使用AJAX来执行此操作,而不是在控制器中返回RedirectToAction,而是返回一个JSON对象:
查看:
$.ajax({
url: '<%: Html.ResolveUrl("~/ControllerFolder/ControllerName/") %>',
type: "POST",
data: data,
success: function (result) {
$("#Div").html(result);
if (result.redirectUrl != null)
{
window.location = result.redirectUrl;
}
}
});
控制器:
[HttpPost]
public ActionResult Index(ViewModel viewModel)
{
if (ModelState.IsValid)
{
// Do save;
return Json(new { redirectUrl = Url.Action("NewAction", "NewController", RouteValues)});
}
// display validation errors and so
return View(viewModel);
}
希望这会有所帮助......