2013-09-10 16 views
5

ASP.NET | MVC 4 | C# | WCFASP.NET MVC - Classi WCF per modelli

Sto utilizzando i servizi Web WCF come intermediario dal livello di presentazione (MVC) al livello dati (Entità). Per semplificare lo spostamento dei dati del modello di dati da MVC al servizio Web, ho pensato di utilizzare le classi proxy in WCF, in modo da creare una classe centralizzata. Sfortunatamente, questo ha causato la perdita delle decorazioni MVC sulle proprietà all'interno del modello. Esiste un buon modo per creare una classe centralizzata da utilizzare con un modello per la vista MVC e anche come metodo di trasporto per il servizio WCF?

L'automapping mi è venuto in mente come opzione, ma credo che richiederebbe due classi identiche. Uno sul lato MVC e uno sul lato WCF. Il che mi richiederebbe comunque di effettuare un cambiamento da entrambe le parti se una proprietà è cambiata in una classe.

Qualsiasi altro suggerimento sarebbe apprezzato. Grazie!

EDIT :: Esempio

Ecco modello per una pagina che contiene una tabella di record

public class ReconcileModel 
{ 
    #region PROPERTIES 

    public List<ReconcileItem> ReconcileItems { get; set;} 

    #endregion 

    #region CONSTRUCTORS 

    public ReconcileModel() 
    { 
     ReconcileItems = new List<ReconcileItem>(); 
    } 

    #endregion 
} 

Ecco una classe per rappresentare ogni record nella tabella.

public class ReconcileItem 
{ 
    #region PROPERTIES 

    public int ID { get; set; } 
    public string Description { get; set; } 
    public string LastLocation { get; set; } 
    public string LastRead { get; set; } 
    public string IntendenLocation { get; set; } 
    public string PickId { get; set; } 
    public string OEM { get; set; } 
    public string LotNumber { get; set; } 
    public string SerialNumber { get; set; } 
    public DateTime ExpirationDate { get; set; } 
    public string ReconcileReason { get; set; } 
    public string RemoveReason { get; set; } 


    #endregion 

    #region CONSTRUCTORS 

    public ReconcileItem() 
    { 
    } 

    #endregion 
} 

La rappresentazione contratto WCF della classe di cui sopra sarebbe

[DataContract] 
public class ReconcileItem 
{ 
    [DataMemeber] 
    public int ID { get; set; } 
    [DataMember] 
    public string Description { get; set; } 
    [DataMember] 
    public string LastLocation { get; set; } 
    [DataMember] 
    public string LastRead { get; set; } 
    [DataMember] 
    public string IntendenLocation { get; set; } 
    [DataMemeber] 
    public string PickId { get; set; } 
    [DataMember] 
    public string OEM { get; set; } 
    [DataMember] 
    public string LotNumber { get; set; } 
    [DataMember] 
    public string SerialNumber { get; set; } 
    [DataMember] 
    public DateTime ExpirationDate { get; set; } 
    [DataMember] 
    public string ReconcileReason { get; set; } 
    [DataMember] 
    public string RemoveReason { get; set; } 
} 

Se voglio aggiornare questo record, la classe viene inviato al servizio WCF, mappato appropriate classi Entity Framework, e salvato al database. Per semplificare il trasferimento ho pensato di inserire questa classe nel progetto WCF e di farne riferimento nel progetto MVC. Quindi potrei passare la classe in avanti tra WCF e MVC. Inoltre, se avessi aggiornato la classe in WCF, questa si sarebbe riflessa in MVC. Questo è ciò che si intende per centralizzato.

+0

La tua domanda è un po 'vaga. Puoi presentarci un codice, ad esempio mostrando cosa intendi per "classe centralizzata"? – Steven

+0

@Steven vedere le modifiche e fammi sapere se questo chiarisce le cose. Grazie! – Will

risposta

2

Proprio come Adrian, mi chiedo se sia effettivamente necessario un servizio WCF tra il DB e un servizio MVC. Questo è uno scenario molto più probabile per un'applicazione client (Win Form, WPF) che comunica con un database. Attualmente sto lavorando su un progetto Form Win dove usiamo WCF come strato intermedio e do il seguente:

  • Abbiamo un gruppo (denominato 'contratto') che viene condiviso tra il client e il WCF/BL .
  • Questo assembly "contratto" contiene tutti gli DTO inviati sul cavo da e verso WCF.
  • Abbiamo configurato il proxy client WCF per utilizzare l'assembly del contratto (invece di consentire a WCF di rigenerare tutti i DTO) impostando il 'Riutilizzo dei tipi negli assembly di riferimento specificati' nelle Impostazioni di riferimento del servizio.
  • Decoriamo questi DTO con gli attributi DataAnnotations (e altri metadati).
  • Noi non decorare quelle DTO con attributi WCF. WCF non ha bisogno di loro per serializzare DTO. Sono facoltativo. Lasciali fuori se puoi. Ingombra solo il tuo codice.
  • Poiché il client utilizza lo stesso assembly, è possibile utilizzare DataAnnotations sul client.
  • Noi convalidiamo anche sul server.
  • Utilizziamo AutoMapper per eseguire la maggior parte della mappatura delle entità dalle DTI (ma mai viceversa).
  • Per essere sinceri, non si permette nemmeno a WCF di serializzare i nostri DTO, ma usare JSON.NET e WCF semplicemente inviare e ricevere (testo normale) JSON, perché JSON.NET è semplicemente molto più flessibile quando si tratta di serializzare e deserializzare strutture dati Ad esempio, utilizziamo JSON.NET per (de) serializzare strutture di oggetti immutabili. Prova con WCF. Ciò fallirà miseramente.

In cima a quello che facciamo:

  • L'uso di classi vista del modello per aggiungere funzionalità di client.
  • Aggiungere convalide DataAnnotation personalizzate nell'assembly del contratto per consentire l'esecuzione delle convalide sul client e sul server.
  • Aggiungi un'astrazione IValidator<T> (di qualche tipo) per consentire convalide specifiche del server o del client (posizionando le implementazioni nel livello aziendale o nell'applicazione client).
  • Errori di convalida specifici del server di trasporto al client utilizzando le eccezioni.
+0

grazie per il tuo post, è stato molto istruttivo. Essenzialmente stavo pensando di rendere le classi ViewModel il DTO. Automatizzare tali classi in una classe WCF e quindi utilizzare il controller per passare la classe a un metodo WCF per l'aggiunta/l'aggiornamento/l'eliminazione. C'è un vantaggio nel metterli in un "contratto" come hai descritto? Piuttosto che limitarsi a definirli in WCF? – Will

+0

Se non li si inserisce nel proprio assieme e si condivide tale assembly tra server e client, significa che Visual Studio deve generare un proxy client per te e rigenererà il DTO sul client. Non solo questo causerà un carico di codice aggiuntivo (generato), VS * non * rigenererà mai alcun attributo (come gli attributi DataAnnotations) sul client. In altre parole: perderai tutti i metadati che hai definito su questi DTO. – Steven

2

È possibile utilizzare ancora le entità, ma creare modelli di visualizzazione e inserire le annotazioni di dati su questi. Si discute molto su dove inserire la convalida in un progetto. In generale è quasi sempre un dato di fatto che è necessario che si verifichi nell'interfaccia utente e quindi di solito anche altrove. Eviterei di provare a centralizzarlo, in quanto non funziona mai (una taglia raramente si adatta a tutti).

In tema di incuneamento di uno strato WCF all'interno di, la soluzione, a meno che non ci sia un buon motivo, eviterei di farlo a tutti i costi. Ho visto questo genere di cose andare storto molte volte. Porta molti effetti negativi. Nei due casi commerciali con cui ho avuto a che fare, si finisce con troppi endpoint e troppa chattiness. È in grado di mettere la logica aziendale nelle tue entità e utilizzare quei metodi over-the-wire, rende la manutenzione un incubo e senza hardware e progettazione accurata, se ospitato su un singolo server, potresti dover utilizzare pipe denominate per ottieni la velocità di cui hai bisogno, il che nega qualsiasi vantaggio distribuito derivante dall'utilizzo di WCF.

Si consiglia di esternalizzare attività di elaborazione pesanti come componenti che è possibile ospitare altrove e comunicare tramite un'interfaccia più piccola e concisa. In realtà, a parte l'elaborazione delle immagini, le applicazioni matematiche e scientifiche, l'elaborazione di dati pesanti non emerge.

+0

Vorrei anche aggiungere che esiste un rischio per la sicurezza nell'esporre le classi WCF come modelli MVC. – VsMaX

+1

L'idea di WCF in mezzo è che l'MVC sarebbe utilizzato solo per la presentazione. Quando i campi della pagina sono stati aggiornati e salvati; la classe verrà popolata e inviata al WCF per essere manipolata e salvata nel database. Ora la domanda è se questo è un modo ideale per farlo. Vogliamo che ogni servizio sia responsabile di un insieme di tabelle nel database, quindi i dati fluiscono sempre attraverso tali servizi se aggiunti/aggiornati/cancellati. – Will

+0

@Suona che suona bene, nei casi in cui ho visto i livelli interni di WCF causare problemi, è sempre stato a causa del fatto che il livello esponeva molti metodi come se fosse solo un assemblaggio. Con un'attenta elaborazione dello strato WCF, in teoria potrebbe/dovrebbe funzionare. Quello che probabilmente dovresti ottenere è un layer WCF che restituisce un set completo (quasi un modello di visualizzazione) di tutto ciò che è necessario per visualizzare una determinata pagina in una singola chiamata. In questo modo sarà più facile avviluppare uno strato di presentazione dell'app per telefoni cellulari in un secondo momento. Sarei solo attento a mantenere la logica di business da uno qualsiasi dei livelli sopra il livello WCF. –

2

Utilizziamo WCF nel modo in cui descrivi il tuo post presso il mio attuale datore di lavoro. Abbiamo finito per avere le classi DTO per comunicare con WCF e MVC e poi ViewModels all'interno dell'applicazione MVC per l'associazione e la convalida del modello all'interno dell'interfaccia utente.

Sono d'accordo sul fatto che avere classi che sono quasi duplicate l'una dell'altra e mappare tra loro è un dolore e sembra solo sbagliato a un certo livello. Da quello che ho letto in passato, quello che abbiamo fatto e quello che potresti essere costretto a fare, è la migliore pratica.

Ciò che Adrian ha proposto in precedenza solo per quanto riguarda l'elaborazione pesante eseguita da WCF ha anche senso. Prima di iniziare il mio attuale lavoro, l'ho fatto. La maggior parte della logica aziendale è stata inserita in un assembly del livello aziendale direttamente riferimento dall'applicazione MVC. Per i pochi processi potenzialmente lunghi sono stati creati servizi WCF ospitati separatamente con cui l'applicazione MVC comunicava.

Infine, è possibile utilizzare Web API vs WCF? L'API Web è leggera e utilizza HTTP senza l'overhead associato ai collegamenti WCF, ecc. Inoltre, con l'API Web è possibile utilizzare le stesse classi utilizzate dall'applicazione MVC e persino utilizzare la convalida del modello all'interno dell'API Web. Questo è qualcosa su cui ho lavorato e sta diventando sempre più comune.

Spero che questo aiuti!

+0

Grazie per la risposta. Mappare classi duplicate mi sembra sbagliato, ma come hai detto tu sembra essere la migliore pratica. Non ero a conoscenza di WebAPI fino ad ora. Sfortunatamente, i nostri servizi sono collegamenti TCP, ma WebAPI potrebbe essere utile su alcuni dei miei altri progetti. – Will

Problemi correlati