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
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 ofStudentNameDTO
.
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);
}