2010-05-26 4 views
4

J'ai récemment commencé à évaluer ASP.NET MVC. Bien qu'il soit vraiment facile et rapide de créer des contrôleurs et des vues pour les modèles avec seulement des propriétés primitives (comme montré dans les vidéos de démarrage de la page officielle), je n'ai trouvé aucun moyen de travailler avec des références complexes. Disons que j'ai ces modèles:Relations de modèle dans ASP.NET MVC

public class Customer { 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public Address Address { get; set; } 
    public IList<Order> Orders { get; set; } 
} 

public class Address { 
    public int Id { get; set; } 
    public string ..... 
    ..... 
} 

public class Order { 
    public int Id { get; set; } 
    public Customer Customer { get; set; } 
    public string OrderName { get; set; } 
    ..... 
} 

Notez que je n'ai pas les clés étrangères dans les modèles (comme il est typique pour LINQ to SQL, qui est également utilisé dans la vidéo de l'échantillon), mais une référence d'objet.

Comment puis-je gérer de telles références dans asp.net mvc? Est-ce que quelqu'un a de bons conseils ou des liens vers des tutoriels sur ce problème? peut-être inclure l'autobinding avec des types complexes.

Répondre

1

Je combiner tout dans mon modèle de vue:

CustomerViewModel.Customer 
CustomerViewModel.Address 
CustomerViewModel.Orders // maybe an IEnumerable<Order> 
CustomerViewMode.CurrentOrder 

Vous devriez être en mesure de lier vos objets complexes sans trop difficulté à utiliser certains des aides à la saisie:

//.. begin form 
<%=Html.HiddenFor(m=>m.Customer.Id)%> 
<%=Html.TextboxFor(m=>m.Customer.FirstName)%> 
<%=Html.TextBoxFor(m=>m.Address.City)%> 
<%=Html.TextBoxFor(m=>m.ActiveOrder.OrderName%> 
//.. submit .. 
//.. end form .. 

Le doit se lier de nouveau ok si votre méthode d'action ressemble à:

[HttpPost] 
public ActionResult UpdateComplexObject(string id, CustomerViewModel customerViewModel) { 
// if (!id.Equals(customerViewModel.Customer.Id) throw something 
// just one of my own conventions to ensure that I am working on the correct active 
// entity - string id is bound from the route rules. 
ValidateModel(customerViewModel); 
service.UpdateCustomer(customerViewModel.Customer); 
serviceOrder.UpdateOrder(customerViewModel.ActiveOrder); 
serviceAddress.UpdateAddress(customerViewModel.Address); 
return RedirectToAction("DisplayComplexObject"); // or whatever 
} 

Hal

+0

De plus, si vous avez besoin de personnaliser vos objets, vous devriez pouvoir implémenter votre propre classeur de modèle et le manipuler. – Hal

3

Vous pouvez utiliser des objets de transfert de données pour ce problème ou vous pouvez utiliser étendre les méthodes sur l'entité - inclure la méthode dans EF -

Rien est différent avec des propriétés primitives. Si c'est pas ce que vous voulez dire, corrigez-moi alors je vais vous aider à nouveau

Merci

DTO:

public class OrderDTO 
{ 
    public int Id { get; set; } 
    public int CustomerId { get; set; } 
    public string CustomerName { get; set; } 
} 

dépôt NHibernate:

public IList<OrderDTO> GetOrders() 
{ 
    return Session.Linq<Order>() 
        .Select(o => new OrderDTO { 
             Id = o.Id 
             CustomerId = o.Customer.Id 
             CustomerName = o.Customer.Name 
             ... 
        }).ToList(); 
} 

Vue:

Avec Développer - Inclure - Le type de modèle est 'Commander':

<%= Model.Customer.Name %> 

Avec DTO - type de modèle est 'OrderDTO':

<%= Model.CustomerName %> 

modifier:

D'accord, d'abord, vous voudrez peut-être utiliser FormViewModel pour créer/modifier des actions. comme ça;

Controller:

public ActionResult Edit(int id) 
{ 
    Order order = null; // OrderService.Get(id); 
    IList<Customer> customers = null; // CustomerService.GetAll(); 

    OrderFormViewModel model = OrderFormViewModel.Create(order); 
    model.Customers = customers.Select(c => new SelectListItem { 
     Value = c.Id, 
     Text = c.Name 
    }); 

    return View(model); 
} 

[HttpPost] 
public ActionResult Edit(int customerId, Order order) 
{ 
    //customerId - selected from dropdown. 
} 

public class OrderFormViewModel 
{ 
    public static OrderFormViewModel Create(Order order) 
    { 
     return new OrderFormViewModel { 
      Order = order 
     }; 
    } 

    public Order Order { get; internal set; } 
    public IEnumerable<SelectListItem> Customers { get; internal set; } 
    public int CustomerId { get; internal set; } 
} 

Vue:

<%= Html.DropDownListFor(o => o.CustomerId, Model.Customers) %> 
+0

merci pour votre réponse. Mais en travaillant sans DTO, comment puis-je définir cette référence (par exemple dans un formulaire de création) <% = Model.Customer = ......%>? Il existe une SelectList mais cela ne supporte que les valeurs de chaîne – Fabiano

+0

@Fabiano: Pas du tout et je viens d'éditer maintenant. Utilisez 'IEnumerable ' pour la liste déroulante, etc. - ou si ce n'est pas ce que vous voulez, dites-moi que je vais éditer. – cem

1

Je préfère garder mon point de vue comme « stupide » que possible, donc je voudrais créer vue personnalisée modèles pour la reliure.

Dans votre contrôleur, vous pouvez mapper vos objets de domaine riche au modèle plus plat du modèle de vue.Par exemple:

public class ChooseCustomerModel { 

    public Order Order { get; set; } 

    // Project Customer objects into this container, which is easy to bind to 
    public IDictionary<int, string> PotentialCustomers { get; set; } 
} 

Si vous cherchez un bon matériel à ce sujet, je vous recommande ASP.NET MVC View Model Patterns.

+0

Merci pour le lien. C'est un article utile. – Fabiano