2010-10-05 13 views
8

Tengo la siguiente situación: mi sitio web muestra artículos (ingresados ​​por un administrador, como un blog).Parámetro del controlador ASP.NET MVC opcional (es decir, índice (int? Id))

Para ver un artículo, se hace referencia al usuario en Inicio/Artículos/{artículo ID}.

Sin embargo, el usuario selecciona qué artículo ver dentro de la vista Articles.aspx, utilizando una lista jsTree.

Así que lo que tengo que hacer es poder diferenciar entre dos casos: el usuario está accediendo a un artículo específico, o simplemente está tratando de acceder a la página de artículos "principal". Intenté configurar el parámetro del controlador "Artículos" como opcional (int? Id), pero luego tengo problemas para "usar" el valor del identificador dentro del controlador.

¿Cuál es la manera óptima de manejar este escenario? Tal vez simplemente necesito una mejor lógica para verificar si un parámetro de identificación se suministró o no en la "url".

Estoy tratando de evitar el uso de dos vistas/controladores, simplemente por razones de duplicación de código.

Respuesta

13

Use acciones separadas, como:

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

Alternativamente moverlo a un controlador de noticias (direcciones URL utilizando la ruta por defecto serán: Articles y Articles/Detail/{id}):

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

Si todavía debe utilizar es como si hubiera publicado, pruebe uno de estos:

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)); 
} 
+0

"Alternativamente, muévalo a un controlador de Artículos (las URL que usen la ruta predeterminada serán: Artículos y Artículos/Detalles/{id}):" esta es probablemente la mejor manera de hacerlo. ¡Gracias! –

0

Realice el parámetro requerido luego establezca un valor predeterminado en el enrutamiento que sea un valor que no sea un índice válido e indique a su acción que debe representar la página principal.

1

esto me suena como dos páginas separadas y debe tratarse como tal. Usted tiene la página de vista "Principal" y la página de "artículos".

Lo dividiría en dos acciones. No deberían ser una verdadera duplicidad, ¡ambos deberían hacer una llamada para obtener el mismo ModelView y el artículo simplemente obtendrá la extensión de eso!

5

definir un valor predeterminado para el Id que sabes indica ningún valor fue suministrado - por lo general 0.

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

gracias, esto es exactamente lo que necesitaba. –

+1

Usar el atributo DefaultValue parece ser una forma muy confusa de resolver este problema. – Ryan

+0

hmmmm ... tal vez use 2 vistas después de todo. Necesito que la página principal de artículos de presentación sea más "interesante" en cuanto a HTML. –

7

En primer lugar, estoy de acuerdo con @Steve :). Pero si realmente desea utilizar

int? id 

sólo se puede comprobar en su método de control si el ID se establece mediante un sencillo

if(id == null) 

y si es así, cargar todos los artículos de su base de datos (o algo similar) y pasarlos a su vista (ya sea directamente, o mediante el uso de un modelo de vista). Si la identificación está configurada, solo cargue el artículo que tiene esa identificación de su base de datos y envíela a la vista (posiblemente también en una lista si no usa ver modelos).

Que en su vista simplemente cargue todos los artículos de la lista con artículos suministrados a la vista. Que contiene todos o solo uno.

código ficticio completa

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); 
} 

Su punto de vista tiene algo como:

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

foreach(Articles a in Model) 
    //display article 

Y lo llamas utilizando cualquiera de las siguientes dos opciones:

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

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

La solución más fácil es tener dos acciones y puntos de vista diferentes, pero nombrar las acciones de la misma manera.

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

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

Ok, pero cuando trato de llamar a la página principal de artículos usando: <% = Html.ActionLink ("Artículos", "Artículos", "Home")%> consigo un error: La petición actual para la acción 'Artículos' en el tipo de controlador 'HomeController' es ambiguo entre los siguientes métodos de acción: System.Web.Mvc.ActionResult Artículos() en el tipo dr_teman_MVC.Controllers.HomeController System.Web.Mvc.ActionResult Artículos (Int32) en escriba dr_teman_MVC.Controllers.HomeController –

+0

¿Su ruta (predeterminada) especifica un ID predeterminado? Supongo que eso podría ser un problema. Probablemente nombraría una acción Artículos y el otro Artículo. – Ryan

0

Bueno, esta es la solución combinada estoy usando:

Usando mismo controlador, con DefaultValue:

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

Si se utilizó DefaultValue, I se refieren a "MainArticles" vista. Si se proporcionó una ID de artículo, me refiero a la vista "Artículos" con el artículo apropiado pasado dentro de ViewModel.

En ambos casos, ViewModel se completa con los datos que ambas visualizaciones necesitan (listas completas de artículos y categorías).

Gracias a todos por su ayuda!

0

No sé si se trató de esto, pero en cambio si está escribiendo el valor directamente en la URL, entonces, en lugar de pasar de esta manera:

controller/action/idValue

tratan de pasar de esta manera:

controller/action?id=value

Cuestiones relacionadas