在ASP.NET MVC 5中,每个Controller Action都必须返回一个与Controller同名的View吗?
这是我的项目。有一个网页,其中包含一个将图像上传到数据库的按钮。加载网页时,我希望它显示已上传的所有图像的列表。因此,此Controller的索引(默认)操作从数据库加载图像,并返回索引视图,而索引视图又显示图像列表:
public ActionResult Index()
{
// Load the images from the database
var images = GetImages();
return View(images);
}
在同一网页上,有一个按钮,允许用户将图像上传到数据库。该按钮调用Upload Action,它根据传递的“file”和“folder”参数上传文件,然后最终再次返回Index View:
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file, string folder)
{
// Upload the file from the specified folder
// ...
// ...
// ...
return Index();
}
但是,当用户点击此上传按钮时,会显示以下错误消息:
The view 'Upload' or its master was not found or no view engine supports the searched locations
但我不是要渲染名为“上传”的视图 - 我正在尝试渲染名为“索引”的视图,这就是为什么我有一行return Index();
。
对我出错的地方有任何帮助吗?
答案 0 :(得分:1)
虽然 Vitaliy 和 Nathan A 提供了足够的答案,但我想解释为什么您的初始方法不起作用,因为这是一个很好的问题并且似乎没有意义。
要获得我们的答案,我们必须查看ASP.NET MVC source code。
在我们开始之前,让我们来看看你的代码。
/Controller/Upload
Index()
Index()
是一种使用自己的模型返回自己视图的方法出了什么问题?
首先要知道Index()
被调用并成功返回。模型对象也被传递给视图(如果找到了)。
当您返回Index()
时,它返回View()这是Controller类中的继承方法,它返回ViewResult。
ViewResult继承自ViewResultBase。
当返回ViewResult时,它会调用ExecuteResult()。
查看ExecuteResult()
的源代码:
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
if (string.IsNullOrEmpty(this.ViewName))
{
this.ViewName = context.RouteData.GetRequiredString("action");
}
ViewEngineResult viewEngineResult = null;
if (this.View == null)
{
viewEngineResult = this.FindView(context);
this.View = viewEngineResult.View;
}
TextWriter output = context.HttpContext.Response.Output;
ViewContext viewContext = new ViewContext(context, this.View, this.ViewData, this.TempData, output);
this.View.Render(viewContext, output);
if (viewEngineResult != null)
{
viewEngineResult.ViewEngine.ReleaseView(context, this.View);
}
}
这里的关键是context.RouteData.GetRequiredString("action")
。此代码获取操作名称,以便可以查找和呈现视图。请注意,它使用的是ControllerContext。
因此,您的操作实际上是在首次调用Upload()
方法时设置的。如果您单步执行Index()
方法,则会看到调用context.RouteData.GetRequiredString("action")
将返回字符串"Upload"
。
这是因为,在用户请求的上下文中,操作实际上是上传(这是他们请求的页面)。
如果你返回Index()
并且该方法碰巧改变了ViewBag(ViewData),那么无论渲染什么,ViewData都会被改变。
如果您的Upload()
执行此操作:
ViewBag.Test = "Upload method";
然后您返回Index()
,而Index()
执行此操作:
ViewBag.Test = "Index method";
然后Test
的值将是“索引方法”。
答案 1 :(得分:0)
查看View方法的文档。它有几个你可以提供的参数,其中一个是视图名称的字符串,但如果你想返回一个视图,你总是使用View()方法。
但是,如果您不想使用默认的视图名称(作为操作方法的名称),只需使用字符串指定一个新名称,如下所示:
public ActionResult Upload(HttpPostedFileBase file, string folder)
{
return View("Index");
}
答案 2 :(得分:0)
你可以这样做:
return RedirectToAction("Index");
或:
return View("Index");
答案 3 :(得分:0)
只是旁注,您不必限制在View文件夹中显示控制器名称的视图。你可以做到
public ActionResult something()
{
return View("../OtherView/somethingElse");
}