asp.net - net - servicestack que es
¿Cómo puedo usar un objeto de sesión ASP.NET estándar dentro de la implementación del servicio ServiceStack? (4)
A partir de ServiceStack 4.5+, HttpHandler también puede admitir Async. Al igual que:
namespace FboOne.Services.Host
{
public class SessionHttpHandlerFactory : IHttpHandlerFactory
{
private static readonly HttpHandlerFactory Factory = new HttpHandlerFactory();
public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
{
var handler = Factory.GetHandler(context, requestType, url, pathTranslated);
return handler == null ? null : new SessionHandlerDecorator((IHttpAsyncHandler)handler);
}
public void ReleaseHandler(IHttpHandler handler)
{
Factory.ReleaseHandler(handler);
}
}
public class SessionHandlerDecorator : IHttpAsyncHandler, IRequiresSessionState
{
private IHttpAsyncHandler Handler { get; set; }
internal SessionHandlerDecorator(IHttpAsyncHandler handler)
{
Handler = handler;
}
public bool IsReusable
{
get { return Handler.IsReusable; }
}
public void ProcessRequest(HttpContext context)
{
Handler.ProcessRequest(context);
}
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
return Handler.BeginProcessRequest(context, cb, extraData);
}
public void EndProcessRequest(IAsyncResult result)
{
Handler.EndProcessRequest(result);
}
}
}
Acabo de comenzar con ServiceStack y, como caso de prueba, busco volver a trabajar un servicio existente que se construye utilizando los controladores estándar de ASP.Net. Me las arreglé para hacer que todo funcione como lo quiero, pero tengo ciertos aspectos que hacen uso del objeto de sesión de ASP.Net.
He intentado agregar IRequiresSessionState en la interfaz de servicio:
public class SessionTestService : RestServiceBase<SessionTest>, IRequiresSessionState {
public override object OnPost(SessionTest request) {
// Here I want to use System.Web.HttpContext.Current.Session
}
}
El problema es que parece que no puedo hacer que funcione, ya que el objeto Session siempre es nulo.
He hecho un montón de Google y he desconcertado en https://github.com/mythz/ServiceStack/blob/master/tests/ServiceStack.WebHost.IntegrationTests/Services/Secure.cs y similares pero no puedo encontrar ninguna Código de ejemplo que hace esto (lo que me sorprende). ¿Alguien puede explicar por qué lo anterior no funciona y aconsejar qué debo hacer para que funcione?
Nota: En última instancia, probablemente buscaré reemplazar esto con Redis o intentaré eliminar cualquier requisito de la sesión del servidor, pero pensé que usaría la implementación de ASP.Net por el momento, para que las cosas funcionen y para evitar volver a trabajar. Más de lo necesario en este punto.
Esa es una gran y completa respuesta por @mythz. Sin embargo, al intentar acceder a la sesión ASP.NET mediante HttpContext.Current.Session
dentro de un servicio web ServiceStack, siempre me devuelve un null
. Esto se debe a que ninguno de los HttpHandlers dentro de ServiceStack está adornado con la interfaz IRequiresSessionState
, por lo que .NET Framework no nos proporciona el objeto de la sesión.
Para solucionar esto, he implementado dos nuevas clases, las cuales utilizan el patrón de decorador para proporcionarnos lo que necesitamos.
En primer lugar, un nuevo IHttpHandler
que requiere estado de sesión. Envuelve el IHttpHandler
proporcionado por ServiceStack y le pasa las llamadas ...
public class SessionHandlerDecorator : IHttpHandler, IRequiresSessionState {
private IHttpHandler Handler { get; set; }
internal SessionHandlerDecorator(IHttpHandler handler) {
this.Handler = handler;
}
public bool IsReusable {
get { return Handler.IsReusable; }
}
public void ProcessRequest(HttpContext context) {
Handler.ProcessRequest(context);
}
}
A continuación, un nuevo IHttpHandlerFactory
que delega la responsabilidad de generar el IHttpHandler
a ServiceStack, antes de envolver el controlador devuelto en nuestro nuevo SessionHandlerDecorator
...
public class SessionHttpHandlerFactory : IHttpHandlerFactory {
private readonly static ServiceStackHttpHandlerFactory factory = new ServiceStackHttpHandlerFactory();
public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated) {
var handler = factory.GetHandler(context, requestType, url, pathTranslated);
return handler == null ? null : new SessionHandlerDecorator(handler);
}
public void ReleaseHandler(IHttpHandler handler) {
factory.ReleaseHandler(handler);
}
}
Entonces, solo es cuestión de cambiar los atributos de type
en los controladores en Web.config a SessionHttpHandlerFactory
lugar de ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack
, y sus servicios web deben tener la sesión ASP.NET disponible para ellos.
A pesar de lo anterior, respaldo completamente la nueva implementación de ISession
proporcionada por ServiceStack. Sin embargo, en algunos casos, en un producto maduro, simplemente parece un trabajo demasiado grande para reemplazar todos los usos de la sesión ASP.NET con la nueva implementación, por lo tanto, esta solución alternativa.
Gracias @Richard por tu respuesta arriba. Estoy ejecutando una nueva versión de la pila de servicios y han eliminado el ServiceStackHttpFactory con HttpFactory. En vez de tener
private readonly static ServiceStackHttpHandlerFactory factory = new ServiceStackHttpHandlerFactory();
Necesitas tener
private static readonly HttpHandlerFactory Factory = new HttpHandlerFactory();
Aquí está el código actualizado para este servicio.
using ServiceStack;
using System.Web;
using System.Web.SessionState;
namespace MaryKay.eCommerce.Mappers.AMR.Host
{
public class SessionHttpHandlerFactory : IHttpHandlerFactory
{
private static readonly HttpHandlerFactory Factory = new HttpHandlerFactory();
public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
{
var handler = Factory.GetHandler(context, requestType, url, pathTranslated);
return handler == null ? null : new SessionHandlerDecorator(handler);
}
public void ReleaseHandler(IHttpHandler handler)
{
Factory.ReleaseHandler(handler);
}
}
public class SessionHandlerDecorator : IHttpHandler, IRequiresSessionState
{
private IHttpHandler Handler { get; set; }
internal SessionHandlerDecorator(IHttpHandler handler)
{
Handler = handler;
}
public bool IsReusable
{
get { return Handler.IsReusable; }
}
public void ProcessRequest(HttpContext context)
{
Handler.ProcessRequest(context);
}
}
}
Usando ServiceStack ISession
ServiceStack tiene una nueva interfaz ISession
respaldada por ICacheClient
que le permite compartir la misma ISession
entre los controladores MVC, las páginas base de ASP.NET y los servicios web de ServiceStack que comparten la misma Id. De cookie, lo que le permite compartir libremente los datos entre estos marcos web.
Nota: ISession es una implementación limpia que omite por completo la sesión ASP.NET existente con los componentes propios de ServiceStack, tal como se describe en el PowerPack MVC de ServiceStack y se explica en detalle en la página de la wiki Sesiones .
Para hacer uso fácil de la sesión de ServiceStack (caché y JSON Serializer), los controladores se heredan de ServiceStackController (en MVC) o PageBase (en ASP.NET)
También hay una nueva funcionalidad de autenticación / validación agregada en ServiceStack que puede leer en la wiki:
Usando la sesión de ASP.NET
Básicamente, ServiceStack es solo un conjunto de IHttpHandler ligero que se ejecuta en un host ASP.NET o HttpListener. Si está alojado en IIS / ASP.NET (lo más común) funciona como una solicitud normal de ASP.NET.
Nada en ServiceStack accede o afecta a los proveedores de caché y sesión configurados en la aplicación ASP.NET subyacente. Si desea habilitarlo, deberá configurarlo según lo normal en ASP.NET (es decir, fuera de ServiceStack), consulte:
http://msdn.microsoft.com/en-us/library/ms178581.aspx
Una vez configurado, puede acceder a la sesión ASP.NET dentro de un servicio web ServiceStack a través del singleton:
HttpContext.Current.Session
O, alternativamente, a través de la HttpRequest de ASP.NET subyacente con:
var req = (HttpRequest)base.RequestContext.Get<IHttpRequest>().OriginalRequest;
var session = req.RequestContext.HttpContext.Session;
Aunque debido a la dependencia obligatoria de la configuración XML y al rendimiento degradado de forma predeterminada , prefiero evitar el uso de la sesión de ASP.NET, en lugar de usar los Clientes de caché más limpios incluidos con ServiceStack.
Básicamente, la forma en que funcionan las Sesiones (incluido ASP.NET) es una cookie que contiene una identificación única y se agrega a la Respuesta que identifica de forma única la sesión del navegador. Esta identificación apunta a un diccionario / colección correspondiente en el servidor que representa la sesión de los navegadores.
La interfaz IRequiresSession a la que se vincula no hace nada de forma predeterminada, simplemente es una forma de indicar a un Filtro de solicitud personalizado o al servicio web base que esta solicitud debe estar autenticada (es decir, dos lugares donde debe colocar la lógica de validación / autenticación en ServiceStack).
Aquí hay una implementación de Autenticación Básica que busca ver si un servicio web es Seguro y, de ser así, asegúrese de que se hayan autenticado.
Aquí hay otra implementación de autenticación que, en cambio, valida todos los servicios marcados con un atributo [Autenticar] , y cómo habilitar la autenticación para su servicio agregando el atributo en su DTO de solicitud.
Nuevo modelo de autenticación en ServiceStack
La implementación anterior es parte del modelo de proveedor de autenticación múltiple incluido en la próxima versión de ServiceStack. Este es el ejemplo de referencia que muestra cómo registrar y configurar el nuevo modelo de Auth en su aplicación.
Estrategias de autenticación
El nuevo modelo de Auth es una conveniencia totalmente opcional, ya que simplemente no puede usarlo e implementar un comportamiento similar utilizando los Filtros de solicitud o en clases base (anulando OnBeforeExecute ). De hecho, los nuevos servicios de Auth no están realmente integrados en ServiceStack per-se. Toda la implementación se encuentra en el proyecto opcional ServiceStack.ServiceInterfaces y se implementa mediante filtros de solicitud personalizados.
Aquí hay diferentes estrategias de autenticación que he usado durante los años:
Marque los servicios que necesitan autenticación con un [atributo] . Probablemente la forma más idiomática de C #, ideal cuando la sesión-id se pasa a través de una cookie.
Especialmente fuera de un contexto web, a veces es mejor usar una interfaz IRequiresAuthentication más explícita, ya que proporciona un acceso de tipo fuerte al User y SessionId requerido para la autenticación.
Solo puede tener un 1-liner para autenticarse en cada servicio que lo necesite, sobre una base ad hoc. Un enfoque adecuado cuando tiene muy pocos servicios que requieren autenticación.