Jak mogę korzystać ze standardowego ASP.NET obiekt sesji w implementacji usługi ServiceStack

Dopiero zaczynam pracę z ServiceStack i, jako przypadek testowy, chcę przerobić istniejącą usługę, która jest zbudowana przy użyciu standardowego ASP.Net pomocnicy. Udało mi się wszystko działać tak, jak chcę, ale mam pewne aspekty, które wykorzystują ASP.Net obiekt sesji.

Próbowałem dodać IRequiresSessionState do interfejsu serwisu:

public class SessionTestService : RestServiceBase<SessionTest>, IRequiresSessionState {
    public override object OnPost(SessionTest request) {
        // Here I want to use System.Web.HttpContext.Current.Session
    }
}

Problem w tym, że nie mogę go uruchomić, ponieważ obiekt sesji jest zawsze null.

Zrobiłem wiele Googlowania i zastanawiali się nad https://github.com/mythz/ServiceStack/blob/master/tests/ServiceStack.WebHost.IntegrationTests/Services/Secure.cs i podobne, ale nie mogę znaleźć żadnego przykładowego kodu, który to robi (co mnie zaskakuje). Czy ktoś może wyjaśnić, dlaczego powyższe nie działa i doradzić, co muszę zrobić, aby to działało?

Uwaga: ostatecznie prawdopodobnie będę szukał, aby zastąpić to Redis lub spróbuję usunąć wszelkie wymagania dotyczące sesji serwera, ale pomyślałem, że użyj ASP.Net wdrożenie na razie, aby wszystko działało i uniknąć przeróbek bardziej niż jest to konieczne w tym momencie.

Author: skaffman, 2011-12-01

4 answers

Korzystanie Z ServiceStack ISession

ServiceStack posiada nowy Interfejs ISession wspierany przez ICacheClient, który pozwala na współdzielenie tego samego ISession pomiędzy kontrolerami MVC, ASP.NET strony bazowe i serwisy internetowe ServiceStack, które mają ten sam identyfikator pliku cookie, umożliwiając swobodne udostępnianie danych między tymi strukturami sieciowymi.

Uwaga: ISession jest czystą implementacją , która całkowicie pomija istniejące ASP.NET sesji z własnymi komponentami ServiceStack opisanymi w MVC Powerpack ServiceStack i szczegółowo wyjaśnione na stronie wiki Sessions .

Aby w prosty sposób korzystać z sesji ServiceStack (Cache & JSON Serializer), Kontrolery dziedziczą z ServiceStackController (W MVC) lub PageBase (w ASP.NET)

W ServiceStack dodano również nową funkcjonalność uwierzytelniania / walidacji, o której można przeczytać na wiki:

Za pomocą ASP.NET sesja

Zasadniczo ServiceStack jest tylko zestawem lekkich IHttpHandler ' s działających na ASP.NET lub host HttpListener. Jeśli hostowane w IIS/ASP. NET (najczęściej) działa jak normalny ASP.NET Prośba.

Nic w ServiceStack nie ma dostępu ani wpływu na skonfigurowane buforowanie i dostawców sesji w podstawowym ASP.NET podanie. Jeśli chcesz włączyć to trzeba by go skonfigurować jak normalnie w ASP.NET (tj. poza ServiceStack) patrz:

Http://msdn.microsoft.com/en-us/library/ms178581.aspx

Po skonfigurowaniu można uzyskać dostęp do ASP.NET sesja wewnątrz serwisu ServiceStack poprzez singleton:

HttpContext.Current.Session

Lub alternatywnie poprzez bazowe ASP.NET HttpRequest with:

var req = (HttpRequest)base.RequestContext.Get<IHttpRequest>().OriginalRequest;
var session = req.RequestContext.HttpContext.Session;

Chociaż ze względu na obowiązkowe poleganie na XML config i pogorszenie wydajności domyślnie, I wolą unikać używania ASP.NET sesji, zamiast tego decydując się na użycie Cleaner Cache Clients dołączonego do ServiceStack.

Zasadniczo sposób pracy sesji (ASP.NET zawiera) plik cookie zawierający unikalny identyfikator jest dodawany do odpowiedzi jednoznacznie identyfikującej sesję przeglądarki. Ten id wskazuje na pasujący Słownik/kolekcję na serwerze, która reprezentuje sesję przeglądarki.

Irequiressession interfejs, do którego linkujesz, nie działa domyślnie jest to po prostu sposób na zasygnalizowanie do niestandardowego filtra żądań lub podstawowej usługi internetowej, że żądanie to musi zostać uwierzytelnione (tzn. dwa miejsca, w których należy umieścić logikę walidacji/uwierzytelniania w ServiceStack).

Oto podstawowa implementacja Auth , która sprawdza, czy usługa internetowa jest Bezpieczna i jeśli tak, upewnij się, że została uwierzytelniona.

Oto kolejna implementacja uwierzytelniania , która zamiast tego sprawdza wszystkie usługi oznaczone z atrybutem [Authenticate] i jak włączyć uwierzytelnianie dla usługi {[15] } poprzez dodanie atrybutu na żądanie DTO.

Nowy model uwierzytelniania w ServiceStack

Powyższa implementacja jest uzupełnieniem modelu multi-auth provider zawartego w następnej wersji ServiceStack. Oto przykład referencyjny pokazujący, jak zarejestrować i skonfigurować nowy model Auth w aplikacji.

Uwierzytelnianie Strategie

Nowy Model Auth jest całkowicie wygodny, ponieważ można go po prostu nie używać i zaimplementować podobne zachowanie samodzielnie za pomocą filtrów żądań lub w klasach bazowych (przez nadpisanie OnBeforeExecute). W rzeczywistości nowe usługi Auth nie są wbudowane w ServiceStack per-se. Cała implementacja znajduje się w opcjonalnym ServiceStack.Projekt ServiceInterfaces i zaimplementowany przy użyciu niestandardowych filtrów zapytań.

Oto różne strategie uwierzytelniania, z których korzystałem przez lata:

  • Oznacz usługi wymagające uwierzytelnienia atrybutem [. Prawdopodobnie najbardziej idiomatyczny sposób C#, idealny, gdy session-id jest przekazywany przez plik Cookie.

  • Szczególnie poza kontekstem sieciowym, czasami lepiej jest używać bardziej wyraźnego interfejsu irequiresauthentication , ponieważ zapewnia on silny dostęp do użytkownika i SessionId wymagane dla Uwierzytelnianie.

  • Możesz po prostu mieć 1-liner do uwierzytelnienia każdej usługi, która jej potrzebuje - na zasadzie adhoc. Odpowiednie podejście, gdy masz bardzo mało usług wymagających uwierzytelniania.

 28
Author: mythz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:17:11

To świetna i wyczerpująca odpowiedź @mythz. Jednak przy próbie uzyskania dostępu do ASP.NET session by HttpContext.Current.Session wewnątrz serwisu ServiceStack, zawsze zwraca null dla mnie. Dzieje się tak dlatego, że żaden z Httphandlerów w ServiceStack nie jest ozdobiony interfejsem IRequiresSessionState, więc. NET Framework nie dostarcza nam obiektu session.

Aby to obejść, zaimplementowałem dwie nowe klasy, z których obie wykorzystują wzór dekoratora, aby zapewnić nam to, co my potrzeba.

Po pierwsze, Nowy IHttpHandler, który wymaga stanu sesji. Zawija IHttpHandler dostarczone przez ServiceStack i przekazuje do niego połączenia...

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);
    }
}

Następnie Nowy IHttpHandlerFactory, który przekazuje odpowiedzialność za wygenerowanie IHttpHandler do ServiceStack, przed owinięciem zwróconego Handlera w nasz nowy 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);
    }

}

Następnie, to tylko kwestia zmiany atrybutów type w programach obsługi w sieci.config do SessionHttpHandlerFactory zamiast ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack, a twoje serwisy www powinny mieć na ASP.NET sesja dostępna dla nich.

Pomimo powyższego, w pełni popieram nową implementację ISession dostarczoną przez ServiceStack. Jednak w niektórych przypadkach, na dojrzałym produkcie, po prostu wydaje się zbyt duże zadanie, aby zastąpić wszystkie zastosowania ASP.NET sesja z nową implementacją, stąd To obejście!

 17
Author: Richard Fawcett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-08 13:00:03

Dzięki @ Richard za odpowiedź powyżej. Uruchamiam nową wersję stosu usług i usunęli ServiceStackHttpFactory z HttpFactory. Zamiast mieć

private readonly static ServiceStackHttpHandlerFactory factory = new ServiceStackHttpHandlerFactory();

Musisz mieć

private static readonly HttpHandlerFactory Factory = new HttpHandlerFactory();

Tutaj jest zaktualizowany kod dla tej usługi

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);
    }
}
}
 3
Author: craig_nelson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-15 17:28:35

Od ServiceStack 4.5+ HttpHandler może również obsługiwać Asynchronikę. Tak:

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);
    }
  }
}
 2
Author: Ries Vriend,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-13 12:25:14