Dubbi su MVC

mercoledì 17 settembre 2014 - 10.43
Tag Elenco Tags  C#  |  .NET 4.0

svipla Profilo | Senior Member

Ciao a tutti
ho appena iniziato a studiare MVC e fino ad ora lo trovo complicato da utilizzare e da modificare.
Devo modificare un ecommerce. nopCommerce, e ho delle enormi difficoltà nel capire come fare anche una semplice modifica.
Per esempio, ho questo codice di una partian view:
Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra


1- non riesco a capire come faccio a sapere qual'è la pagina controller. Cercando tra le varie pagine ho trovato una pagina che contiene azioni per diverse pagine che hanno a che fare con i prodotti.
2- Questo pezzo di codice mi permette di visualizzare dei prodotti, ma se oltre a visualizzare i prodotti volessi anche visualizzare altri dati letti dal db, come faccio? Da come capisco dal codice, il controller mi carica la lista dei prodotti, poi controlla se ci sono prodotti e li visualizza. Non capisco come caricare altre info che non appartengono alla lista dei prodotti.
3- CMS che sto tentando di modificare utilizza EF codefirst, se io volessi aggiungere altri campi, per esempio ai prodotti, come faccio ad aggiungerli al db?

Ho una gran confusione e non riesco proprio a capire i vantaggi di MVC. Trovo tutto più lento e complicato.
Grazie mille

0v3rCl0ck Profilo | Guru

Ciao, quella è una partial e quindi può essere utilizzata in diversi contesti, l'importante è che gli venga passato il modello corretto e cioè vuole un intera lista di ProductOverviewModel, per la precisione IList<ProductOverviewModel>... detto questo devi cercare i metodi che ritornano appunto una lista di ProductOverviewModel... ma prima di tutto controlla dove la partial viene utilizzata, con il comando @Html.Partial("...", ...)

devi cercare di non ragionare provando a capire per forza tutto il giro del fumo, i progetti ben disegnati, con moduli disaccoppiati, diventano complessi da capire nell'insieme, ma estremamente semplici nel singolo modulo. Nel tuo caso ad esempio è chiaro come aggiungere informazioni in quella partial, non devi fare altro che aggiungere le informazioni sul modello ProductOverviewModel, e poi preoccuparti di andare ad arricchire quel modello quando lo carichi, e si, sarà sicuramente in un controller, non devi fare altro che cercare dove viene utilizzato il modello ProductOverviewModel, ti può aiutare anche vedere semplicemente dove viene settata una proprietà di ProductOverviewModel, in modo da trovare esattamente il punto dove viene fatto new ProductOverviewModel() ... item.Proprietà = ...

io invece la penso esattamente il contrario, trovo asp.net web forms, una complicazione inutile, un prodotto estremamente over-engineered, che nel tempo a portato a fare più confusione che altro, e te lo dico avendo usato abbondantemente l'uno e l'altro, non scriverei mai e poi mai più una web application in web forms, tra l'altro ora è tutto client (javascript + ui fx) con rest service (webapi), e le webforms nel contesto moderno proprio non ci va d'accordo, chi me lo fa fare, non posso avere controlli renderizzati da un terzo attore, ci vuole controllo per potere sfruttare tutte le nuove tecnologie e quello che richiede il mercato (webapp che si comportano come desktop app).

scusa per la digressione, me l'hai servita


Michael Denny | Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic

svipla Profilo | Senior Member

Ciao
grazie per l'aiuto
Forse perchè sono all'inizio e non capisco molto, ma sto impazzendo per fare una cosa semplicissima: voglio visualizzare le categorie a cui appartiene il prodotto.

Controller
Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Model
namespace Nop.Web.Models.Catalog { public partial class ProductOverviewModel : BaseNopEntityModel { public ProductOverviewModel() { ProductPrice = new ProductPriceModel(); DefaultPictureModel = new PictureModel(); SpecificationAttributeModels = new List<ProductSpecificationModel>(); ReviewOverviewModel = new ProductReviewOverviewModel(); Categories = new List<ProductCategory>(); } public string Name { get; set; } public string ShortDescription { get; set; } public string FullDescription { get; set; } public string SeName { get; set; } //price public ProductPriceModel ProductPrice { get; set; } //picture public PictureModel DefaultPictureModel { get; set; } //specification attributes public IList<ProductSpecificationModel> SpecificationAttributeModels { get; set; } //price public ProductReviewOverviewModel ReviewOverviewModel { get; set; } //categorie QUESTO E' QUELLO CHE VOGLIO AGGIUNGERE IO public IList<ProductCategory> Categories { get; set; } #region Nested Classes public partial class ProductPriceModel : BaseNopModel { public string OldPrice { get; set; } public string Price {get;set;} public bool DisableBuyButton { get; set; } public bool DisableWishlistButton { get; set; } public bool AvailableForPreOrder { get; set; } public DateTime? PreOrderAvailabilityStartDateTimeUtc { get; set; } public bool ForceRedirectionAfterAddingToCart { get; set; } /// <summary> /// A value indicating whether we should display tax/shipping info (used in Germany) /// </summary> public bool DisplayTaxShippingInfo { get; set; } } #endregion } }

Lettura dei dati
/// <summary> /// Gets all products displayed on the home page /// </summary> /// <returns>Product collection</returns> public virtual IList<Product> GetAllProductsDisplayedOnHomePage() { var query = from p in _productRepository.Table orderby p.DisplayOrder, p.Name where p.Published && !p.Deleted && p.ShowOnHomePage select p; var products = query.ToList(); return products; }

Classe Product
Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Classe Category
Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Non riesco a capire come assegnare i valori alla List Category che ho aggiunto io. Non mi è propro chiara la logica di come vengano assegnati i valori.
Grazie mille

0v3rCl0ck Profilo | Guru

direi che sei sulla buona strada, hai praticamente trovato tutti i punti che coinvolgono quella partial view... ora, vedendo il metodo di accesso ai dati "GetAllProductsDisplayedOnHomePage" e il modello entity, mi sembra che tu sia già a posto, perchè di fatto il modello Product già contiene la lista delle category a cui è assegnato attraverso la proprietà "ProductCategories", quindi anche la child action "HomepageProducts" non va cambiata di una virgola, perchè demanda il lavoro di modellazione su view model al metodo "PrepareProductOverviewModels", che è l'unico che hai omesso nel post, ed è forse l'unico insieme alla partia view, che dovrai modificare.

Nel metodo "PrepareProductOverviewModels" verrà creato il modello ProductOverviewModel partendo dal modello di dominio, per ogni prodotto creerà un "ProductOverviewModel", li non dovrai fare altro che andare a valorizzare anche la tua lista "Categories" del "ProductOverviewModel", ciclando la lista "ProductCategories" di ogni "Product" del domain model.

Unico appunto, vedrai che "ProductCategories" è dichiarato virtual, questo perchè abilita la possibilità a entity framework di intercettare le chiamate e di aggiungere il concetto di lazy-load per le entità collegate, come nel caso delle categorie, questo vuol dire che se non includi esplicitamente nella query EF la volontà di caricare anche tutte le categorie, quest'ultime non vengono valorizzate subito, ma eventualmente solo se si va in get sulla proprietà, questo nel tuo caso vuol dire che dopo la chiamata alla "GetAllProductsDisplayedOnHomePage", la proprietà "ProductCategories", non conterrà nessun valore, ma se successivamente accedi alla proprietà, quest'ultima effettuarà un ulteriore chiamata a db per valorizzarsi. Questo però è un comportamento che si può disabilitare, e inoltre vedo che la proprietà è stata implementata ritornando una lista vuota se _productCategories è null, quindi sinceramente nel tuo caso specifico non so cosa succede, secondo me hanno previsto entrambe le possibilità, sia che ci sia abilitato il lazy-load a livello globale, che disabilitato, così quando è disabilitato per lo meno la proprietà ritorna lista vuota, invece che ritornare null che facilmente risulta spesso in un null reference exception. Qui spiega il lazy-load di EF: http://msdn.microsoft.com/en-us/data/jj574232.aspx

Detto questo oltre a modificare il metodo "PrepareProductOverviewModels" e partial view, ti consiglio anche di modificare il metodo "GetAllProductsDisplayedOnHomePage", per fare in modo di "allegare" anche le categories, questo perchè non ha alcun senso lasciare che il lazy-load faccia N chiamate per ogni prodotto, quando sai già che per ogni prodotto vuoi sicuramente fare visualizzare le sue categorie, se lasci lavorare il lazy-load questo si traduce in N chiamate, invece che una soltanto sfruttando il comando di JOIN del database engine. Nel tuo caso specifico non so cosa "_productRepository.Table" ritorni, ma immagino un "IQueryable<T>" e che quindi dovrebbe avere un extension method "Include", per potere fare l'eager loading (l'opposto del lazy loading), così:

_productRepository.Table.Include(x => x.ProductCategories)

http://msdn.microsoft.com/en-us/library/gg671236.aspx

oppure se "_productRepository" implementa un repository pattern, è facile che ci sia un parametro/metodo apposta per l'inclusione, sicuramente ci saranno altre query che fanno delle "join", guarda magari altre parti di codice dove vengono "toccate" proprietà di collegamento tra diverse tabelle, in alcuni casi saranno in lazy-load, e quindi non fanno l'include, in altri casi invece mi aspetto che ci siano qualche include, altrimenti è un sistema che lavora tutto in lazy-load, e quindi vai di lazy, anche se non è il massimo dell'ottimizzazione nel tuo caso, il lazy-load non è sempre una cosa buona e giusta perchè dipende dal contesto.

Per quello che riguarda invece MVC in generale, ci sono tutorial ottimi direttamente sul famoso sito asp.net: http://www.asp.net/mvc
Poi mentre guardavo un po' in giro sono incampato in questo tizio matto, che ha fatto un sacco di tutorial veramente esaustivi, correlati di slide e video: http://csharp-video-tutorials.blogspot.it/p/aspnet-mvc-tutorial-for-beginners.html
il tutto sperando che tu abbia un po' di dimestichezza con l'inglese, perchè di tutorial/guide in italiano, faccio veramente fatica a darti link, perchè ho sempre letto tutto in eng... prima o poi devo trovare qualche libro/risorsa in ita da mettere nel bagaglio, anche quando faccio corsi ho questo problema


Michael Denny | Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic

svipla Profilo | Senior Member

Aiuto che confusione
Grazie mille
Provo a modificare

0v3rCl0ck Profilo | Guru

>Aiuto che confusione

No dai, non dire così forse hai approcciato nel modo peggiore a MVC, perchè hai dovuto da subito sbattere la testa su un sistema ben strutturato, e quindi sicuramente complesso per uno che si aspetta tutto nel code-behind di una pagina (ecco perchè ce l'ho un po' con web forms, proprio per questo, anche se non sputo nel piatto dove ho mangiato BENE un decennio fa ).

Appena hai tempo rilassati un po' con questo tutorial di asp.net su MVC, passo a passo, semplice e di impatto, e vedrai che stai meglio: http://www.asp.net/mvc/tutorials/mvc-5/introduction/getting-started

>Grazie mille
>Provo a modificare

Vai! Non ti arrendere!!



Michael Denny | Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic

0v3rCl0ck Profilo | Guru

Ah e giusto per mandarti nello sconforto più assoluto , ti lascio con questa affermazione presa da www.asp.net:

http://www.asp.net/vnext/overview/aspnet-vnext/overview
"As part of ASP.NET vNext, the MVC, Web API, and Web Pages frameworks are being merged into one framework, called MVC 6."

e ancora

http://www.asp.net/vnext/overview/aspnet-vnext/getting-started-with-aspnet-vnext-and-visual-studio
"ASP.NET vNext is being rewritten from the ground up, and while much of your code for vNext will look the same, vNext is not backwards compatible with existing ASP.NET applications. However, the current frameworks (Web Forms 5, MVC 5, Web API 2, Web Pages 3, SignalR 2, and Entity Framework 6) will continue to ship in Visual Studio, and will be fully supported in ASP.NET vNext."

Quindi.... il vecchio pacchetto asp.net in generale deve morire non ci metterei la mano sul fuoco che c'è pure stata un po' di malizia per cercare di togliersi dalle scatole web forms , sicuramente non è per quello è per tutto il resto, quello che è certo, è che punteranno a farti scrivere le app in vnext e cioè sulla base di MVC


Michael Denny | Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic

svipla Profilo | Senior Member

Bene!
Ma c'è qualche libro, tutorial ecc che partendo da zero faccia capire MVC?
Un qualcosa che parta da un esempio bannale per arrivare esempi complessi. Di esempi banali ne ho visti, poi quando ti trovi un progetto enorme non capisci nulla. Specialmente progetti con accesso ai dati.
Grazie

0v3rCl0ck Profilo | Guru

intanto fai fino in fondo tutto questo (ha anche l'accesso ai dati): http://www.asp.net/mvc/tutorials/mvc-5/introduction/getting-started

quel tutorial già spiega tante cose, anche su entity framework code-first, e almeno vedi tutto dall'inizio alla fine. Gli aspetti più avanzati (http://www.asp.net/mvc/tutorials/mvc-5/lifecycle-of-an-aspnet-mvc-5-application), le internals per così dire (routing, dependency injection, EF migration, ecc...), scaturiscono partendo dal costruire qualcosa, dall'esperienza, quando poi hai domande specifiche, troverai anche risposte specifiche e soddisfacenti.

per EF, trovi un tutorial (code-first) tutto suo in specifico, anche quello sicuramente da fare dall'inizio alla fine (spiega anche le migration): http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application


Michael Denny | Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic

svipla Profilo | Senior Member

Scusami ancora, ma non riesco a capire come funziona PrepareProductOverviewModels e come da a inizializzare i valori. Questo è il codice di ProductController:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Qui per esempio non capisco dov'è PrepareProductOverviewModels con tutti quei parametri:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Grazie

0v3rCl0ck Profilo | Guru

vai a vedere in BasePublicController ci dev'essere il metodo PrepareProductOverviewModels... perchè nel ProductController c'è solo il metodo proxy con meno parametri, che poi richiama l'altro metodo in overload con mille parametri


Michael Denny | Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic

svipla Profilo | Senior Member

Grazie mille
Ora seguendo i tuoi consigli sto cercando di caricare le categorie.
Ancora grazie

0v3rCl0ck Profilo | Guru

di niente, dai che ce la fai!


Michael Denny | Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2025
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5