问题描述
在Blazor服务器端创建和读取Cookie的最简单方法是什么。
似乎所有的解决方案都适用于Blazor Web组装,并且每当我使用那些Response.Cookies.Append(“”)和Request.Cookies []选项时,这些解决方案都将不起作用。
解决方法
执行HTTP Post / Get,以便您实际上可以修改响应cookie。回调通常是通过WebSocket调用的,因此已经发送了响应(包括cookie),因此您无法进行修改。
,我找到了使用本地存储解决Blazor服务器端Cookie问题的好方法。
首先,使用以下命令获取NuGet Blazored LocalStorage:Install-Package Blazored.LocalStorage。我必须更新我的System.Text.Json,可从https://www.nuget.org/packages/System.Text.Json/
将以下内容添加到Startup.cs中:
public void ConfigureServices(IServiceCollection services)
{
services.AddBlazoredLocalStorage(); // local storage
services.AddBlazoredLocalStorage(config =>
config.JsonSerializerOptions.WriteIndented = true); // local storage
}
在您的Razor页面上(我使用Index.razor进行测试):
@page "/"
@inject Blazored.LocalStorage.ILocalStorageService localStorage
<button @onclick="HandleSubmit">Create Cookie</button> @* Create your cookie *@
@code{
public async Task HandleSubmit()
{
await localStorage.SetItemAsync("cookieName","Jason Bourne");
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
var cookieContent = await localStorage.GetItemAsync<string>("cookieName");
if (cookieContent == null)
{
Console.WriteLine("Cookie is blank");
}
else
{
Console.WriteLine("We have a cookie with contents: " + cookieContent);
}
}
}
,
在wwwroot/index.html
(Blazor WebAssembly)或Pages/_Host.cshtml
(Blazor Server)中,编写以下javascript代码:
<script>
window.WriteCookie = {
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=/";
}
}
window.ReadCookie = {
ReadCookie: function (cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length,c.length);
}
}
return "";
}
}
</script>
然后,将以下示例代码写入Razor组件(.razor):
@inject IJSRuntime JsRuntime;
<button class="btn" @onclick="WriteCookies">
Write Cookie
</button>
<button class="btn" @onclick="ReadCookies">
Read Cookie
</button>
<p>The cookie is @myCookieValue</p>
@code {
public string myCookieValue { get; set; } = "";
protected async Task WriteCookies()
{
await JsRuntime.InvokeAsync<object>("WriteCookie.WriteCookie","cookieName","cookieValue",DateTime.Now.AddMinutes(1));
}
protected async Task ReadCookies()
{
myCookieValue= await JsRuntime.InvokeAsync<string>("ReadCookie.ReadCookie","cookieName");
}
}
,
我尝试了基于 Blazored.LocalStorage 的方法以及此处提供的实验包
而且,我必须说它们非常相似,但它们有一个不方便之处:LocalStorage 变量只能从 OnAfterRenderAsync 或 OnInitializedAsync 中读取(InvalidOperationException:此时无法发出 JavaScript 互操作调用。等等...)。
就我而言,我需要从 OnParametersSetAsync 访问 LocalStorage,所以我使用了一个像这样的简单控制器:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
namespace MyNamespace.Controllers
{
[Route("[controller]/[action]")]
public class CookieController : Controller
{
private readonly IHttpContextAccessor _httpContextAccessor;
public CookieController(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
[HttpGet]
public IActionResult Write(string key,string value,string redirectUri)
{
CookieOptions options = new CookieOptions
{
Expires = DateTime.Now.AddDays(30)
};
_httpContextAccessor.HttpContext.Response.Cookies.Append(key,options);
return LocalRedirect(redirectUri);
}
}
}
在 Startup.cs 中,我添加了 services.AddSingleton<IHttpContextAccessor,HttpContextAccessor>();
并且,在组件内部:
@inject IHttpContextAccessor HttpContextAccessor
@code
{
private string cookieContent;
protected override async Task OnParametersSetAsync()
{
...
cookieContent= HttpContextAccessor.HttpContext.Request.Cookies["myCookie"];
}
}