Search code examples
c#asp.net-coreasp.net-core-identity

Asp.Net Core class not passing data


In asp.net core 2.1 Identity I am using a class to move the login name from ExternalLogin.cshtml.cs and Login.cshtml to save them to another table via a class AddUserToStudentTable.

EDIT - I have got the terminology of DTO wrong, but consider it just a class that pushes data around. I just used the wrong naming convention.

The class is

public class StudentNameDTO : IStudentNameDTO
{
    public string StudentGoogleNameLogin { get; set; } = string.Empty;
    public bool IsExternal { get; set; } = false;
}

The Startup is using AddSingleton but I have also tried AddTransient, with no difference.

services.AddSingleton<IStudentNameDTO, StudentNameDTO>();

And I am using the usual Constructor injection automatically done with wonderful VS 2017

Yet when passing data I always get an error of

evaluation of method () calls into native method system System.Environment.FailFast().

and it all crashes down with

NullReferenceException: Object reference not set to an instance of an object. ASPNZBat.Business.AddUserToStudentTable.AddUserToStudent(string Email) in AddUserToStudentTable.cs + if (_studentNameDTO.IsExternal == true) ASPNZBat.Areas.Identity.Pages.Account.ExternalLoginModel.OnGetCallbackAsync(string returnUrl, string remoteError) in ExternalLogin.cshtml.cs + _addUserToStudentTable.AddUserToStudent(Email);

I have tried using AddTransient and AddScope as well in the startup, but no difference. Having worked on it for hours I am starting to doubt my ability to program....

Note that when there is data passing through it works OK. But when there is no data - null - instead of working with it it just crashes. I even wrapped it in a boolean to see if I could catch the output with that but it crashed at the boolean as well.

Data going in

if (info.Principal.Identity.Name != null)
{
    _studentNameDTO.IsExternal = true;
    _studentNameDTO.StudentGoogleNameLogin = info.Principal.Identity.Name;

    string Email = info.Principal.FindFirstValue(ClaimTypes.Email);

    _addUserToStudentTable.AddUserToStudent(Email);
}

Data coming out

string StudentName = string.Empty;
if (_studentNameDTO.IsExternal == true)
{
    StudentName = _studentNameDTO.StudentGoogleNameLogin;
}

There is something about passing null data that it doesn't like and I don't understand.

Here is the github acc for it https://github.com/Netchicken/ASPNZBatV2/tree/master/ASPNZBat


Solution

  • It looks like you've got a case of Over-Dependency Injection.

    Aside: You almost certainly don't want to be using AddSingleton here, a singleton is something that you want your application to have no more than one instance of during its execution. In this instance that would mean that if you had two users logging (or whatever the process is here) in at the same time they would both share the same instance of StudentNameDTO.

    Based on the code in AddUserToStudentTable.cs the reason you're seeing a NullReferenceException is that there's nothing here that assigns to _studentNameDTO prior to it being used. It's not being injected anywhere, nor is it being passed into the class anywhere, it's declared private so isn't accessible from outside the class and is only read from on lines 36 and 38.

    That said, not everything in your code needs, or should, be instantiated via Dependency Injection. Your StudentNameDTO isn't something the class depends on, it's something it consumes / modifies. From a cursory look at your code, it looks like the place that obtains all the data that's stored into StudentNameDTO is in ExternalLoginModel.OnGetCallbackAsync so this is where you should var studentNameDto = new StudentNameDTO() before calling AddUserToStudent and passing the instance of StudentNameDTO into the method, e.g. (line 97 onwards):

    if (info.Principal.Identity.Name != null)
    {
        var studentNameDto = new StudentNameDTO
        {
            IsExternal = true,
            _studentNameDTO.StudentGoogleNameLogin = info.Principal.Identity.Name
        };
    
        string Email = info.Principal.FindFirstValue(ClaimTypes.Email);
    
        _addUserToStudentTable.AddUserToStudent(studentNameDto, Email);
    }