如何正确解决RedirectToAction从抛出对象未设置为实例

时间:2014-03-19 16:09:37

标签: c# asp.net-mvc asp.net-mvc-4

这个问题可能有一个非常简单的答案,但我想知道处理这种情况的最佳实践。运行MVC4,我有一个页面执行重定向到Controller操作,该操作执行查找并在另一页上动态呈现内容。

该页面调用以下控制器进行查找:

    public ActionResult GetMembershipLevel(string userid)
    {
       var memberDetails = MemberDetails.GetMembershipDetails(userid);
       TempData["MemberDetails"] = memberDetails;
       var memberLevel = memberDetails.MemberLevel;
       switch (memberLevel)
       {
           case 0:
               return RedirectToAction("Basic");
           case 1:
               return RedirectToAction("Gold");
           case 2:
               return RedirectToAction("Platinum");
       }
       return null;
    }

在查找之后,基于成员详细信息,数据存储在TempData对象中,并重定向到同一控制器内的ActionResult,以提供发送到可能3个视图中的1个的模型数据。我这样做是因为每个视图都会根据成员分类呈现不同的模型集:

    public ActionResult Basic()
    {
        var details = (MembershipDetail)TempData["MemberDetails"];
        ViewBag.Member = details.IndividualName;
        return View(tuple);
    }

在此代码段中,Model返回到名为Basic的View,所有这些都可以正常工作。除了在浏览器中进行手动刷新的情况。然后所有的地狱爆发了臭名昭着的“对象未设置为对象的实例”在“ViewBag.Artist = details.IndividualName;”

我知道它发生的原因是因为刷新同一页面不能并且不会重复将用户放在页面上的整个周期。它是一个重定向,最初是用户选择的Id,刷新只是刷新现有页面而没有Id参数,导致TempData在后续刷新时为空。

我做了一些研究并找到了一些建议。   1.将模块runAllManagedModulesForAllRequests =“true”添加到WebConfig。 (我认为这是一个潜在的解决方案,因为我不相信它与我的问题有关。

  1. 使用[HandleError]属性装饰我的Controller。 (这实际上有效并缓解了这个问题)
  2. 但我的问题是,“这是处理这个问题的正确和最好的方法吗?”

    我读到了关于属性的问题,“当你只向你的类提供HandleError属性时(或者你的动作方法),当发生未处理的异常时,MVC将首先查找名为”Error“的相应视图。 Controller的View文件夹。如果找不到它,那么它将继续查看Shared View文件夹(默认情况下应该包含Error.aspx文件)“

    因此,我认为[HandleError]属性的实现应该需要相应的View。

    如果这是正确的;看来我已经完成的是解决问题的方法,但不过是一个没有实现捕获的类似try catch块。

    对还是错?在这种情况下,这种方法是否可以接受?

1 个答案:

答案 0 :(得分:3)

我相信你应该以不同的方式设计你的应用程序。

您应该使用单个页面根据其成员资格状态呈现正确的视图,而不是让您重定向到不同的操作(阻止用户只使用Gold而不是Basic键入网址?)这基本上解决了你的整个问题。此外,它使得某人无法输入他们没有的会员级别。

基本上,你会这样做:

public ActionResult Membership()
{
     var memberDetails = MemberDetails.GetMembershipDetails(userid);

     var memberLevel = memberDetails.MemberLevel;
     switch (memberLevel)
     {
         default:
         case 0:
             return View("Basic", memberDetails);
         case 1:
             return View("Gold", memberDetails);
         case 2:
             return View("Platinum", memberDetails);
     }
}