0

I have a login page that allows the user to login. In the HandlieValidSubmit() event I check if username and password matches with the value stored in database.

If everything is fine I want to store some data into the usercookie before redirecting to another site. This is the html/blazor-Code:

<EditForm>
<!-- standard form-controls here -->
</EditForm>
@code {
    private Models.LoginUser _loginUser = new Models.LoginUser();
    private EditContext _editContext;

    private void HandleValidSubmit()
    {
        if (UserApi.Login(_loginUser.Mail, _loginUser.Password, out string error, out Guid? guid))
        {
            NaviationManager.NavigateTo($"/manage/{guid}");
        }
    }
}

the Cookie is set from within the Login-Function and looks like this:

   public  DateTime SetCookie<T>(T data, TimeSpan expiration, bool httpOnly = true, bool secure = true)
        {
            DateTime expireDate = DateTime.Now.Add(expiration);
            if (data == null) return DateTime.Now;
            Type dataType = typeof(T);
            var response = _httpContextAccessor.HttpContext.Response;
            CookieOptions cookieOptions = new CookieOptions
            {
                HttpOnly = httpOnly,
                Secure = secure,
                Expires = expireDate
            };

            foreach (var property in dataType.GetProperties())
            {
                var storeInCookieAttribute = property.GetCustomAttribute<StoreInCookieAttribute>();
                if (storeInCookieAttribute == null) continue;
                response.Cookies.Append(BuildCookieKey(dataType.Name, property.Name), property.GetValue(data) as string, cookieOptions);
            }

            return expireDate;
        }

IMHO this is the standard "how-to-write-cookies-in-netcore" - way.

When I try to write the cookie I receive the error:

"The response headers cannot be modified because the response has already started."

I understand what this error wants to tell me. Alas I do not really know how to prevent this. I expected that at this point the response should not have started at all.

Is there another event than HandleValidSubmit() I need to use instead? Or can I just clear the Response before writing the cookie without bad side effects?

Ole Albers
  • 8,715
  • 10
  • 73
  • 166

1 Answers1

2

Blazor Server App is websocket-based application, not HTTP-based one, so the HttpContext service is not available.

When you create a Blazor Server App with support for IdentityUI, you get in the default template a component ( AuthorizeView ) that enables login and logout. When you click on the "Login" button, you are being redirected to a Login page where you can enter your credentials. The Login page is actually a Razor Page, not part of the Blazor App, meaning that you are no longer in the realm of Blazor, and here in this new realm (The Razor Page), the HttpContext is available, you don't even have to use the HttpContextAccessor, as the HttpContext is provided as a property in the PageModel object. After the user has been logged in, cookies created, etc., he is redirected to Blazor.

This is how you can do it. Just emulate this procedure... Create a Razor Page, where you can do all that stuff. You may also pass a return url, so that you'll be redirected to a specific Component page instead of the the Index Component Page.

Note: HandleValidSubmit() is a method that is called if your forms component elements have passed validation. It has got nothing to do with the issue in question.

Note: To use the NavigationManger.NavigateTo method to navigate to external location (outside of the Blazor App realm), add a second boolean parameter with the value true.

Note: This may help you how to cope . There are also many answers related to the current subject and authentication with OpenID Connect, Okta, IdentityUI, etc. Just look for them if you are in need.

Note: Are you aware that you can store data in the local storage and session storage ?

Hope this helps...

enet
  • 41,195
  • 5
  • 76
  • 113