如何使用 blazor 创建 cookie 客户端

Posted

技术标签:

【中文标题】如何使用 blazor 创建 cookie 客户端【英文标题】:How do I create a cookie client side using blazor 【发布时间】:2019-05-30 04:21:32 【问题描述】:

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

所以首先我已经成功注入了 IHttpContextAccessor。现在在我的 Blazor 函数中,我有:

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

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

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

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

【问题讨论】:

另一种方法是通过this Blazor library 使用LocalStorage。 IMO,它是 Blazor 应用程序的更合适的客户端存储工具,因为每次请求都会发送 cookie,而本地存储是 Blazor 应用程序可用的数据,可以根据需要使用。 我们尽可能使用本地存储,但是对于这一点,我们与之交互的另一个软件会查找存储在 Cookie 中的信息。这个应用程序需要代表次要软件创建它,直到我们能够改变它。 【参考方案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 ([Discussion] Microsoft.Interop.JSRuntime.Current has been removed) 开始,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=/";


【讨论】:

我知道现在还为时过早,但我祈祷每次我想做这样的小事情时不必总是使用 JS 互操作,这应该是一个开箱即用的功能。不过谢谢,这很有帮助! 我同意,最终这将由社区包提供。见这里:github.com/BlazorExtensions【参考方案2】:

如果你想避免外部脚本依赖

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

保留正确转义 cookie 值。

【讨论】:

【参考方案3】:

您可以在&lt;script&gt; 标签中添加@Flores in_Host.cshtml 解释的javascript

<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>

【讨论】:

【参考方案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(1, val.IndexOf('=') - 1).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");
    

您可以通过ExpireDays 设置默认过期时间,并在SetValue() 中将null 设置为days 以使用默认值或设置为0 用于会话或天数。 然后导入_import.razor并添加到Program.cs中的服务:

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

使用:

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

尽情享受吧。

【讨论】:

if(val.Substring(1, val.IndexOf('=') - 1).Trim().Equals(key, StringComparison.OrdinalIgnoreCase)) 应该是(val.Substring(0, val.IndexOf('=')).Trim().Equals(key, StringComparison.OrdinalIgnoreCase)) 我认为

以上是关于如何使用 blazor 创建 cookie 客户端的主要内容,如果未能解决你的问题,请参考以下文章

如何从服务器端 Blazor 应用程序中的 Blazor 组件调用 razor 页面而不导致页面刷新

如何在 Blazor 服务器中设置同意 cookie

如何使用 Blazor 框架在前端浏览器中导入和导出 Excel

使用 Cookie 进行 Blazor 服务器端身份验证

简单服务器端Blazor Cookie身份验证的演示

Blazor WebAssembly Server 项目如何引用客户端索引?