2012-06-21 24 views
5

Vengo a asp.net MVC 4 desde un fondo en Rails, y estoy teniendo algunos problemas para encontrar la forma de tratar con modelos anidados.ASP.NET MVC 4 - Modelos anidados - ¿Cómo configurar asociaciones adecuadas?

Estoy utilizando Entity Framework 4.3 con un enfoque CodeFirst.

La aplicación es bastante sencilla y tiene un Conjunto modelo - que tiene muchas franquicias . Y tiene un modelo de franquicia, que pertenece a Sets.

Las clases de POCO se crearon junto con las propiedades de navegación apropiadas, luego se anodilizaron los controladores con las vistas, luego se generó la base de datos.

Estas son las clases:

Set

namespace FranchiseManagerTest.Models 
    { 
     public class Set 
     {   
      [Key] 
      public int SetID { get; set; } 
      public string SetName { get; set; } 
      public string MainAddress { get; set; } 
      public string TimeZone { get; set; }  
      public virtual ICollection<Franchise> Franchises { get; set; } 
     } 
    } 

franquicia

namespace FranchiseManagerTest.Models 
{ 
    public class Franchise 
    { 
     [Key] 
     public int FranchiseID { get; set; }   
     public int SetID { get; set; } 
     public string FranchiseName { get; set; } 
     public string FranchiseNumber { get; set; }  

     public virtual Set Set { get; set; } 

    } 
} 

Entonces creó algunos conjuntos de la licencia de prueba y franquicias.

Aquí es la vista principal:

enter image description here

El proyecto requiere que todas las franquicias relacionadas con un conjunto son visibles dentro del Conjunto correspondiente. Además, necesito poder agregar una franquicia a un conjunto mientras estoy en los detalles del conjunto.

creé una captura de pantalla para ilustrar lo que parece después de que haga clic en "detalles" en la vista principal:

enter image description here

El botón Nuevo franquicia se crea con un ActionLink que tiene este aspecto:

@Html.ActionLink("New Franchise", "Create", "Franchise", null, new { @class = "btn btn-large btn-primary" }) 

esto me lleva a la franquicia Crear la página que tiene este aspecto:

enter image description here

El problema, como se puede ver, es que el menú desplegable que debe contener el Conjunto Modelo relacionado no se rellena previamente - en lugar tengo que hacer clic en el menú desplegable y volver a seleccionar el conjunto que ya estoy . en

el menú desplegable es está poblada - sino por todos los conjuntos existentes - en lugar del conjunto que estoy dentro de.

Aquí está el menú desplegable al hacer clic en él:

enter image description here

En el interior de la franquicia Crear vista, esto es lo que desplegable y su etiqueta se parecen:

 <div class="editor-label"> 
      @Html.LabelFor(model => model.SetID, "Set") 
     </div> 
     <div class="editor-field"> 
      @Html.DropDownList("SetID", String.Empty) 
      @Html.ValidationMessageFor(model => model.SetID) 
     </div> 

Esto es lo que he intentado:


que intentó pasar en un SETID valor a la vista mediante el ActionLink:

@Html.ActionLink("New Franchise", "Create", "Franchise", Model.SetID, new { @class = "btn btn-large btn-primary" }) 

Luego trató de cambiar el atributo de la String.Empty Ver Crear para esto:

<div class="editor-label"> 
     @Html.LabelFor(model => model.SetID, "Set") 
    </div> 
    <div class="editor-field"> 
     @Html.DropDownList("SetID", Model.SetID) 
     @Html.ValidationMessageFor(model => model.SetID) 
    </div> 

Sin embargo, esto no funcionó y generó un error Invalid Argument.

Aquí es una posible pista

Cuando visito la vista Crear franquicia del conjunto asociado que estoy en, esto es lo que la URL se parece a (u otro problema?):

enter image description here

yo supongo que si las asociaciones entre Establecer y franquicia eran correctas, y cuando fui a añadir una franquicia dentro de un conjunto, que la URL sería loo k como esto:

localhost:52987/Set/1/Franchise/Create 

¿Es esta una suposición errónea de hacer - es esto posible hacer en .NET MVC?

¡Cualquier consejo aquí es muy apreciado!


EDITS


Aquí están las rutas en mi archivo Global.asax si esto es útil:

public static void RegisterRoutes(RouteCollection routes) 
     { 
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

      routes.MapHttpRoute(
       name: "DefaultApi", 
       routeTemplate: "api/{controller}/{id}", 
       defaults: new { id = RouteParameter.Optional } 
      ); 

      routes.MapRoute(
       name: "Default", 
       url: "{controller}/{action}/{id}", 
       defaults: new { controller = "Set", action = "Index", id = UrlParameter.Optional } 
      ); 
     } 

por requerimiento - en este caso son el GET y POST Crear métodos del controlador de franquicia:

// 
    // GET: /Franchise/Create 

    public ActionResult Create() 
    { 
     ViewBag.SetID = new SelectList(db.Sets, "SetID", "SetName"); 
     return View(); 
    } 

    // 
    // POST: /Franchise/Create 

    [HttpPost] 
    public ActionResult Create(Franchise franchise) 
    { 
     if (ModelState.IsValid) 
     { 
      db.Franchises.Add(franchise); 
      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 

     ViewBag.SetID = new SelectList(db.Sets, "SetID", "SetName", franchise.SetID); 
     return View(franchise); 
    } 

Solo avíseme si hay más códigos útiles.

+0

¿Cómo se ve el método FranchiseController.Create? – StriplingWarrior

+0

Hey Stripling: he agregado el código del controlador a la sección Editar de mi OP. Puede ser algo con el controlador, simplemente no estoy seguro de qué. Intenté poner un parámetro para SetID en el método GET Create, pero no tuve suerte. De nuevo, estoy seguro de que lo estoy haciendo mal. Eliminé el parámetro y así es como se ve ahora. – PhillipKregg

+1

Necesita cambiar su método Create del modo que sugiere justinb138. Necesita tomar un parámetro 'SetID' para que el que lo pasa desde el enlace se pueda usar como el valor predeterminado en el menú desplegable. (Es posible que desee hacer que utilice una entrada oculta para ese valor en lugar de un menú desplegable, a menos que espere que la gente cambie la franquicia) – StriplingWarrior

Respuesta

3

estoy un poco confundido en cuanto a lo que estás buscando que hacer, pero me gustaría sugerir algunos cambios:

que cambiaría esto:

<div class="editor-label"> 
    @Html.LabelFor(model => model.SetID, "Set") 
</div> 
<div class="editor-field"> 
    @Html.DropDownList("SetID", Model.SetID) 
    @Html.ValidationMessageFor(model => model.SetID) 
</div> 

a esto:

<div class="editor-label"> 
    @Html.LabelFor(model => model.SetID, "Set") 
</div> 
<div class="editor-field"> 
    @Html.DropDownListFor(model => model.SetID, (SelectList)ViewBag.FranchiseSets) 
    @Html.ValidationMessageFor(model => model.SetID) 
</div> 

Si pasa en el valor SetID a su Crear ActionMethod y se asigna, se debe obtener pas sed a la vista. Parece que no está completando DropDownList, por lo que no hay ninguna opción en la lista de selección para seleccionar.

public ActionResult Create(int SetID) 
{ 
    ViewBag.FranchiseSets = new SelectList(...); 
    var franchise = new Franchise { SetID = SetID }; 
    return View(franchise); 
} 
+0

Gracias por la ayuda. Básicamente es una aplicación CRUD simple. Las acciones de CRUD deben realizarse en elementos secundarios mientras se encuentra dentro del elemento principal. La lista de selección en la vista Crear franquicia en realidad está siendo poblada por todos los conjuntos de franquicias existentes. El problema es que estoy creando la nueva franquicia dentro de un conjunto, por lo que ese conjunto ya debería aparecer en el menú desplegable, sin que el usuario tenga que hacer clic en el menú desplegable y volver a seleccionar el conjunto en el que ya están. ¿Tiene sentido? – PhillipKregg

+0

+1, gran respuesta! – StriplingWarrior

+0

Excelente: intenté esto y parece estar funcionando ahora. ¡Gracias por tu ayuda! – PhillipKregg

1

No está claro exactamente cómo sus acciones y rutas se crean, pero es posible que desee probar esto:

@Html.ActionLink("New Franchise", "Create", "Franchise", new{Model.SetID}, new { @class = "btn btn-large btn-primary" }) 

Mediante la creación de un objeto con una propiedad SetID, MVC sabrá que el parámetro se supone que es llamado "SetID".

PS - ¿Puedo sugerir cambiar el nombre de Set a (FranchiseSet, o FranchiseGroup, etc.), para evitar el nombramiento de colisiones? Setis one of the most ambiguous and common words en el idioma inglés.

+0

Gracias por los comentarios: intenté usar el nuevo {Model.SetId}, pero eso no funcionó para mí, desafortunadamente. Si lo desea, publicaré las rutas en mi archivo Global.asax, pero son las estándar creadas por el marco. De hecho, tuve Set a nombre de FranchiseSet al principio, pero cuando se creó la base de datos, crearía FranchiseSet_ID en lugar de FranchiseSetID. Nunca podría lograr que las asociaciones funcionen hasta que cambie el nombre. Puedo intentar usar "Franchiseset" en su lugar. – PhillipKregg

+0

@PhillipKregg: En cuanto al nombre de la base de datos: podría funcionar mejor denominarlo 'FranchiseSetId' en lugar de' FranchiseSetID'. El marco probablemente piensa que necesita agregar ese guión bajo para diferenciar las mayúsculas o algo así. – StriplingWarrior

Cuestiones relacionadas