查看未找到 - asp.net mvc错误

时间:2011-08-05 14:59:38

标签: c# asp.net-mvc-2 view error-handling

我收到一条错误,说找不到视图更新,我想显示TaskDetail视图而不是更新视图......

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Update(int taskid, string status)
    {
        if (!status.Equals("closed", StringComparison.OrdinalIgnoreCase) &&
            !status.Equals("opened", StringComparison.OrdinalIgnoreCase))
            ModelState.AddModelError("", "incorrect status, please try again");

        if (!this.ModelState.IsValid)
            return TaskDetail(taskid);

        if (status.Equals("Closed", StringComparison.OrdinalIgnoreCase))
            _service.CloseTask( taskid, true);
        else
            _service.CloseTask(taskid, false);

        this.FlashInfo("success, task status has been updated...");
        return RedirectToAction("TaskDetail");

}

例外:

$exception{"The view 'Update' or its master was not found. The following locations were searched:\r\n~/Areas/Tasks/Views/TaskManager/Update.aspx\r\n~/Areas/Tasks/Views/TaskManager/Update.ascx\r\n~/Areas/Tasks/Views/Shared/Update.aspx\r\n~/Areas/Tasks/Views/Shared/Update.ascx\r\n~/Views/TaskManager/Update.aspx\r\n~/Views/TaskManager/Update.ascx\r\n~/Views/Shared/Update.aspx\r\n~/Views/Shared/Update.ascx"} System.Exception {System.InvalidOperationException}

任务明细:(这是在同一个控制器内)

    [HttpGet]
    public ActionResult TaskDetail(int taskid)
    {
        var loggedonuser = _repo.GetCurrentUser();


        var companies = _repo.All<Company>();
        var users = _repo.All<User>();

        var task = _repo.Single<InstructionTask>
            (x => x.TaskID == taskid && (x.CompanyID == loggedonuser.CompanyID || x.AssignedTo.Contains(loggedonuser.CompanyType.ToString())));

        var dto = new TaskDTO
        {
            TaskID = task.TaskID,
            Title = task.Title,
            Description = task.Description,
            DateCreated = task.DateCreated,
            IsClosed = task.IsClosed,
            CompanyID = companies.Where(y => task.CompanyID == y.CompanyID).SingleOrDefault().Identifier,
        };

        var checkedtags = TaskTagsHelper.GetTags(task.AssignedTo);

        var t = TaskTagsHelper.GetPanelTags();

        if (checkedtags != null) //if tags are present only then tick them off...
        {
            foreach (var item in t.Keys.ToList())
            {
                if (checkedtags.Any(x => x == item))
                    t[item] = true;
            }
        }

        dto.AvailableTags = t;

        if (task.DueDate.HasValue)
            dto.DueDate = task.DueDate.Value;

        var comments = _repo.All<TaskComment>()
            .Where(x => x.TaskID == task.TaskID)
            .OrderByDescending(x => x.Timestamp)
            .Select(x => new TaskCommentDTO
            {
                Comment = x.Comment,
                Timestamp = x.Timestamp,
                CompanyID = companies.Where(y => x.CompanyID == y.CompanyID).SingleOrDefault().Identifier,
                UserID = users.Where(y => x.UserID == y.UserID).SingleOrDefault().Login,
                Type = EnumHelper.Convert<TaskCommentType>(x.Type)
            });

        dto.AllComments = comments;

        return View(new TaskViewModel
        {
            TaskDetail = dto,
            NewComment = new TaskCommentDTO()
        });
    }

我在我的基本控制器中捕获异常:

    //Generic methods/ controllers/ attributes will be applied here...
    protected override void OnException(ExceptionContext filterContext)
    {
        //dont interfere if the exception is already handled
        if (filterContext.ExceptionHandled)
            return;

        //let the next request know what went wrong
        filterContext.Controller.TempData["exception"] = filterContext.Exception;

        //logg exception

        //set up redirect to my global error handler
        filterContext.Result = new ViewResult { ViewName = "~/Views/Error/PublicError.aspx" };

        //advise subsequent exception filters not to interfere and stop
        // asp.net from showing yellow screen of death
        filterContext.ExceptionHandled = true;

        //erase any output already generated
        filterContext.HttpContext.Response.Clear();
    }

2 个答案:

答案 0 :(得分:2)

根据我对您的代码的理解,您从Update方法调用TaskDetail操作。不建议这样做。原因如下:

  1. 请求的拥有上下文是Update方法,这就是它尝试呈现“更新”视图的原因。这是因为按照惯例,视图是根据命中的第一个动作选择的。 MVC没有意识到你已经调用了TaskDetail。
  2. 违反了PRG模式(Post-Redirect-Get)。我建议你在这里阅读:http://en.wikipedia.org/wiki/Post/Redirect/Get - 基本上,你真的不应该从HTTP POST中渲染任何内容。你应该重定向回GET。它会导致各种各样的问题。
  3. 如果你希望它按原样运行,你可以通过将TaskDetail的最后一行更改为以下内容来实现这一点,以便它知道总是呈现TaskDetail视图,但我不推荐它:

    return View("TaskDetail", ...viewModel...)
    

答案 1 :(得分:1)

明显的问题是:

您是否在其中一个文件夹中有文件:

Views\ControllerName\TaskDetail.aspx
Views\ControllerName\TaskDetail.ascx
Views\Shared\TaskDetail.aspx
Views\Shared\TaskDetail.ascx

其中ControllerName是Update方法所在的控制器的名称。也就是说,如果您的控制器是HomeController,那么您的文件夹将是\ Views \ Home \

修改
我对你的ModelState.IsValid调用也有些困惑,但主要是因为你没有包含TaskDetail控制器动作。如果您的模型状态无效,您不想返回更新视图,以便用户可以纠正错误并重新提交吗?或者他们是否从TaskDetail发布到Update操作?