ASP.NET MVC控制器参数可选(即Index(int?id))

时间:2010-10-05 12:41:03

标签: asp.net-mvc controller asp.net

我有以下情况:我的网站显示文章(由管理员输入,如博客)。

因此,要查看文章,请将用户引用到Home / Articles / {article ID}。

但是,用户使用jsTree列表从Articles.aspx视图中选择要查看的文章。

所以我需要做的是能够区分两种情况:用户正在访问特定文章,或者他只是试图访问“主要”文章页面。我尝试将“Articles”控制器参数设置为可选(int?id),但是我在控制器内“使用”id值时出现问题。

处理此方案的最佳方式是什么?也许我只需要一个更好的逻辑来检查“url”中是否提供了id参数?

我试图避免使用两个视图/控制器,只是出于代码复制的原因。

8 个答案:

答案 0 :(得分:14)

使用单独的操作,例如:

public ActionResult Articles() ...
public ActionResult Article(int id) ...

或者将其移至Article控制器(使用默认路由的网址为:ArticlesArticles/Detail/{id}):

public class ArticlesController : Controller
{
    public ActionResult Index() ...
    public ActionResult Detail(int id) ...
}

如果您仍然必须像发布的那样使用它,请尝试以下方法之一:

public ActionResult Articles(int id = 0)
{
     if(id == 0) {
         return View(GetArticlesSummaries());
     }
     return View("Article", GetArticle(id));
}
public ActionResult Articles(int? id)
{
     if(id == null) {
         return View(GetArticlesSummaries());
     }
     return View("Article", GetArticle(id.Value));
}

答案 1 :(得分:7)

首先,我同意@Steve :)。但如果你真的想用

int? id

如果使用简单的

设置了id,您可以检查控制器方法
if(id == null)

如果是这样,请从您的数据库(或类似的东西)加载所有文章,并将这些文章传递给您的视图(直接或使用视图模型)。如果设置了id,你只需从数据库加载具有该id的文章并将其发送到视图(如果你不使用视图模型,也可以在列表中)?

在您的视图中,只需加载列表中包含提供给视图的文章的所有文章。其中包含全部或仅包含一个。

完整的虚拟代码

public ActionResult showArticles(int? id){
   List<Articles> aList;
   if(id == null){
       aList = repository.GetAllArticles().ToList();
   }else{
      aList = new List<Articles>(); 
      aList.add(repository.GetArticleByID(id));
   }

   return View(aList);
}

你的观点有类似的内容:

<% Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 
Inherits="System.Web.Mvc.ViewPage<List<Articles>>"%>

foreach(Articles a in Model)
    //display article

您可以使用以下两个选项中的任何一个来调用它:

html.ActionLink("one article","showArticles","Articles",new {id = aID},null}

html.ActionLink("all articles","showArticles","Articles"}

答案 2 :(得分:5)

为您知道未提供任何值的ID定义默认值 - 通常为0.

public ActionResult Articles([DefaultValue(0)]int Id)
{
  if (Id == 0)
    // show all
  else
    // show selected
..

答案 3 :(得分:2)

最简单的解决方案是拥有两个不同的操作和视图,但将操作命名为相同。

public ViewResult Articles()
{
   //get main page view model
   return View("MainPage", model);
}

public ViewResult Articles(int id)
{
   // get article view model
   return View(model);
}

答案 4 :(得分:1)

这对我来说听起来像两个单独的页面,应该这样对待。您有“主要”视图页面和“文章”页面。

我会把它分成两个动作。它们实际上应该不是很多重复,两者都应该调用以获得相同的ModelView,文章将简单地获得对它的扩展!

答案 5 :(得分:1)

我不知道你是否尝试过这个,但是如果你直接在URL中输入值,那么,而不是像这样传递它:

  

控制器/动作/ idValue

尝试传递它:

  

控制器/动作?ID =值

答案 6 :(得分:0)

创建所需的参数,然后在路由中设置一个默认值,该值是一个非有效索引的值,并向您的操作指示它应该呈现页面。

答案 7 :(得分:0)

嗯,这是我正在使用的综合解决方案:

使用相同的控制器,使用DefaultValue:

public ActionResult Articles([DefaultValue(0)]int id)

如果使用DefaultValue,我会参考“MainArticles”视图。如果提供了文章ID - 我引用了“文章”视图,并在ViewModel中传递了相应的文章。

在这两种情况下,ViewModel都会填充两个视图都需要的数据(完整的文章和类别列表)。

感谢大家的帮助!