public virtual async Task <ActionResult> Post(RedeemEmailVerification command, string emailAddress) { //System.Threading.Thread.Sleep(new Random().Next(5000, 5001)); if (command == null || string.IsNullOrWhiteSpace(emailAddress)) { return(View(MVC.Errors.Views.BadRequest)); } if (!ModelState.IsValid) { var firstError = ModelState.Values.SelectMany(x => x.Errors.Select(y => y.ErrorMessage)).First(); var message = string.Format("Could not confirm email address: **{0}**", firstError); TempData.Alerts(message, AlertFlavor.Danger, true); ViewBag.EmailAddress = emailAddress; ViewBag.Ticket = command.Ticket; ViewBag.Token = command.Token; return(View(MVC.Security.Views.User.AddEmailConfirm, command)); } await _commands.Execute(command); Session.VerifyEmailTickets(null); return(this.RedirectToLocal(await MVC.UserEmails.Index())); }
public virtual async Task <ActionResult> Post(CreateLocalMembership command, string returnUrl, string emailAddress) { //System.Threading.Thread.Sleep(new Random().Next(5000, 5001)); if (command == null || string.IsNullOrWhiteSpace(emailAddress)) { return(View(MVC.Errors.Views.BadRequest)); } if (!ModelState.IsValid) { ViewBag.EmailAddress = emailAddress; ViewBag.Ticket = command.Ticket; ViewBag.Token = command.Token; ViewBag.ReturnUrl = returnUrl; return(View(MVC.Security.Views.SignUp.CreateUser, command)); } await _commands.Execute(command); var signIn = new SignIn { UserNameOrVerifiedEmail = command.UserName, Password = command.Password }; await _commands.Execute(signIn); Session.VerifyEmailTickets(null); Response.ClientCookie(signIn.SignedIn.Id, _queries); return(this.RedirectToLocal(returnUrl, await MVC.UserName.Index())); }
public virtual async Task <ActionResult> LinkLoginCallback(string provider, string returnUrl) { string alert = null; var loginInfo = await _queries.Execute(new PrincipalRemoteMembershipTicket(User)); if (loginInfo == null) { alert = string.Format("There was an error adding your **{0}** login, please try again.", provider); } var command = new CreateRemoteMembership { Principal = User }; var validationResult = _validation.Validate(command); if (!validationResult.IsValid) { alert = string.Format("There was an error adding your **{0}** login: {1}", provider, validationResult.Errors .First(x => !string.IsNullOrWhiteSpace(x.ErrorMessage)).ErrorMessage); } if (!string.IsNullOrWhiteSpace(alert)) { TempData.Alerts(alert, AlertFlavor.Danger, true); return(RedirectToAction(await MVC.UserLogins.Index())); } await _commands.Execute(command); alert = string.Format("Your **{0}** login was added successfully.", provider); TempData.Alerts(alert, AlertFlavor.Success, true); return(RedirectToAction(await MVC.UserLogins.Index())); }
public async Task Handle(CreateLocalMembership command) { // does user already exist? var hasUserId = command.Principal != null && command.Principal.Identity.HasAppUserId(); var user = hasUserId ? await _entities.GetAsync <User>(command.Principal.Identity.GetUserId <int>()) : null; if (!hasUserId) { var createUser = new CreateUser { Name = command.UserName }; await _commands.Execute(createUser); user = createUser.CreatedEntity; // verify & associate email address await _commands.Execute(new RedeemEmailVerification(user) { Commit = false, Token = command.Token, Ticket = command.Ticket, }); } user.LocalMembership = new LocalMembership { User = user, PasswordHash = await _queries.Execute(new HashedPassword(command.Password)), }; user.SecurityStamp = Guid.NewGuid().ToString(); await _entities.SaveChangesAsync(); command.CreatedEntity = user.LocalMembership; }
public virtual async Task <ActionResult> Post(CreateLocalMembership command) { if (command == null) { return(View(MVC.Errors.Views.BadRequest)); } if (!ModelState.IsValid) { var userId = User.Identity.GetUserId <int>(); var user = await _queries.Execute(new UserViewBy(userId)); var model = new CreateLocalMembershipModel { UserView = user, Command = command, }; return(View(MVC.Security.Views.User.CreatePassword, model)); } await _commands.Execute(command); TempData.Alerts("**Your password was created successfully.**", AlertFlavor.Success, true); return(RedirectToAction(await MVC.UserPassword.Index())); }
public async Task Handle(CreateRemoteMembership command) { // does user already exist? var hasUserId = command.Principal.Identity.HasAppUserId(); var user = hasUserId ? await _entities.Get <User>() .EagerLoad(new Expression <Func <User, object> >[] { x => x.RemoteMemberships, }) .ByIdAsync(command.Principal.Identity.GetUserId <int>()) : command.User; if (user == null) { var createUser = new CreateUser { Name = command.UserName }; await _commands.Execute(createUser); user = createUser.CreatedEntity; // verify & associate email address await _commands.Execute(new RedeemEmailVerification(user) { Commit = false, Token = command.Token, Ticket = command.Ticket, }); } var ticket = await _queries.Execute(new PrincipalRemoteMembershipTicket(command.Principal)); // do not add this login if it already exists if (user.RemoteMemberships.ByUserLoginInfo(ticket.Login) != null) { return; } var entity = new RemoteMembership { User = user, UserId = user.Id, Id = { LoginProvider = ticket.Login.LoginProvider, ProviderKey = ticket.Login.ProviderKey }, }; user.RemoteMemberships.Add(entity); user.SecurityStamp = Guid.NewGuid().ToString(); if (command.Commit) { await _entities.SaveChangesAsync(); } command.CreatedEntity = entity; }
public virtual async Task <ActionResult> Post(string ticket, VerifyEmailSecret command, string returnUrl, string emailAddress) { //System.Threading.Thread.Sleep(new Random().Next(5000, 5001)); if (command == null) { return(View(MVC.Errors.Views.BadRequest)); } if (!ModelState.IsValid) { ViewBag.ReturnUrl = returnUrl; ViewBag.ActionUrl = Url.Action(MVC.ResetPasswordVerifySecret.Post()); ViewBag.Ticket = ticket; ViewBag.Purpose = EmailVerificationPurpose.ForgotPassword; if (Session.VerifyEmailTickets().Contains(ticket)) { ViewBag.EmailAddress = emailAddress; } return(View(MVC.Security.Views.ResetPassword.VerifySecret, command)); } await _commands.Execute(command); return(RedirectToAction(await MVC.ResetPassword.Index(command.Token, ticket, returnUrl))); }
public async Task <IActionResult> AddCustomer([FromBody] CustomerDto customer, CancellationToken cancellationToken) { var command = new CreateCustomerCommand { FirstName = customer.FirstName, LastName = customer.LastName, EmailAddress = customer.EmailAddress }; if (!ModelState.IsValid) { return(BadRequest(ModelState)); } await _commands.Execute(command, cancellationToken).ConfigureAwait(false); if (command.CreatedEntity == null) { return(BadRequest()); } var contract = new CustomerDto { Id = command.CreatedEntity.Id, FirstName = command.CreatedEntity.FirstName, LastName = command.CreatedEntity.LastName, EmailAddress = command.CreatedEntity.EmailAddress }; return(CreatedAtAction( "GetCustomer", new { id = command.CreatedEntity.Id }, contract)); }
public virtual async Task <ActionResult> Put(ChangeUserName command) { if (command == null) { return(View(MVC.Errors.Views.BadRequest)); } var view = await _queries.Execute(new UserViewBy(command.UserId)); if (view == null) { return(HttpNotFound()); } if (!ModelState.IsValid) { var model = new ChangeUserNameModel { UserView = view, Command = command, }; return(View(MVC.Security.Views.User.Settings, model)); } await _commands.Execute(command); Response.ClientCookie(command.SignedIn.Id, _queries); return(RedirectToAction(await MVC.UserName.Index())); }
public async Task Handle(SendVerificationEmail command) { // create the email verification var createEmailVerification = new CreateEmailVerification { Commit = false, EmailAddress = command.EmailAddress, Purpose = command.Purpose, }; await _commands.Execute(createEmailVerification); var verification = createEmailVerification.CreatedEntity; // attach the email to a user when appropriate if (command.Purpose == EmailVerificationPurpose.AddEmail && command.Principal != null && command.Principal.Identity.IsAuthenticated) { verification.EmailAddress.UserId = command.Principal.Identity.GetUserId <int>(); } // load the templates var resourceFormat = string.Format("{0}.{1}.txt", verification.Purpose, "{0}"); var assembly = Assembly.GetExecutingAssembly(); var subjectFormat = assembly.GetManifestResourceText(assembly.GetManifestResourceName(string.Format(resourceFormat, "Subject"))); var bodyFormat = assembly.GetManifestResourceText(assembly.GetManifestResourceName(string.Format(resourceFormat, "Body"))); // format the message body var formatters = new Dictionary <string, string> { { "{EmailAddress}", verification.EmailAddress.Value }, { "{Secret}", verification.Secret }, // don't forget to encode the token, it contains illegal querystring characters { "{VerificationUrl}", string.Format(command.VerifyUrlFormat ?? "", Uri.EscapeDataString(verification.Token), Uri.EscapeDataString(verification.Ticket)) }, { "{SendFromUrl}", command.SendFromUrl } }; // create the message var message = new EmailMessage { EmailAddress = verification.EmailAddress, From = _appConfiguration.MailFromDefault.ToString(), Subject = formatters.Format(subjectFormat), Body = formatters.Format(bodyFormat), IsBodyHtml = false, SendOnUtc = DateTime.UtcNow, }; _entities.Create(message); // link the message to the verification verification.Message = message; await _entities.SaveChangesAsync(); _mail.Deliver(message.Id); command.CreatedTicket = verification.Ticket; }
public async Task Handle(SignOn command) { if (command.Principal.Identity.IsAuthenticated) { command.SignedOn = await _queries.Execute(new UserBy(command.Principal)); return; } // try to find user by external login credentials var externalLogin = await _queries.Execute(new PrincipalRemoteMembershipTicket(command.Principal)); if (externalLogin == null) { return; } var user = await _queries.Execute(new UserBy(externalLogin.Login)); if (user != null) { await _authenticator.SignOn(user, command.IsPersistent); command.SignedOn = user; return; } // if they don't exist, check with email claim var emailClaim = await _queries.Execute(new ExternalCookieClaim(ClaimTypes.Email)); if (emailClaim != null) { var emailAddress = await _queries.Execute(new EmailAddressBy(emailClaim) { IsVerified = true, EagerLoad = new Expression <Func <EmailAddress, object> >[] { x => x.User, }, }); if (emailAddress != null) { // need to add the external login credentials user = emailAddress.User; _entities.Update(user); // make sure it is attached to the context await _commands.Execute(new CreateRemoteMembership { Principal = command.Principal, User = user, }); await _authenticator.SignOn(user, command.IsPersistent); command.SignedOn = user; } } }
public virtual async Task <ActionResult> SignOnCallback(string returnUrl) { // make sure we have external login info var loginInfo = await _queries.Execute(new PrincipalRemoteMembershipTicket(User)); if (loginInfo == null) { return(RedirectToAction(MVC.SignIn.Index())); } var signOn = new SignOn { Principal = User, }; await _commands.Execute(signOn); if (signOn.SignedOn != null) { Response.ClientCookie(signOn.SignedOn.Id, _queries); return(this.RedirectToLocal(returnUrl, await MVC.UserName.Index())); } // if user doesn't have an email claim, we need them to verify an email address var emailClaim = await _queries.Execute(new ExternalCookieClaim(ClaimTypes.Email)); if (emailClaim == null) { return(RedirectToAction(await MVC.SignOnSendEmail.Index(returnUrl))); } // if user does have an email claim, create a verification against it var createEmailVerification = new CreateEmailVerification { Purpose = EmailVerificationPurpose.CreateRemoteUser, EmailAddress = emailClaim.Value, }; await _commands.Execute(createEmailVerification); return(RedirectToAction(await MVC.SignOnCreateUser.Index( createEmailVerification.CreatedEntity.Token, createEmailVerification.CreatedEntity.Ticket, returnUrl))); }
public virtual async Task <ActionResult> Post(CreateRemoteMembership command, string returnUrl, string emailAddress) { //System.Threading.Thread.Sleep(new Random().Next(5000, 5001)); // make sure we still have a remote login var loginInfo = await _queries.Execute(new PrincipalRemoteMembershipTicket(User)); if (loginInfo == null) { return(RedirectToAction(MVC.SignIn.Index())); } if (command == null || string.IsNullOrWhiteSpace(emailAddress)) { return(View(MVC.Errors.Views.BadRequest)); } if (!ModelState.IsValid) { var emailClaim = await _queries.Execute(new ExternalCookieClaim(ClaimTypes.Email)); ViewBag.EmailAddress = emailAddress; ViewBag.LoginProvider = loginInfo.Login.LoginProvider; ViewBag.HasClaimsEmail = emailClaim != null; ViewBag.Token = command.Token; ViewBag.Ticket = command.Ticket; ViewBag.ReturnUrl = returnUrl; return(View(MVC.Security.Views.SignOn.CreateUser, command)); } await _commands.Execute(command); var signOn = new SignOn { Principal = User, }; await _commands.Execute(signOn); Session.VerifyEmailTickets(null); Response.ClientCookie(signOn.SignedOn.Id, _queries); return(this.RedirectToLocal(returnUrl, await MVC.UserName.Index())); }
public virtual async Task <ActionResult> Post(SendVerificationEmail command) { if (command == null || command.Purpose == EmailVerificationPurpose.Invalid) { return(View(MVC.Errors.Views.BadRequest)); } if (!ModelState.IsValid) { var user = await _queries.Execute(new UserViewBy(User.Identity.GetUserId <int>())); var emails = await _queries.Execute(new EmailAddressViewsBy(User.Identity.GetUserId <int>()) { OrderBy = new Dictionary <Expression <Func <EmailAddressView, object> >, OrderByDirection> { { x => x.IsPrimary, OrderByDirection.Descending }, { x => x.IsVerified, OrderByDirection.Descending }, }, }); var model = new EmailAddressSettingsModel { UserView = user, EmailAddresses = emails.ToArray(), SendVerificationEmail = command, }; TempData.Alerts("**Could not send verification email due to error(s) below.**", AlertFlavor.Danger); ViewBag.ActionUrl = Url.Action(MVC.UserEmails.Post()); return(View(MVC.Security.Views.User.EmailAddresses, model)); } command.VerifyUrlFormat = Url.AbsoluteActionFormat(await MVC.UserEmailConfirm.Index("{0}", "{1}")); command.SendFromUrl = Url.AbsoluteAction(await MVC.UserEmails.Index()); await _commands.Execute(command); Session.VerifyEmailTickets(command.CreatedTicket); return(RedirectToAction(await MVC.UserEmailVerifySecret.Index(command.CreatedTicket))); }
public virtual async Task <ActionResult> Post(SignIn command, string returnUrl) { //System.Threading.Thread.Sleep(new Random().Next(5000, 5001)); if (command == null) { return(View(MVC.Errors.Views.BadRequest)); } if (!ModelState.IsValid) { return(View(MVC.Security.Views.SignIn, command)); } await _commands.Execute(command); Response.ClientCookie(command.SignedIn.Id, _queries); return(this.RedirectToLocal(returnUrl, await MVC.UserName.Index())); }
public async Task StartProcessing(CancellationToken cancellationToken) { var processingTask = Task.Run(async() => { try { // Consume consume the BlockingCollection while (true) { var currentCommand = _commandQueue.Take(); await _processCommands.Execute(currentCommand, cancellationToken).ConfigureAwait(false); } } catch (InvalidOperationException) { // An InvalidOperationException means that Take() was called on a completed collection //Console.WriteLine("That's All!"); } }, cancellationToken); await processingTask.ConfigureAwait(false); }
public virtual async Task <ActionResult> Post(SendVerificationEmail command, string returnUrl) { if (command == null || command.Purpose == EmailVerificationPurpose.Invalid) { return(View(MVC.Errors.Views.BadRequest)); } if (!ModelState.IsValid) { ViewBag.ReturnUrl = returnUrl; return(View(MVC.Security.Views.ResetPassword.SendEmail, command)); } command.VerifyUrlFormat = Url.AbsoluteActionFormat( MVC.ResetPassword.Index("{0}", "{1}", returnUrl).Result); command.SendFromUrl = Url.AbsoluteAction( MVC.ResetPasswordSendEmail.Index(returnUrl)); await _commands.Execute(command); Session.VerifyEmailTickets(command.CreatedTicket); return(RedirectToAction(await MVC.ResetPasswordVerifySecret.Index(command.CreatedTicket, returnUrl))); }
public virtual async Task <ActionResult> Post(SendVerificationEmail command, string returnUrl, string loginProvider) { // todo: make sure we still have a remote login if (command == null || command.Purpose == EmailVerificationPurpose.Invalid) { return(View(MVC.Errors.Views.BadRequest)); } if (!ModelState.IsValid) { ViewBag.ReturnUrl = returnUrl; ViewBag.ActionUrl = Url.Action(MVC.SignOnSendEmail.Post()); ViewBag.LoginProvider = loginProvider; return(View(MVC.Security.Views.SignOn.SendEmail, command)); } command.SendFromUrl = Url.AbsoluteAction(MVC.SignIn.Index(returnUrl)); await _commands.Execute(command); Session.VerifyEmailTickets(command.CreatedTicket); return(RedirectToAction(await MVC.SignOnVerifySecret.Index(command.CreatedTicket, returnUrl))); }
public async Task Run() { var tokenSource = new CancellationTokenSource(); // Create 2 people at 1 address var addAddressCommand1 = new CreateAddressCommand { Street = "15 My Street", Suburb = "Springfield", State = "My State", Country = "Safe Country", PostalCode = "12345" }; await _processCommands.Execute(addAddressCommand1, tokenSource.Token).ConfigureAwait(false); var addCustomerCommand1 = new CreateCustomerCommand { FirstName = "Bob", LastName = "Jones", EmailAddress = "*****@*****.**", AddressId = addAddressCommand1.CreatedEntity.Id //Commit = false }; var addCustomerCommand2 = new CreateCustomerCommand { FirstName = "Herbert", LastName = "Scrackle", EmailAddress = "*****@*****.**", AddressId = addAddressCommand1.CreatedEntity.Id //Commit = false }; await _processCommands.Execute(addCustomerCommand1, tokenSource.Token).ConfigureAwait(false); await _processCommands.Execute(addCustomerCommand2, tokenSource.Token).ConfigureAwait(false); // Now create 1 person at a second address var addAddressCommand2 = new CreateAddressCommand { Street = "742 Evergreen Terrace", Suburb = "Springfield", State = "Unknown", Country = "USA", PostalCode = "Unknown" }; await _processCommands.Execute(addAddressCommand2, tokenSource.Token).ConfigureAwait(false); var addCustomerCommand3 = new CreateCustomerCommand { FirstName = "Homer", LastName = "Simpson", EmailAddress = "*****@*****.**", AddressId = addAddressCommand2.CreatedEntity.Id //Commit = false }; await _processCommands.Execute(addCustomerCommand3, tokenSource.Token).ConfigureAwait(false); Console.WriteLine("Records created: 2 addresses, 3 people"); // Now test getting data back { // Query using "Projector" pattern where the mapping is done on Sql Server rather than in this application. // This approach is more efficient as only the required data ever comes back to the application var customersByQuery = new CustomersBy { FirstName = "Bob" }; var results = await _processQueries.Execute(customersByQuery, tokenSource.Token).ConfigureAwait(false); var resultsList = results?.ToList(); Console.WriteLine($"Querying for Customer with First Name of '{customersByQuery.FirstName}' returns {resultsList?.Count ?? 0}"); if (resultsList != null && resultsList.Count > 0) { var json = JsonSerializer.Serialize(resultsList, new JsonSerializerOptions { WriteIndented = true }); Console.WriteLine("Query result:"); Console.WriteLine(json); } Console.WriteLine(); } { // Query using Include expressions. There may be scenarios where an include is required. EF Core poses restrictions // when using AsExpandable() from LinqKit, so this QueryHandler shows how to pass Include expressions to Query<TEntity>(...) var customersWithIncludeByQuery = new CustomersWithIncludeBy() { FirstName = "Bob" }; var resultsUsingInclude = await _processQueries.Execute(customersWithIncludeByQuery, tokenSource.Token).ConfigureAwait(false); var resultsList = resultsUsingInclude?.ToList(); Console.WriteLine($"Querying for Customer with First Name of '{customersWithIncludeByQuery.FirstName}' returns {resultsList?.Count ?? 0}"); if (resultsList != null && resultsList.Count > 0) { var json = JsonSerializer.Serialize(resultsList, new JsonSerializerOptions { WriteIndented = true }); Console.WriteLine("Query result:"); Console.WriteLine(json); } Console.WriteLine(); } { // Get a single address var addressesByQuery = new AddressesBy { Id = addAddressCommand1.CreatedEntity.Id }; var addressResults = await _processQueries.Execute(addressesByQuery, tokenSource.Token).ConfigureAwait(false); var addressResultsList = addressResults?.ToList(); Console.WriteLine($"Querying for Address with id {addAddressCommand1.CreatedEntity.Id} returns {addressResultsList?.Count ?? 0}"); if (addressResultsList != null && addressResultsList.Count > 0) { var json = JsonSerializer.Serialize(addressResultsList, new JsonSerializerOptions { WriteIndented = true }); Console.WriteLine("Query result (1 address):"); Console.WriteLine(json); } Console.WriteLine(); } { // Get all address var addressesByQuery = new AddressesBy { }; var addressResults = await _processQueries.Execute(addressesByQuery, tokenSource.Token).ConfigureAwait(false); var addressResultsList = addressResults?.ToList(); Console.WriteLine($"Querying for all Addresses returns {addressResultsList?.Count ?? 0}"); if (addressResultsList != null && addressResultsList.Count > 0) { var json = JsonSerializer.Serialize(addressResultsList, new JsonSerializerOptions { WriteIndented = true }); Console.WriteLine("Query result (multiple addresses):"); Console.WriteLine(json); } Console.WriteLine(); } // Create an Employer, and a CustomerEmployerMapping for one of the Customers above var addEmployerCommand = new CreateEmployerCommand { Name = "Springfield Power Plant" }; await _processCommands.Execute(addEmployerCommand, tokenSource.Token); var addCustomerEmployerMappingComand = new CreateCustomerEmployerMappingCommand { CustomerId = addCustomerCommand3.CreatedEntity.Id, EmployerId = addEmployerCommand.CreatedEntity.Id }; await _processCommands.Execute(addCustomerEmployerMappingComand, tokenSource.Token); { // And now show the full details of all CustomerEmployerMappings, includinging drilling down var getAllCEMs = new GetCustomerEmployerMappings(); var cemResults = await _processQueries.Execute(getAllCEMs, tokenSource.Token).ConfigureAwait(false); var cemResultsList = cemResults?.ToList(); Console.WriteLine($"Querying for all CustomerEmployerMappings returns {cemResultsList?.Count ?? 0}"); if (cemResultsList != null && cemResultsList.Count > 0) { var json = JsonSerializer.Serialize(cemResultsList, new JsonSerializerOptions { WriteIndented = true }); Console.WriteLine("Query result:"); Console.WriteLine(json); } Console.WriteLine(); } }
public virtual ActionResult Post() { _commands.Execute(new SignOut()); Response.ClientCookie(null, _queries); return(RedirectToAction(MVC.Home.Index())); }
public async Task Run() { var tokenSource = new CancellationTokenSource(); var addCustomerCommand1 = new CreateCustomerCommand { FirstName = "Bob", LastName = "Jones", EmailAddress = "*****@*****.**", //Commit = false }; var addCustomerCommand2 = new CreateCustomerCommand { FirstName = "Herbert", LastName = "Scrackle", EmailAddress = "*****@*****.**", //Commit = false }; await _processCommands.Execute(addCustomerCommand1, tokenSource.Token).ConfigureAwait(false); await _processCommands.Execute(addCustomerCommand2, tokenSource.Token).ConfigureAwait(false); // Console.WriteLine("Querying All"); var customersByQueryAll = new CustomersBy(); var results = await _processQueries.Execute(customersByQueryAll, tokenSource.Token).ConfigureAwait(false); var resultsList = results?.ToList(); if (resultsList != null && resultsList.Count > 0) { var json = JsonSerializer.Serialize(resultsList, new JsonSerializerOptions { WriteIndented = true }); Console.WriteLine("Query result:"); Console.WriteLine(json); } // Console.WriteLine("Deleting Bob"); var deleteCommand = new DeleteCustomerCommand() { Id = addCustomerCommand1.CreatedEntity.Id }; await _processCommands.Execute(deleteCommand, tokenSource.Token).ConfigureAwait(false); // Console.WriteLine("Querying All Again"); results = await _processQueries.Execute(customersByQueryAll, tokenSource.Token).ConfigureAwait(false); resultsList = results?.ToList(); if (resultsList != null && resultsList.Count > 0) { var json = JsonSerializer.Serialize(resultsList, new JsonSerializerOptions { WriteIndented = true }); Console.WriteLine("Query result:"); Console.WriteLine(json); } }