2

我正在通过MVC Music Store tutorial工作,并遇到了一个小问题/查询。实体框架.find(id)NullReferenceException

我期待通过它的ID找到相册。

var album = db.Albums.Find(id)

然而,这工作得很好,如果ID不存在,然后我得到一个NullReferenceException当控制器通过一个空模型视图。

我可以想出2种方法来解决这个问题。方法1:检查控制器中的空值,如果为null,则显示不同的视图/重定向到不同的操作,如索引页或专用错误页/ 404找不到页面。方法2:检查模型在视图中是否为空,如果是,则不显示模型特定项目,而是显示错误消息。

@model MvcMusicStore.Models.Album 
@{ 
    ViewBag.Title = "Details"; 
} 
@if (Model == null) 
{ 
    <h2>That album doesn't exist</h2> 
} 
else 
{ 
    <h2>Details: @Model.Title</h2> 
} 

的问题是:是否有任何其他方式/ 最佳实践方式处理这个问题?方法1和方法2有什么优点?

回答

4

您可以编写一个自定义操作筛选器,检查传递给视图的模型是否为null并呈现404页面。这样,您就不需要再重复这样的逻辑在所有的控制器动作:

public class CheckForEmptyModelAttribute: ActionFilterAttribute 
{ 
    public override void OnResultExecuted(ResultExecutedContext filterContext) 
    { 
     var viewResult = filterContext.Result as ViewResultBase; 
     if (viewResult != null && viewResult.Model == null) 
     { 
      var view404 = new ViewResult 
      { 
       ViewName = "~/Views/Shared/404.cshtml" 
      }; 
      filterContext.Result = view404; 
     } 
    } 
} 

然后:

// 
// GET: /Store/Details/4 
[CheckForEmptyModel] 
public ActionResult Details(int? id) 
{ 
    var album = db.Albums.Find(id); 
    return View(album); 
} 

替代方法包括通过从Route类派生编写定制的路线,你将检索模型,如果没有找到,只是不匹配的路线。

0
// 
// GET: /Store/Details/4 
public ActionResult Details(int? id) 
{ 
    var album = db.Albums.Find(id); 
    return ViewIfNotNull(album); 
} 

// boxing 
private ActionResult ViewIfNotNull(object model) 
{ 
    if (album == null) return RedirectToAction("Index"); 
    else return View(album); 
} 

// OR generic 
private ActionResult ViewIfNotNull<T>(T model) 
{ 
    if (album == null) return RedirectToAction("Index"); 
    else return View(album); 
}