ServiceStack nuevo servicio lado a lado ASP.NET Sitio web MVC


En los ejemplos para ServiceStack no veo una sola aplicación que sea ASP.NET El sitio web de MVC primero y luego el servicio ServiceStack segundo.

Vamos a tomar un muy simple ASP.NET Aplicación web MVC que renderiza productos a través de vistas. Utiliza controladores, vistas, modelos y viewmodels.

Digamos que tenemos un modelo de Product que se mantiene en una DB de documento. Supongamos que tenemos un viewmodel de ProductViewModel que se mapea desde Product y se muestra dentro MVC Razor View / PartialView.

Así que este es un lado web de las cosas..ahora supongamos que queremos agregar un servicio que devuelve productos a varios clientes como las aplicaciones de Windows 8.

¿Deberían las clases request/response estar completamente desconectadas de lo que ya tenemos? Es posible que nuestro ProductViewModel ya contenga todo lo que queremos devolver del servicio.

Dado que ya tenemos Product (clase modelo) no podemos tener otra clase Product en el espacio de nombres de la API..bueno, podríamos pero eso hace que las cosas no estén claras y me gustaría evitarlo.

Entonces, ¿deberíamos introducir la clase independiente ProductRequest y la clase ProductRequestResponse (hereda ProductViewModel) en el espacio de nombres de la API?

Así ProductRequestResponse : ProductViewModel?

Lo que estoy diciendo es que ya tenemos las clases Model y ViewModel y para construir las clases Request y Response para el servicio SS tendríamos que crear otros dos archivos, principalmente copiando todo de las clases que ya tenemos. Esto no me parece SECO, podría siga las pautas de separación de preocupaciones, pero DRY también es importante, en realidad más que separar todo (separar todo conduce a la duplicación de código).

Lo que me gustaría ver es un caso en el que una aplicación web ya se ha hecho, actualmente cuenta con Modelos y ViewModels y devuelve las vistas adecuadas para su visualización en la Web, pero se puede extender a un servicio completamente funcional para apoyar a los clientes programáticos? Como clientes de AJAX etc...con lo que ya tener.

Otra cosa:

Si echas un vistazo a este ejemplo https://github.com/ServiceStack/ServiceStack.Examples/blob/master/src/ServiceStack.MovieRest/MovieService.cs

Verá que hay Movie Clase de solicitud y Movies Clase de solicitud (una para solicitud de una sola película, la otra para una lista de películas). Como tal, también hay dos servicios, MovieService y MoviesService, uno que se ocupa de las solicitudes de una sola película, el otro para un género de películas.

Ahora bien, aunque me gusta el enfoque de SS a los servicios y creo que es el correcto, no me gusta este tipo de separación simplemente por el tipo de solicitud. ¿Y si quisiera películas por director? ¿Estaría inventando otra clase request que tenga una propiedad Director y otro servicio (MoviesByDirector) para ella?

Creo que las muestras deben estar orientadas hacia un solo servicio. Todo lo que tiene que ver con las películas tiene que estar bajo un mismo techo. ¿Cómo se logra eso con ¿ServiceStack?

public class ProductsService : Service
{
    private readonly IDocumentSession _session;
    private readonly ProductsHelperService _productsHelperService;
    private readonly ProductCategorizationHelperService _productCategorization;

    public class ProductRequest : IReturn<ProductRequestResponse>
    {
        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<Product>(request.Id);
            response.InjectFrom(product);
        }
        return response;
    }
}
Author: mare, 2013-03-12

2 answers

La Capa de Servicio es su Contrato más importante

La interfaz más importante que puede crear en todo su sistema es su contrato de servicio externo, esto es a lo que se unirán los consumidores de su servicio o aplicación, es decir, los sitios de llamadas existentes que a menudo no se actualizarán junto con su base de código: todos los demás modelos son secundarios.

Los TDT son las mejores prácticas para los servicios remotos

Siguiendo la recomendación de Martin Fowler para uso de DTOs (Objetos de transferencia de datos) para servicios remotos (MSDN), ServiceStack fomenta el uso de POCOs limpios y sin contaminación para definir un contrato bien definido con el que se debe mantener en gran medida una implementación y libre de dependencias .DLL. Los beneficios de esto le permiten ser capaz de reutilizar los DTO tipeados utilizados para definir sus servicios con, tal cual, en sus clientes C#/. NET , proporcionando una API tipeada de extremo a extremo sin el uso de cualquier gen de código u otro maquinaria.

SECO vs Intención

Mantener las cosas SECAS no debe confundirse con indicar claramente la intención, que debe evitar tratar de SECAR o esconderse detrás de la herencia, propiedades mágicas o cualquier otro mecanismo. Tener DTOS limpios y bien definidos proporciona una única fuente de referencia que cualquiera puede ver para ver lo que cada servicio acepta y devuelve, permite a los desarrolladores de clientes y servidores comenzar su trabajo de inmediato y vincularse a los modelos de servicio externos sin que la implementación haya sido escrita.

Mantener los DTO separados también le da la libertad de volver a factorizar la implementación desde dentro sin romper los clientes externos, es decir, su servicio comienza a almacenar en caché las respuestas o aprovecha una solución NoSQL para completar sus respuestas.

También proporciona la fuente autorizada (que no se filtra ni se acopla dentro de la lógica de su aplicación) que se utiliza para crear las páginas de metadatos generadas automáticamente, respuestas de ejemplo, Swagger soporte, XSDs, WSDLs, etc.

Usando el mapeo automático integrado de ServiceStack

Aunque recomendamos mantener modelos DTO separados, no necesita mantener su propio mapeo manual, ya que puede usar un mapeador como AutoMapper o usar el soporte de Mapeo automático integrado de ServiceStack, por ejemplo:

Crear una nueva instancia DTO, poblada con propiedades coincidentes en ViewModel:

var dto = viewModel.ConvertTo<MyDto>();

Inicialice DTO y rellénelo con propiedades coincidentes en una vista modelo:

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

Inicialice DTO y rellénelo con propiedades coincidentes no predeterminadas en un modelo de vista:

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

Inicialice DTO y rellénelo con propiedades coincidentes que están anotadas con el atributo Attr en un modelo de vista:

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

Cuando la lógica de asignación se vuelve más complicada, nos gusta usar métodos de extensión para mantener el código SECO y mantener la asignación en un lugar que sea fácilmente consumible desde su aplicación, por ejemplo:

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

Que ahora es fácilmente consumible con solo:

var dto = viewModel.ToDto();
 70
Author: mythz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-27 13:45:56

Si no está vinculado específicamente a ServiceStack y solo desea "servicio completamente funcional para apoyar a los clientes programáticos ... con lo que ya tenemos", puede intentar lo siguiente: Que sus controladores devuelvan un ViewResult o un JsonResult basado en el encabezado accept de la solicitud - Request.AcceptTypes.Contains("text/html") o Request.AcceptTypes.Contains("application/json").

Tanto ViewResult como JsonResult son ActionResult, por lo que la firma de las acciones sigue siendo la misma, y tanto View() como Json() aceptan un ViewModel. Además, si tienes un ControllerBase puedes hacer un método base (por ejemplo protected ActionResult RespondWith(Object viewModel)) que llama a View() o Json() por lo que el cambio al código existente es mínimo.

Por supuesto, si tus ViewModels no son puros (es decir, tienen algunas cosas específicas de html o confías en alguna magia de ViewBag), entonces es un poco más de trabajo. Y no obtendrá SOAP u otros tipos de enlace proporcionados por ServiceStack, pero si su objetivo es admitir una interfaz de datos JSON con cambios mínimos de código en la aplicación MVC existente, esto podría ser una solución.

Lp

 2
Author: Boris B.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-10 22:36:50