ServiceStack nuovo servizio fianco a fianco sito Web ASP.NET MVC

Negli esempi per ServiceStack non vedo prima una singola applicazione che è il sito Web ASP.NET MVC e quindi ha reso il servizio ServiceStack in secondo luogo.

Prendiamo una semplice applicazione web ASP.NET MVC che esegue il rendering dei prodotti tramite Views. Utilizza controller, viste, modelli e modelli di visualizzazione.

Diciamo che abbiamo un modello di Product che viene mantenuto in un DB del documento. Supponiamo di avere un viewmodel di ProductViewModel che viene mappato da Product e visualizzato all’interno di MVC Razor View / PartialView.

quindi questo è un lato web delle cose … ora supponiamo di voler aggiungere un servizio che restituisca prodotti a vari client come le applicazioni di Windows 8.

Le classi di richiesta / risposta dovrebbero essere completamente disconnesse da ciò che abbiamo già? Il nostro ProductViewModel potrebbe già contenere tutto ciò che vogliamo restituire dal servizio.

Dato che abbiamo già Product (class del modello) non possiamo avere un’altra class Product nello spazio dei nomi API … beh, potremmo, ma questo rende le cose poco chiare e vorrei evitarlo.

Quindi, dovremmo introdurre la class ProductRequest standalone e la class ProductRequestResponse (eredita ProductViewModel) nello spazio dei nomi API?

Ti piace ProductRequestResponse : ProductViewModel ?

Quello che sto dicendo è che abbiamo già le classi Model e ViewModel e per build classi di richieste e risposte per il servizio SS dovremmo creare altri due file, principalmente copiando tutto dalle classi che già abbiamo. Questo non mi sembra ASCIUTTO, potrebbe seguire le linee guida sulla separazione delle preoccupazioni ma anche SECCO è importante, in realtà più che separare tutto (separare tutto porta alla duplicazione del codice).

Quello che mi piacerebbe vedere è un caso in cui è già stata creata un’applicazione Web, attualmente è dotata di Modelli e ViewModels e restituisce le Visualizzazioni appropriate per la visualizzazione sul Web, ma può essere estesa a un servizio pienamente funzionale per supportare i client programmatici? Come i client AJAX ecc. Con ciò che abbiamo già.

Un’altra cosa:

Se dai un’occhiata a questo esempio https://github.com/ServiceStack/ServiceStack.Examples/blob/master/src/ServiceStack.MovieRest/MovieService.cs

vedrai che c’è la class Richiesta Movie e la class Richiesta Movies (una per la richiesta di un solo film, l’altra per un elenco di film). Come tale, ci sono anche due servizi, MovieService e MoviesService , uno che si occupa di richieste per un singolo film, l’altro per un genere di film.

Ora, mentre mi piace l’approccio SS ai servizi e penso che sia quello giusto, non mi piace questo tipo di separazione semplicemente a causa del tipo di richiesta. E se volessi dei film per regista? Sarei stato in grado di inventare un’altra class di richieste con una proprietà Director e ancora un altro servizio ( MoviesByDirector ) per questo?

Penso che i campioni dovrebbero essere orientati verso un servizio. Tutto ciò che ha a che fare con i film deve essere sotto lo stesso tetto. Come si raggiunge questo con ServiceStack?

 public class ProductsService : Service { private readonly IDocumentSession _session; private readonly ProductsHelperService _productsHelperService; private readonly ProductCategorizationHelperService _productCategorization; public class ProductRequest : IReturn { public int Id { get; set; } } // Does this make sense? // Please note, we use ProductViewModel in our Views and it holds everything we'd want in service response also public class ProductRequestResponse : ProductViewModel { } public ProductRequestResponse GetProducts(ProductRequest request) { ProductRequestResponse response = null; if (request.Id >= 0) { var product = _session.Load(request.Id); response.InjectFrom(product); } return response; } } 

Il Service Layer è il tuo contratto più importante

L’interfaccia più importante che puoi mai creare nell’intero sistema è il tuo contratto di servizio esterno, questo è ciò a cui i consumatori del tuo servizio o dell’applicazione si legano, vale a dire i siti di chiamata esistenti che spesso non vengono aggiornati insieme al tuo codice -base – ogni altro modello è secondario.

Le DTO sono le migliori pratiche per i servizi remoti

Seguendo la raccomandazione di Martin Fowler sull’utilizzo di DTO (Data Transfer Objects) per servizi remoti ( MSDN ), ServiceStack incoraggia l’uso di POCO puliti e non contaminati per definire un contratto ben definito con quello che dovrebbe essere mantenuto in gran parte implementato e privo di dipendenza. dll. I vantaggi di questo ti consentono di riutilizzare DTO tipizzati utilizzati per definire i tuoi servizi con, come è, nei tuoi client C # /. NET – fornendo un’API tipizzata end-to-end senza l’uso di alcun codice- gen o altre macchine artificiali.

DRY vs Intent

Mantenere le cose ASCIUTTE non deve essere confuso con affermazioni chiare di intenti, che dovresti evitare di provare a ASCIUGARE o nascondersi dietro eredità , proprietà magiche o qualsiasi altro meccanismo. Con DTO puliti e ben definiti fornisce un’unica fonte di riferimento che chiunque può vedere per vedere cosa accetta e restituisce ciascun servizio, consente agli sviluppatori client e server di iniziare immediatamente il proprio lavoro e associarsi ai modelli di servizio esterni senza l’implementazione essendo stato scritto

Mantenere separati i DTO consente inoltre di ridimensionare l’implementazione dall’interno senza rompere i client esterni, ovvero il servizio inizia a memorizzare le risposte nella cache o utilizza una soluzione NoSQL per compilare le risposte.

Fornisce anche la fonte autorevole (che non è trapelata o accoppiata all’interno della logica dell’app) utilizzata per creare pagine di metadati generate automaticamente, risposte di esempio, supporto di Swagger, XSD, WSDL, ecc.

Utilizzo della mapping automatica integrata di ServiceStack

Mentre incoraggiamo la conservazione di modelli DTO separati, non è necessario mantenere la propria mapping manuale poiché è ansible utilizzare un mappatore come AutoMapper o il supporto Auto Mapping integrato di ServiceStack, ad esempio:

Crea una nuova istanza DTO, popolata con proprietà corrispondenti su viewModel:

 var dto = viewModel.ConvertTo(); 

Inizializza DTO e compila con le proprietà corrispondenti su un modello di visualizzazione:

 var dto = new MyDto { A = 1, B = 2 }.PopulateWith(viewModel); 

Inizializza DTO e compila con proprietà di corrispondenza non predefinite su un modello di vista:

 var dto = new MyDto { A = 1, B = 2 }.PopulateWithNonDefaultValues(viewModel); 

Inizializza DTO e compila le proprietà corrispondenti annotate con Attrib Attribute su un modello di vista:

 var dto = new MyDto { A=1 }.PopulateFromPropertiesWithAttribute(viewModel); 

Quando la logica della mapping diventa più complicata, ci piace usare i metodi di estensione per mantenere il codice DRY e mantenere la mapping in un posto facilmente consumabile dall’interno dell’applicazione, ad esempio:

 public static class MappingExtensions { public static MyDto ToDto(this MyViewModel viewModel) { var dto = viewModel.ConvertTo(); dto.Items = viewModel.Items.ConvertAll(x => x.ToDto()); dto.CalculatedProperty = Calculate(viewModel.Seed); return dto; } } 

Che ora è facilmente consumabile con solo:

 var dto = viewModel.ToDto(); 

Se non sei legato in modo specifico a ServiceStack e desideri semplicemente “un servizio pienamente funzionale per supportare i client programmatici … con quello che già abbiamo”, potresti provare quanto segue: Chiedi ai tuoi controller di restituire ViewResult o JsonResult base JsonResult della richiesta header – Request.AcceptTypes.Contains("text/html") o Request.AcceptTypes.Contains("application/json") .

Sia ViewResult che JsonResult sono ActionResult , quindi la firma delle azioni rimane la stessa e sia View() che Json() accettano un ViewModel. Inoltre, se si dispone di un ControllerBase, è ansible creare un metodo di base (ad esempio protected ActionResult RespondWith(Object viewModel) ) che chiama View () o Json () in modo che la modifica al codice esistente sia minima.

Ovviamente, se i tuoi ViewModels non sono puri (cioè hanno alcune cose specifiche per l’html o ti affidi ad alcuni Magic di ViewBag) allora è un po ‘più di lavoro. Inoltre, non verrà fornito SOAP o altri tipi di binding forniti da ServiceStack, ma se il tuo objective è supportare un’interfaccia dati JSON con modifiche minime del codice all’app MVC esistente, questa potrebbe essere una soluzione.

Lp