Mengakses Sesi Menggunakan ASP.NET Web API

268

Saya menyadari sesi dan REST tidak berjalan beriringan, tetapi apakah tidak mungkin untuk mengakses status sesi menggunakan Web API baru? HttpContext.Current.Sessionselalu nol.

Menandai
sumber
4
[SessionState(SessionStateBehavior.Required)]pada ApiControllermelakukan trik (atau .ReadOnlyjika perlu).
Roman Starkov
@RomanStarkov Tidak dapat mengaktifkan ini. Lingkungan apa yang Anda gunakan? .NET Core?
Bondolin
@Bondolin tidak, ini bukan Core.
Roman Starkov
@RomanStarkov MVC? Saya mengalami kesulitan menemukannya.
Bondolin
@Bondolin SessionStateAttribute dan ya, MVC.
Roman Starkov

Jawaban:

336

MVC

Untuk proyek MVC, lakukan perubahan berikut (WebForms dan Dot Net Core menjawab di bawah):

WebApiConfig.cs

public static class WebApiConfig
{
    public static string UrlPrefix         { get { return "api"; } }
    public static string UrlPrefixRelative { get { return "~/api"; } }

    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: WebApiConfig.UrlPrefix + "/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

Global.asax.cs

public class MvcApplication : System.Web.HttpApplication
{
    ...

    protected void Application_PostAuthorizeRequest()
    {
        if (IsWebApiRequest())
        {
            HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
        }
    }

    private bool IsWebApiRequest()
    {
        return HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.StartsWith(WebApiConfig.UrlPrefixRelative);
    }

}

Solusi ini memiliki bonus tambahan yang dapat kami ambil dari URL dasar dalam javascript untuk melakukan panggilan AJAX:

_Layout.cshtml

<body>
    @RenderBody()

    <script type="text/javascript">
        var apiBaseUrl = '@Url.Content(ProjectNameSpace.WebApiConfig.UrlPrefixRelative)';
    </script>

    @RenderSection("scripts", required: false) 

dan kemudian dalam file / kode Javascript kami, kami dapat membuat panggilan webapi kami yang dapat mengakses sesi:

$.getJSON(apiBaseUrl + '/MyApi')
   .done(function (data) {
       alert('session data received: ' + data.whatever);
   })
);

WebForms

Lakukan hal di atas tetapi ubah fungsi WebApiConfig.Register untuk mengambil RouteCollection sebagai gantinya:

public static void Register(RouteCollection routes)
{
    routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: WebApiConfig.UrlPrefix + "/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}

Dan kemudian panggil yang berikut di Application_Start:

WebApiConfig.Register(RouteTable.Routes);

Dot Net Core

Tambahkan paket NuGet Microsoft.AspNetCore.Session dan kemudian buat perubahan kode berikut:

Startup.cs

Panggil metode AddDistributedMemoryCache dan AddSession pada objek layanan di dalam fungsi ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    ...

    services.AddDistributedMemoryCache();
    services.AddSession();

dan pada fungsi Konfigurasi tambahkan panggilan ke UseSession :

public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
ILoggerFactory loggerFactory)
{
    app.UseSession();
    app.UseMvc();

SessionController.cs

Di dalam controller Anda, tambahkan pernyataan menggunakan di atas:

using Microsoft.AspNetCore.Http;

dan kemudian gunakan objek HttpContext.Session dalam kode Anda seperti:

    [HttpGet("set/{data}")]
    public IActionResult setsession(string data)
    {
        HttpContext.Session.SetString("keyname", data);
        return Ok("session data set");
    }

    [HttpGet("get")]
    public IActionResult getsessiondata()
    {
        var sessionData = HttpContext.Session.GetString("keyname");
        return Ok(sessionData);
    }

Anda sekarang dapat menekan:

http://localhost:1234/api/session/set/thisissomedata

dan kemudian pergi ke URL ini akan menariknya:

http://localhost:1234/api/session/get

Banyak info lebih lanjut tentang mengakses data sesi dalam dot net core di sini: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/app-state

Masalah Kinerja

Baca jawaban Simon Weaver di bawah ini tentang kinerja. Jika Anda mengakses data sesi di dalam proyek WebApi itu bisa memiliki konsekuensi kinerja yang sangat serius - Saya telah melihat ASP.NET memberlakukan penundaan 200 ms untuk permintaan bersamaan. Ini bisa bertambah dan menjadi bencana jika Anda memiliki banyak permintaan bersamaan.


Perhatian pada keamanan

Pastikan Anda mengunci sumber daya per pengguna - pengguna yang diautentikasi seharusnya tidak dapat mengambil data dari WebApi Anda yang tidak dapat mereka akses.

Baca artikel Microsoft tentang Otentikasi dan Otorisasi di ASP.NET Web API - https://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api

Baca artikel Microsoft tentang menghindari serangan hack Pemalsuan Permintaan Situs Web. (Singkatnya, periksa metode AntiForgery.Validate) - https://www.asp.net/web-api/overview/security/preventing-cross-site-request-forgery-csrf-attacks

Rocklan
sumber
7
Sempurna. Sederhana dan berhasil. Untuk non-MVC, cukup tambahkan Application_PostAuthorizeRequest () ke Global.ascx.cs.
mhenry1384
1
Terima kasih @Jallico, saya kira kebanyakan orang menekan halaman ASP.NET terlebih dahulu yang membuat sesi.
Rocklan
3
Saya perlu memodifikasi IsWebApiRequest () untuk juga mengembalikan true di mana path dimulai dengan WebApiConfig.UrlPrefix, serta WebApiConfig.UrlPrefixRelative. Selain itu, berfungsi seperti yang diharapkan.
gb2d
7
Satu hal lagi tentang perbaikan ini. saat mengatur SessionStateBehavior ke Required, Anda menghambat webapi, karena semua permintaan Anda akan berjalan disinkronkan karena kunci pada objek sesi. Anda malah bisa menjalankannya sebagai SessionStateBehavior.Readonly. Dengan cara ini tidak akan membuat kunci pada objek sesi.
Michael Kire Hansen
2
Hati-hati saat mengatur perilaku status sesi ke "Diperlukan". Permintaan dengan izin menulis akan mengunci sesi dan mencegah beberapa aplikasi Http untuk muncul per klien. Anda harus mengatur status sesi ke level yang sesuai untuk setiap rute. Silakan lihat jawaban saya di sini: stackoverflow.com/a/34727708/1412787
Axel Wilczek
66

Anda dapat mengakses status sesi menggunakan RouteHandler khusus.

// In global.asax
public class MvcApp : System.Web.HttpApplication
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        var route = routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
        route.RouteHandler = new MyHttpControllerRouteHandler();
    }
}

// Create two new classes
public class MyHttpControllerHandler
    : HttpControllerHandler, IRequiresSessionState
{
    public MyHttpControllerHandler(RouteData routeData) : base(routeData)
    { }
}
public class MyHttpControllerRouteHandler : HttpControllerRouteHandler
{
    protected override IHttpHandler GetHttpHandler(
        RequestContext requestContext)
    {
        return new MyHttpControllerHandler(requestContext.RouteData);
    }
}

// Now Session is visible in your Web API
public class ValuesController : ApiController
{
    public string Get(string input)
    {
        var session = HttpContext.Current.Session;
        if (session != null)
        {
            if (session["Time"] == null)
                session["Time"] = DateTime.Now;
            return "Session Time: " + session["Time"] + input;
        }
        return "Session is not availabe" + input;
    }
}

Ditemukan di sini: http://techhasnoboundary.blogspot.com/2012/03/mvc-4-web-api-access-session.html

warrickh
sumber
14
Perbarui: jika fungsi API Anda membaca dari sesi, dan jangan memodifikasi sesi, mungkin ide yang baik untuk menggunakan IReadOnlySessionState alih-alih IRequiresSessionState. Ini memastikan sesi tidak dikunci selama pemrosesan fungsi API.
warrickh
6
tidak bekerja untuk saya di MVC 4 - route.RouteHandler bahkan bukan properti bagi saya. @LachlanB tampaknya memiliki apa yang berhasil untuk saya.
bkwdesign
3
Terima kasih @bkwdesign untuk menunjukkan solusi MVC. Jawaban ini hanya berkaitan dengan API Web.
warrickh
2
Ini sepertinya tidak mendukung Atribut Rute. Pikiran?
Tim S
Seperti yang ditunjukkan oleh bkwdesign, ini tidak lagi didukung. Namun, ada cara untuk mendefinisikan perilaku status sesi per rute menggunakan DataTokens: stackoverflow.com/a/34727708/1412787
Axel Wilczek
46

Mengapa menghindari menggunakan Sesi di WebAPI?

Kinerja, kinerja, kinerja!

Ada alasan yang sangat bagus, dan sering diabaikan mengapa Anda tidak harus menggunakan Sesi di WebAPI sama sekali.

Cara ASP.NET bekerja ketika Session sedang digunakan adalah untuk membuat cerita bersambung semua permintaan yang diterima dari satu klien . Sekarang saya tidak berbicara tentang serialisasi objek - tetapi menjalankannya dalam urutan yang diterima dan menunggu masing-masing untuk menyelesaikan sebelum menjalankan berikutnya. Ini untuk menghindari kondisi thread / ras yang tidak menyenangkan jika dua permintaan masing-masing mencoba mengakses Sesi secara bersamaan.

Permintaan Bersamaan dan Status Sesi

Akses ke status sesi ASP.NET bersifat eksklusif per sesi, yang berarti bahwa jika dua pengguna yang berbeda membuat permintaan secara bersamaan, akses ke setiap sesi terpisah diberikan secara bersamaan. Namun, jika dua permintaan bersamaan dibuat untuk sesi yang sama (dengan menggunakan nilai SessionID yang sama), permintaan pertama mendapat akses eksklusif ke informasi sesi. Permintaan kedua dieksekusi hanya setelah permintaan pertama selesai.(Sesi kedua juga bisa mendapatkan akses jika kunci eksklusif pada informasi dibebaskan karena permintaan pertama melebihi batas waktu kunci.) Jika nilai EnableSessionState di direktif @ Halaman diatur ke ReadOnly, permintaan untuk read-only informasi sesi tidak menghasilkan kunci eksklusif pada data sesi. Namun, permintaan baca-saja untuk data sesi mungkin masih harus menunggu kunci yang ditetapkan oleh permintaan baca-tulis untuk data sesi dihapus.

Jadi apa artinya ini untuk Web API? Jika Anda memiliki aplikasi yang menjalankan banyak permintaan AJAX maka hanya SATU yang akan dapat berjalan pada satu waktu. Jika Anda memiliki permintaan yang lebih lambat maka itu akan memblokir semua yang lain dari klien itu sampai selesai. Dalam beberapa aplikasi ini dapat menyebabkan kinerja yang sangat lambat.

Jadi Anda mungkin harus menggunakan pengontrol MVC jika Anda benar-benar membutuhkan sesuatu dari sesi pengguna dan menghindari hukuman kinerja yang tidak perlu untuk mengaktifkannya untuk WebApi.

Anda dapat dengan mudah menguji ini sendiri dengan hanya memasukkan Thread.Sleep(5000)metode WebAPI dan mengaktifkan Sesi. Jalankan 5 permintaan untuk itu dan mereka akan membutuhkan total 25 detik untuk menyelesaikannya. Tanpa Sesi mereka akan mengambil total lebih dari 5 detik.

(Alasan yang sama ini berlaku untuk SignalR).

Simon_Weaver
sumber
18
Anda dapat menyiasatinya dengan menggunakan [SessionState (SessionStateBehavior.ReadOnly)] jika metode Anda hanya membaca dari sesi.
Rocklan
21

Ya, Anda benar, REST tidak memiliki kewarganegaraan. Jika Anda menggunakan sesi, pemrosesan akan menjadi stateful, permintaan berikutnya akan dapat menggunakan state (dari sesi).

Agar sesi dapat direhidrasi, Anda harus menyediakan kunci untuk mengaitkan negara. Dalam aplikasi asp.net normal, kunci tersebut disediakan dengan menggunakan cookie (sesi cookie) atau parameter url (sesi tanpa masak).

Jika Anda membutuhkan sesi, lupakan istirahat, sesi tidak relevan dalam desain berbasis REST. Jika Anda memerlukan sesi untuk validasi, gunakan token atau otorisasi berdasarkan alamat IP.

Nickz
sumber
10
Saya tidak yakin tentang ini. Dalam contoh Microsoft, mereka ditampilkan menggunakan atribut Otorisasi. Saya sudah mencobanya dan berfungsi dengan Otentikasi Berbasis Formulir. API Web mengetahui status otentikasi yang diteruskan dalam cookie otentikasi default.
Markus
4
Berikut adalah contoh yang saya maksudkan, code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7 . Ini menggunakan API Web berbasis REST baru mengimplementasikan Formulir Otentikasi.
Markus
4
Saya berhasil menggunakan atribut [Otorisasi] tanpa perlu status sesi. Saya baru saja menulis penangan pesan otentikasi untuk mengatur identitas.
Antony Scott
57
Menandai Anda karena Anda tidak menawarkan jawaban untuk masalahnya, dan terlebih lagi, Web Api adalah kerangka kerja asinkron yang bekerja sangat baik dengan aplikasi web ajax berat. Tidak ada yang mengatakan Anda harus menghormati semua penyewa desain RESTful untuk mendapatkan manfaat dari menggunakan kerangka Web API.
Brian Ogden
3
@Tanda. berhak memberi tahu bahwa API Web tidak seharusnya mengetahui status sesi. Jawaban negatif masih tetap menjadi jawaban. Pemungutan suara.
Antoine Meltzheim
20

Mark, jika Anda memeriksa contoh MVC nerddinner logikanya hampir sama.

Anda hanya perlu mengambil cookie dan mengaturnya di sesi saat ini.

Global.asax.cs

public override void Init()
{
    this.AuthenticateRequest += new EventHandler(WebApiApplication_AuthenticateRequest);
    base.Init();
}

void WebApiApplication_AuthenticateRequest(object sender, EventArgs e)
{
    HttpCookie cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
    FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);

    SampleIdentity id = new SampleIdentity(ticket);
    GenericPrincipal prin = new GenericPrincipal(id, null); 

    HttpContext.Current.User = prin;
}

enter code here

Anda harus mendefinisikan kelas "SampleIdentity" Anda, yang dapat Anda pinjam dari proyek nerddinner .

JSancho
sumber
Kelas identitas ada di NerdDinner_2.0 \ NerdDinner \ Models \ NerdIdentity.cs.
mhenry1384
Ini tidak berfungsi untuk saya (dalam. NET 4). Saya tidak pernah memiliki kue itu. Apakah itu hanya berfungsi jika FormsAuthentication Anda dihidupkan?
mhenry1384
cookie memang dihasilkan setelah Anda mengotentikasi melalui formulir login. Anda juga dapat menyesuaikan bagaimana / kapan itu dibuat, lihat stackoverflow.com/questions/7217105 Tetapi Anda masih membutuhkan pengguna untuk mengotentikasi secara efektif terhadap server web
JSancho
Pertanyaannya menanyakan HttpContext.Current.Session dan jawaban ini tidak jelas menjelaskan apa yang perlu dilakukan. Lihat jawaban @LachlanB.
JCallico
14

Untuk memperbaiki masalah:

protected void Application_PostAuthorizeRequest()
{
    System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
}

di Global.asax.cs

Suresh Muttagi
sumber
4
Peringatan! Ini akan mengaktifkan sesi untuk SEMUA permintaan. Ini benar-benar dapat merusak kinerja jika aplikasi Anda menggunakan sumber daya yang disematkan.
cgatian
@cgatian ada solusi alternatif yang diperbaiki ?
Kiquenet
Saya pikir pendekatan terbaik adalah apa yang disarankan @Treyphor. Jangan aktifkan itu untuk semua permintaan. Hanya rute yang memiliki "/ api" atau sesuatu di URL. Juga, jika mungkin setel status sesi untuk hanya membaca untuk pengontrol API Anda.
cgatian
10

Yang terakhir tidak berfungsi sekarang, ambil yang ini, itu bekerja untuk saya.

di WebApiConfig.cs di App_Start

    public static string _WebApiExecutionPath = "api";

    public static void Register(HttpConfiguration config)
    {
        var basicRouteTemplate = string.Format("{0}/{1}", _WebApiExecutionPath, "{controller}");

        // Controller Only
        // To handle routes like `/api/VTRouting`
        config.Routes.MapHttpRoute(
            name: "ControllerOnly",
            routeTemplate: basicRouteTemplate//"{0}/{controller}"
        );

        // Controller with ID
        // To handle routes like `/api/VTRouting/1`
        config.Routes.MapHttpRoute(
            name: "ControllerAndId",
            routeTemplate: string.Format ("{0}/{1}", basicRouteTemplate, "{id}"),
            defaults: null,
            constraints: new { id = @"^\d+$" } // Only integers 
        );

Global.asax

protected void Application_PostAuthorizeRequest()
{
  if (IsWebApiRequest())
  {
    HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
  }
}

private static bool IsWebApiRequest()
{
  return HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.StartsWith(_WebApiExecutionPath);
}

keempat di sini: http://forums.asp.net/t/1773026.aspx/1

Cruiser KID
sumber
Ini adalah solusi paling sederhana tetapi memiliki beberapa kesalahan dalam kode sehingga tidak benar-benar berfungsi. Saya telah memposting solusi lain berdasarkan ini, jangan ragu untuk mengedit milik Anda untuk mencocokkan milik saya.
Rocklan
Koreksi sedikit pada baris _WebApiExecutionPath perlu membaca string statis publik _WebApiExecutionPath = "~ / api";
stephen ebichondo
8

Sebagai lanjutan dari jawaban LachlanB, jika ApiController Anda tidak berada dalam direktori tertentu (seperti / api), Anda bisa menguji permintaan menggunakan RouteTable.Routes.GetRouteData, misalnya:

protected void Application_PostAuthorizeRequest()
    {
        // WebApi SessionState
        var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(HttpContext.Current));
        if (routeData != null && routeData.RouteHandler is HttpControllerRouteHandler)
            HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
    }
Stumblor
sumber
8

Saya punya masalah yang sama di asp.net MVC, saya memperbaikinya dengan meletakkan metode ini di basis api controller saya bahwa semua pengendali api saya mewarisi dari:

    /// <summary>
    /// Get the session from HttpContext.Current, if that is null try to get it from the Request properties.
    /// </summary>
    /// <returns></returns>
    protected HttpContextWrapper GetHttpContextWrapper()
    {
      HttpContextWrapper httpContextWrapper = null;
      if (HttpContext.Current != null)
      {
        httpContextWrapper = new HttpContextWrapper(HttpContext.Current);
      }
      else if (Request.Properties.ContainsKey("MS_HttpContext"))
      {
        httpContextWrapper = (HttpContextWrapper)Request.Properties["MS_HttpContext"];
      }
      return httpContextWrapper;
    }

Kemudian dalam panggilan api Anda bahwa Anda ingin mengakses sesi yang baru saja Anda lakukan:

HttpContextWrapper httpContextWrapper = GetHttpContextWrapper();
var someVariableFromSession = httpContextWrapper.Session["SomeSessionValue"];

Saya juga punya ini di file Global.asax.cs saya seperti orang lain telah diposting, tidak yakin apakah Anda masih membutuhkannya menggunakan metode di atas, tetapi ini dia hanya dalam kasus:

/// <summary>
/// The following method makes Session available.
/// </summary>
protected void Application_PostAuthorizeRequest()
{
  if (HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.StartsWith("~/api"))
  {
    HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
  }
}

Anda juga bisa membuat atribut filter khusus yang dapat Anda tempel di panggilan api yang Anda butuhkan sesi, kemudian Anda bisa menggunakan sesi dalam panggilan api Anda seperti yang biasa Anda lakukan melalui HttpContext.Current.Session ["SomeValue"]:

  /// <summary>
  /// Filter that gets session context from request if HttpContext.Current is null.
  /// </summary>
  public class RequireSessionAttribute : ActionFilterAttribute
  {
    /// <summary>
    /// Runs before action
    /// </summary>
    /// <param name="actionContext"></param>
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
      if (HttpContext.Current == null)
      {
        if (actionContext.Request.Properties.ContainsKey("MS_HttpContext"))
        {
          HttpContext.Current = ((HttpContextWrapper)actionContext.Request.Properties["MS_HttpContext"]).ApplicationInstance.Context;
        }
      }
    }
  }

Semoga ini membantu.

Treyphor
sumber
6

Saya mengikuti pendekatan @LachlanB dan memang sesi itu tersedia ketika cookie sesi hadir atas permintaan. Bagian yang hilang adalah bagaimana cookie Sesi dikirim ke klien pertama kali?

Saya membuat HttpModule yang tidak hanya mengaktifkan ketersediaan HttpSessionState tetapi juga mengirimkan cookie ke klien ketika sesi baru dibuat.

public class WebApiSessionModule : IHttpModule
{
    private static readonly string SessionStateCookieName = "ASP.NET_SessionId";

    public void Init(HttpApplication context)
    {
        context.PostAuthorizeRequest += this.OnPostAuthorizeRequest;
        context.PostRequestHandlerExecute += this.PostRequestHandlerExecute;
    }

    public void Dispose()
    {
    }

    protected virtual void OnPostAuthorizeRequest(object sender, EventArgs e)
    {
        HttpContext context = HttpContext.Current;

        if (this.IsWebApiRequest(context))
        {
            context.SetSessionStateBehavior(SessionStateBehavior.Required);
        }
    }

    protected virtual void PostRequestHandlerExecute(object sender, EventArgs e)
    {
        HttpContext context = HttpContext.Current;

        if (this.IsWebApiRequest(context))
        {
            this.AddSessionCookieToResponseIfNeeded(context);
        }
    }

    protected virtual void AddSessionCookieToResponseIfNeeded(HttpContext context)
    {
        HttpSessionState session = context.Session;

        if (session == null)
        {
            // session not available
            return;
        }

        if (!session.IsNewSession)
        {
            // it's safe to assume that the cookie was
            // received as part of the request so there is
            // no need to set it
            return;
        }

        string cookieName = GetSessionCookieName();
        HttpCookie cookie = context.Response.Cookies[cookieName];
        if (cookie == null || cookie.Value != session.SessionID)
        {
            context.Response.Cookies.Remove(cookieName);
            context.Response.Cookies.Add(new HttpCookie(cookieName, session.SessionID));
        }
    }

    protected virtual string GetSessionCookieName()
    {
        var sessionStateSection = (SessionStateSection)ConfigurationManager.GetSection("system.web/sessionState");

        return sessionStateSection != null && !string.IsNullOrWhiteSpace(sessionStateSection.CookieName) ? sessionStateSection.CookieName : SessionStateCookieName;
    }

    protected virtual bool IsWebApiRequest(HttpContext context)
    {
        string requestPath = context.Request.AppRelativeCurrentExecutionFilePath;

        if (requestPath == null)
        {
            return false;
        }

        return requestPath.StartsWith(WebApiConfig.UrlPrefixRelative, StringComparison.InvariantCultureIgnoreCase);
    }
}
JCallico
sumber
Ini sangat bagus. Ini menjaga sesi tetap sama antara permintaan selama belum habis waktu. Tidak yakin apakah saya akan menggunakannya dalam prod sampai saya menemukan cara yang baik untuk mengubah status sesi antara yang diperlukan dan hanya membaca untuk menghentikan pemblokiran permintaan, tetapi ini telah memberi saya jalan awal yang saya inginkan. Terima kasih!
Derreck Dean
3

satu hal yang perlu disebutkan pada jawaban @LachlanB.

protected void Application_PostAuthorizeRequest()
    {
        if (IsWebApiRequest())
        {
            HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
        }
    }

Jika Anda menghilangkan garis if (IsWebApiRequest())

Seluruh situs akan memiliki masalah kelambatan pemuatan halaman jika situs Anda dicampur dengan halaman formulir web.

maxisam
sumber
0

Ya, sesi tidak berjalan seiring dengan API Istirahat dan juga kita harus menghindari praktik ini. Tetapi sesuai persyaratan kita perlu mempertahankan sesi entah bagaimana sehingga dalam setiap permintaan, klien dapat bertukar atau mempertahankan status atau data. Jadi, cara terbaik untuk mencapai ini tanpa melanggar protokol REST adalah berkomunikasi melalui token seperti JWT.

https://jwt.io/

Sulabh Singla
sumber
-4

Kembali ke dasar mengapa tidak membuatnya sederhana dan menyimpan nilai Sesi dalam nilai html tersembunyi untuk diteruskan ke API Anda?

Pengendali

public ActionResult Index()
        {

            Session["Blah"] = 609;

            YourObject yourObject = new YourObject();
            yourObject.SessionValue = int.Parse(Session["Blah"].ToString());

            return View(yourObject);
        }

cshtml

@model YourObject

@{
    var sessionValue = Model.SessionValue;
}

<input type="hidden" value="@sessionValue" id="hBlah" />

Javascript

$ (dokumen) .ready (function () {

    var sessionValue = $('#hBlah').val();

    alert(sessionValue);

    /* Now call your API with the session variable */}

}

Andy A.
sumber
1
Apakah aplikasi tersebut menggunakan MVC dan WebAPI? Juga, beberapa hal lebih masuk akal untuk disimpan di sisi server, misalnya token keamanan Sharepoint. Alih-alih menerapkan pembungkus khusus untuk penyimpanan token seperti wadah gumpalan biru, kadang-kadang wajar menggunakan kembali Sesi untuk jenis data ini. Konteks keamanan Sharepoint seperti yang diterapkan dalam templat aplikasi, menggunakan sesi untuk menyimpan konteks keamanan ini, dan hanya sebagian kecil data yang ditransfer (tag sesi) alih-alih beberapa kilobyte data. Akan luar biasa jika konteks ini akan lebih kecil ...
Konstantin Isaev