How do I create a cookie client side using blazor

You can use this way without any script:
First define this service:

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

You can set default expire by ExpireDays, and in SetValue() set null to days for use default or set to 0 for session or number of days.
Then import to _import.razor and add to service in Program.cs:

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

For use:

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

Enjoy it.


You can add javaScript explained by @Flores in_Host.cshtml inside <script> tag.

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

You will have to use JS interop:

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

Starting with ASP.NET Core 3.0.0-preview3 ([Discussion] Microsoft.Interop.JSRuntime.Current has been removed), the Current property is not available, so use the following code:

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

Don't forget to inject IJSRuntime at the top:

@inject IJSRuntime JSRuntime

And this 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=/";
}
}

If you want to avoid the external script dependency

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

Remains to properly escape the cookie value.

Tags:

C#

Blazor