Periodic report of all Episerver users?

Vote:
 

Is it possible to create a periodic (scheduled job) report of all EpiServer users that can be sent to someone? Preferabbly in .csv format? 

I would really appreciate any pointing in the right direction or any code examples that I can look into.

How would you recommend to best go about this?

#259472
Jul 26, 2021 12:21
Vote:
 

Are you talking about backend users or users of the front end of your website? What authentication system do you have in place? E.g. the OOTB asp.net identity, azure ad/OAuth provider?

#259476
Jul 26, 2021 13:28
Vote:
 

Sorry I meant backend users. I think it is the OOTB authentication.

#259477
Jul 26, 2021 13:50
Vote:
 

Get an instance of the user store

var userStore = new UserStore<ApplicationUser>(new IdentityDbContext(connectionString));

Substituing whatever user you're using if you're using any other role than the standard ApplicationUser else just user that then you can access all users via

userStore.Users
#259478
Jul 26, 2021 13:58
Vote:
 

If you are using AspNetIdentity, you can use UserManager<TUser>.Users (or ApplicationUserManager<TUser>), which TUser is your implementation of ApplicationUser

#259513
Jul 27, 2021 6:27
Scott Reed - Jul 27, 2021 8:01
What methods will work for getting multiple users? I did double check these first but they've only got methods for working with single users, I couldn't see any listing methods and the search ones require parameters.
Quan Mai - Jul 27, 2021 10:43
There is no such method, but this return IQueryable
Scott Reed - Jul 27, 2021 10:45
Ah yes I completely missed the properties when I saw. Apologies didn't see the .Users part of your comment. It's funny I would usually use the UserManager but for some reason I doubted myself when I checked it. Busy day tho
Quan Mai - Jul 28, 2021 7:01
No worries mate. We've been all there. How's life?
Scott Reed - Jul 28, 2021 8:31
Yeah not too bad, heavily in a load of commerce projects for lots of different clients. Enjoying playing with the .net 5 project and such. :-) Your blogs pop up on many a project we do as I'm sure they do for everyone. Isn't there a new version of your book on the way?
Quan Mai - Jul 28, 2021 10:49
Yes, but I'm a bit stuck with vacations and kids to make a progress on that
Scott Reed - Aug 02, 2021 8:03
haha, well family is the most important thing...at least that's what the fast and furious franchise tell me :p Have great vacations Quan :-) :-) I'm just back from a half week off, always nice to rest and recover
Vote:
 

Thank you for the suggestions so far. How hard would it be to periodically generate a report in .csv format and have it sent to a location? Or what other suggestions would you have to implement something similar?

#259564
Jul 28, 2021 9:06
Daniel Ovaska - Jul 29, 2021 18:43
A day or two of development probably depending on skill level. An hour or two for a skilled senior developer depending on what information you need
Vote:
 

It is just another scheduled job, so the "periodically" task is handled for you, other than that it is normal .net code Scheduled jobs | Optimizely Developer Community

#259568
Jul 28, 2021 10:49
Vote:
 

Thank you all for the info so far. Some more questions, any recommendations on the best tools for creating a .csv file? Also would you recommend to use the built in CMS E-Mailing capabilities to send this report to someone, or is better/safer to have the file sent/stored at a specific location?

#259673
Jul 30, 2021 7:07
Scott Reed - Aug 02, 2021 8:03
I've used the library LINQ to CSV before and it worked well
Vote:
 

I think you are over thinking it. Check your requirements to make sure you fulfill it, then do a minimal approach. You can always improve later

A search for "C# convert List<T> to csv" would be enough for first question.

Cms has no builtin mail capacity but you can simply write one using .net. Depends on what you need, but you might store the csv as an asset with specific access rights granted to certain people, and send the url to those.

#259674
Jul 30, 2021 7:20
Vote:
 

Sorry this is a pretty dumb question, but how do I find out the relevent "connectionString" from our project ?

var userStore = new UserStore<ApplicationUser>(new IdentityDbContext(connectionString));
#264759
Oct 08, 2021 9:12
Scott Reed - Oct 08, 2021 9:27
You can inject the DataAccessOptions object or get it via the service locator to get the connectionstrings.
Unless you've changed it which you can check in web.config CMS will be EPiServerDB and Commerce will be EcfSqlConnection
Vote:
 

You can inject IConnectionStringHandler in your constructor and

_connectionStringHandler.Commerce.ConnectionString or _connectionStringHandler.Cms.ConnectionString

#264764
Oct 08, 2021 10:37
Quan Mai - Oct 08, 2021 10:37
and no question is dumb. that is a totally valid question
Vote:
 

I am trying to put the following example into a ViewModel:

var userStore = new UserStore<ApplicationUser>(new IdentityDbContext(connectionString));

Like so:

using EPiServer.Cms.UI.AspNetIdentity;
using Microsoft.AspNet.Identity.EntityFramework;

namespace WebProject.Site.Models.ViewModels
{
    public class UsersReportViewModel
    {
        var userStore = new UserStore<ApplicationUser>(new IdentityDbContext("EPiServerDB"));
    }
}

The error I am getting is:

The contextual keyword 'var' may only appear within a local variable declaration or in script code

What type would you recommend here? I would like to be able to access it from my view so that I can create a table listing the users.

#265126
Oct 15, 2021 8:43
Scott Reed - Oct 15, 2021 10:50
Your trying to write code in a class definition. That's not C# syntax. Classes contain method, properties, events, constructors and such
Quan Mai - Oct 15, 2021 11:01
@Scott - right, missed that important part :)
Vote:
 

just replace var with UserStore<ApplicationUser> ? 

    public class UsersReportViewModel
    {
        public UserStore<ApplicationUser> UserStore {get;set;} = new UserStore<ApplicationUser>(new IdentityDbContext("EPiServerDB"));
    }

Should work

#265127
Edited, Oct 15, 2021 9:12
Vote:
 

Then I must be misunderstanding something crucial here. Don't I need to make the call to the userstore in the Model so that this data is provided to my view? Are there any examples that you could point to that I could look at? 

#265140
Oct 15, 2021 14:15
Quan Mai - Oct 15, 2021 14:20
This is C# thingy, you can't declare a variable (var in your case) directly inside a class. You can only define it inside a property or method. In your case, I changed it to be a property, which is allowed (And has to be) directly inside a class
Vote:
 

A few things to point out

  1. I thought this was a scheduled job or are you making an admin plugin now? What are you trying to do
  2. A view model is indeed the standard way to pass information to a view but you usually don't do the logic in the view model itself usually to do it in the controller or if being clever a view model factory
  3. The comment on your code are that it's incorrect for C#. You can't put code like that just in the class it needs to be in a method or a constructor if you were. If you can give me some more context to where you are and what you're doing, maybe post something I can help out
#265142
Oct 15, 2021 14:20
Vote:
 

Thanks guys for the feedback. No scheduled job required anymore (sorry for not mentioning it). I would like to create a custom report in the report center that displays all users (their username, email and whether their account is active or not).

I have managed to create a placeholder page in the report center called Users. Now I am trying to figure what's needed to pull all the users and the required data and display it in a simple table in the Users report.

I have my UsersReportController.cs like this currently:

using System.Web.Mvc;

namespace WebProject.Site.Controllers
{
    [EPiServer.PlugIn.GuiPlugIn(
        Area = EPiServer.PlugIn.PlugInArea.ReportMenu,
        Url = "~/usersreport",
        Category = "Users",
        DisplayName = "Users")]
    [Authorize(Roles = "Administrators, WebAdmins")]
    public class UsersReportController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    }
}

Is this where I would build the query to get all the users?

I've also got my ViewModel called UsersReportViewModel.cs where I would like to build the table, currently pretty empty:

using EPiServer.Cms.UI.AspNetIdentity;
using EPiServer.Core;
using EPiServer.DataAbstraction;
using Microsoft.AspNet.Identity.EntityFramework;
using System.Collections.Generic;

namespace WebProject.Site.Models.ViewModels
{
    public class UsersReportViewModel
    {

    }
}
#265143
Edited, Oct 15, 2021 14:24
Scott Reed - Oct 15, 2021 14:27
That's fair although one point to mention is the new version of the platform (Optimizely CMS 12) completely removes reports from the feature set so it's not a great future proof way of doing it.

If you want to make this future proof for CMS 12 I would look at this way https://world.optimizely.com/blogs/mark-stott/dates/2021/8/extending-the-admin-interface-in-optimizely-cms-12/ . If you're happy with a report can you share the code you've written so far for the report?
EpiNewbie - Oct 15, 2021 14:32
For now I am happy with building a report instead of extending the admin menu. But sadly I have not yet managed to build the code the report as I seem to be struggling with the basics as you can see by my questions :-(
Scott Reed - Oct 15, 2021 14:34
Have you see https://world.optimizely.com/blogs/Henrik-Fransas/Dates/2016/3/create-custom-report-in-mvc-with-excel-export/ this seems to show how to build a report in MVC?
EpiNewbie - Oct 15, 2021 14:38
That's the guide I am trying to follow which has gotten me so far as to be able to have a placeholder page in the report center. I am somewhat confused as to the next steps though. Do I need put the logic into the controller in my case? What do I do with the ViewModel?
Scott Reed - Oct 15, 2021 14:43
Normally a ViewModel is just a model, it contains only properties. You populate those properties from something else (such as a controller) then pass it to the view which then displays those properties. This page https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions/mvc-music-store/mvc-music-store-part-3 gives a run down of the basic of using models within MVC, it might be worth a read through.
EpiNewbie - Oct 15, 2021 14:50
Thanks very much Scott, really appreciated. I will give it a shot and see how it goes. Thanks for pointing me in the right direction.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.