如何使用 blazor 创建 cookie 客户端How do I create a cookie client side using blazor

How do I create a cookie client side using blazor

提问人:bilpor 提问时间:1/3/2019 最后编辑:Vibeeshan Mahadevabilpor 更新时间:10/1/2022 访问量:31457

问:

我有一个登录页面,该页面转到服务器获取一堆数据,然后我想获取其中一些数据并在客户端上使用 Blazor 将其保存到 cookie 中。

因此,首先,我已经成功注入了 IHttpContextAccessor。目前,在我的 Blazor 函数中,我有:

httpContextAccessor.HttpContext.Response.Cookies.Append("test", "ddd");

在调试中,当我点击上面的代码行时,它会出现以下错误:

“标头是只读的,响应已经开始。”

当然,我不会在 cookie 中保存带有“ddd”的“test”,我只是想让一个 cookie 保存。

C# Blazor

评论

1赞 Kirk Woll 1/4/2019
另一种方法是通过此 Blazor 库使用。IMO,它是更适合 Blazor 应用的客户端存储工具,因为 Cookie 会在每个请求时发送,而本地存储是 Blazor 应用可用的数据,可以根据需要使用。LocalStorage
2赞 bilpor 1/4/2019
我们正在尽可能使用本地存储,但对于这一点,我们与之交互的另一个软件会查找存储在 Cookie 中的信息。这个应用程序需要代表辅助软件创建它,直到我们能够改变它。

答:

21赞 Flores 1/3/2019 #1

您必须使用 JS 互操作:

        public async static Task WriteCookieAsync(string name, string value, int days)
        {
           var test = await JSRuntime.Current.InvokeAsync<object>("blazorExtensions.WriteCookie", name, value, days);
        }

从 ASP.NET Core 3.0.0-preview3([讨论] Microsoft.Interop.JSRuntime.Current 已删除)开始,Current 属性不可用,因此请使用以下代码:

var test = await JSRuntime.InvokeAsync<string>("blazorExtensions.WriteCookie", name, value, days);

不要忘记在顶部注入 IJSRuntime:

@inject IJSRuntime JSRuntime

而这个JS:

window.blazorExtensions = {

WriteCookie: function (name, value, days) {

    var expires;
    if (days) {
        var date = new Date();
        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
        expires = "; expires=" + date.toGMTString();
    }
    else {
        expires = "";
    }
    document.cookie = name + "=" + value + expires + "; path=/";
}
}

评论

15赞 Diogo Neves 1/4/2019
我知道现在还为时过早,但我祈祷每次我想做这样的小事时都不必总是使用 JS 互操作,这应该是一个开箱即用的功能。但是谢谢,这很有帮助!
1赞 Flores 1/8/2019
我同意,最终这将由社区包提供。请参阅此处:github.com/BlazorExtensions
2赞 TheKingPinMirza 6/27/2020 #2

您可以通过@Flores in_内部标签添加解释。javaScriptHost.cshtml<script>

<script>
window.blazorExtensions = {

    WriteCookie: function (name, value, days) {

        var expires;
        if (days) {
            var date = new Date();
            date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
            expires = "; expires=" + date.toGMTString();
        }
        else {
            expires = "";
        }
        document.cookie = name + "=" + value + expires + "; path=/";
    }
}
</script>
5赞 Etienne Charland 10/15/2020 #3

如果要避免外部脚本依赖

await jsRuntime.InvokeVoidAsync("eval", $"document.cookie = \"{cookieValue}\"")

剩余以正确转义 cookie 值。

评论

0赞 Fabio Pagano 6/2/2023
完美而简洁的解决方案,谢谢。您是否有“Remains to properly escape the cookie value.”的示例?谢谢。
18赞 MohsenB 11/7/2021 #4

您可以在没有任何脚本的情况下使用这种方式: 首先定义此服务:

using Microsoft.JSInterop;

namespace MyProject.Utils
{
    public interface ICookie
    {
        public Task SetValue(string key, string value, int? days = null);
        public Task<string> GetValue(string key, string def = "");
    }

    public class Cookie : ICookie
    {
        readonly IJSRuntime JSRuntime;
        string expires = "";

        public Cookie(IJSRuntime jsRuntime)
        {
            JSRuntime = jsRuntime;
            ExpireDays = 300;
        }

        public async Task SetValue(string key, string value, int? days = null)
        {
            var curExp = (days != null) ? (days > 0 ? DateToUTC(days.Value) : "") : expires;
            await SetCookie($"{key}={value}; expires={curExp}; path=/");
        }

        public async Task<string> GetValue(string key, string def = "")
        {
            var cValue = await GetCookie();
            if (string.IsNullOrEmpty(cValue)) return def;                

            var vals = cValue.Split(';');
            foreach (var val in vals)
                if(!string.IsNullOrEmpty(val) && val.IndexOf('=') > 0)
                    if(val.Substring(0, val.IndexOf('=')).Trim().Equals(key, StringComparison.OrdinalIgnoreCase))
                        return val.Substring(val.IndexOf('=') + 1);
            return def;
        }

        private async Task SetCookie(string value)
        {
            await JSRuntime.InvokeVoidAsync("eval", $"document.cookie = \"{value}\"");
        }

        private async Task<string> GetCookie()
        {
            return await JSRuntime.InvokeAsync<string>("eval", $"document.cookie");
        }

        public int ExpireDays
        {
            set => expires = DateToUTC(value);
        }

        private static string DateToUTC(int days) => DateTime.Now.AddDays(days).ToUniversalTime().ToString("R");
    }
}

您可以将默认过期设置为 ,并将 设置为 for use default,或者设置为 for session 或 number of days。
然后导入到服务并添加到服务中:
ExpireDaysSetValue()nulldays0_import.razorProgram.cs

builder.Services.AddScoped<ICookie, Cookie>();

适用范围:

@inject ICookie cookie  
...  
await cookie.SetValue("mytest20", "Hello Mohsen!");
_message = await cookie.GetValue("mytest20");

好好享受吧。

由 @jaap 评论更新。

评论

5赞 Jaap 11/26/2021
if(val.Substring(1, val.IndexOf('=') - 1).Trim().Equals(key, StringComparison.OrdinalIgnoreCase))应该是我认为(val.Substring(0, val.IndexOf('=')).Trim().Equals(key, StringComparison.OrdinalIgnoreCase))
0赞 Syed Rafay 9/8/2022
任何使用此服务的人,请查看@Jaap的评论。
0赞 devlife 7/19/2023
或范围运算符:if (val[..val.IndexOf('=')].Trim().Equals(key, StringComparison.OrdinalIgnoreCase)) { return val[(val.IndexOf('=') + 1)..]; }
2赞 Michika Iranga Perera 4/11/2022 #5

借助 MohsenB 提供的代码片段。我为它创建了一个 NuGet 包。

NuGet 安装:

Install-Package AltairCA.Blazor.WebAssembly.Cookie

程序.cs

builder.Services.AddAltairCACookieService(options =>
{
   options.DefaultExpire = TimeSpan.FromMinutes(15);
});

使用示例

注入服务

@inject IAltairCABlazorCookieUtil _cookieUtil;

示例 1

await _cookieUtil.SetValueAsync("cookieName", "value");