obind
obind

Reputation: 185

How to get data from an Object from another Class in Blazor?

Hello I'm working on a Blazor Project. I hope someone knows a Solution

I have a class called User:

public class User
{
public string email { get; set; }
public string password { get; set; }
public string mobilenumber { get; set; }
public string service { get; set; }
   public override string ToString()
   {
       return $"{email}: {password}: {mobilenumber}: {service}";
   }
}

And two Razor Components(Login.razor, SecondMain.razor)

In the Login Component a new object user is created

public User user = new User;

and is filled with data

user.email = [email protected];
user.password = password;

After a sucessfull Login the User is navigatet to SecondMain.razor

NavigationManager.NavigateTo("SecondMain");

Now im trying to get this data in my secondMain.razor component. I tryed something like this

Login login = new Login;    
string output = login.user.email;

The problem is that my output is null.

Upvotes: 0

Views: 1002

Answers (1)

Marvin Klein
Marvin Klein

Reputation: 1746

There are several ways of passing data around within a blazor app.

Component Parameters.

Every public Parameter which has the property [Parameter] assigned can get a value from outside. For example:

TestComponent.razor:

<p>@Title</p>
@code {
[Parameter] public string Title { get; set; }
}

Using a service

You can define properties within a service and update these propteries from different pages.

Using SessionStorage

This one requires a third party libary. I suggest this one: https://github.com/Blazored/SessionStorage it's simply to install and easy to use.

Which one fits in your case?

Neither of those. I think you are trying to achive a user login for your blazor app. Each of this approaches does not work in your case. But why?

  1. Parameters shall be used by components itself.
  2. The data in the service will be lost when the user refreshes the page (except when using singleton but then the same object is shared between all users)
  3. The SessionStorage can only be called after your website has been rendered (Not sure about Blazor WASM).

Instead you should use either ASP.NET Core Identity authentication, or a ClaimsBased authentication.

For example: You create a Login.cshtml page within Pages/Account/

In your code behind file:

public async Task<IActionResult> OnPostAsync(string? returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");

    if (ModelState.IsValid)
    {

        // Check your user here

        // If you found it define some claims:
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, Input.Username),
        };

        
        var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);

        var authProperties = new AuthenticationProperties
        {
            IsPersistent = Input.RememberMe,
            RedirectUri = returnUrl
        };

        await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties);


        return LocalRedirect(returnUrl);       
    }
    return Page();
}

In Program.cs

builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>{});

builder.Services.AddAuthorization(options =>{});


app.UseAuthentication();
app.UseAuthorization();

Within your _Host.cshtml file you then can check your HttpContext and recreate the object which can be cascaded to your pages. For example:

@{
    User? user = null;

    if (HttpContext.User.Identity is not null && HttpContext.User.Identity.Name is not null)
    {
        var guidClaim = HttpContext.User.Claims.FirstOrDefault(x => x.Type == "guid");
        if (guidClaim is not null)
        {
            Guid guid = new Guid(guidClaim.Value);
            user = Program.AppDaten.Users.FirstOrDefault(x => x.Guid == guid);

            
        }
    }
}

This object can the be passed down to your app:

<component type="typeof(App)" param-User="user" render-mode="Server" />

Within App.razor:

Wrap your Router within

<CascadingAuthenticationState>
    <CascadingValue Value="User">
    </CascadingValue>
</CascadingAuthenticationState>

Define the parameter:

@code {
    [Parameter] public User? User { get; set; }
}

Now you can get this object within every page/component by creating a cascaded property like this:

[CascadingParameter] public User User { get; set; }

Upvotes: 2

Related Questions