how to load a list of custom UserAccount from AppSettings? - c#

My Identity Settings class:
public abstract class UserAccount
{
[Required]
public string Firstname { get; set; }
[Required]
public string Lastname { get; set; }
[EmailAddress]
public string Email { get; set; }
public string Password { get; set; }
[Required]
public string RoleName { get; set; }
}
public class AdministratorUserAccount : UserAccount
{
public string Company{ get; set; }
}
public class ManagerUserAccount : UserAccount
{
public string AdministratorEmail { get; set; }
}
public class IdentitySettings
{
[Required]
[MinLength(1)]
public List<UserAccount> UserAccounts { get; set; }
}
in startup.cs:
services.Configure<T>(configuration.GetSection("Identity"));
in DBInitializer, the list of UserAccounts is always empty.
var defaultUserAccountsSettings = services.GetRequiredService<IOptions<IdentitySettings>>().Value;
How to be able to get the data from appsettings.json serialized in a list of UserAccount where UserAccount can be Administrator or Manager.

It seems like the option binding doesn't know which concreate class object to create to fill up the list since UserAccount is abstract.
To make the scenario work, we need to have a way to control the creation of the object somehow.
How about putting the list in an additional json (test-data.json for example), read it by a jsonSerializer, and fill up the list:
services.AddOptions<IdentitySettings>().Configure(idSettings => {
idSettings.UserAccounts = JsonConvert.DeserialzeObject<IdentitySettings>(...); // Whatever deserializer that works.
});
Here's how to creating object with TypeNameHandling with Newtonsoft.Json: Deserialize a List<AbstractClass> with newtonsoft.json.
=====
After I read the comment, I realized you relies on Options pattern with various providers. In that case, technically, one approach could be parsing of IConfigurationSection like this:
var x = Configuration.GetSection("UserAccounts").AsEnumerable();
The result of the KeyValue pair will be a bit tedious to deal with, like:
Key
Value
UserAccount
null
UserAccount:0
null
UserAccount:0:FirstName
Mike
UserAccount:0:LastName
...
...
UserAccount:1
null
UserAccount:1:FirstName
...
...
Group it by the index will results to Group<int, IEnumerable<KeyVaultPair<string, string>>.
Create a factory method like static bool TryBuildAccount(IEnumerable<KeyValuePair<string,string>> input, out UserAccount account); to create one object by 1 group.
Then, the question is, it it really worth it? Will it become too complex when there's change to the Account class.
I would probably take Hassan Monjezi's suggestion unless there's better way that doesn't require that much tedious code.

Related

Returning different versions of set of data

So I have a class with a static method that uses EF to retrieve certain set of mailing lists and maps to the class.
public static List<MailingList> GetMailingListsForUser(IUsersAccess user, IProspectorDataSource db )
{
return db.MailingLists.Where(x => x.UserID == user.UserID).ToList()
.Select(y => new MailingList(y, db) ).ToList();
}
Now though I have a proc that will return the MailingList plus some extra stuff. I don't want to add these extra columns (which will be used in other sections and areas of functionality) to this class. What is the best way to address this?
I am thinking a Factory Pattern that will generate a different class that implements different contracts (interfaces) based on whats needed. Going to try implement it and will post code/working when completed.
Was wondering what other people have done in instances like this and if there are any better ways to address this.
Edit: (some extra information to help people understand what I mean).
public class MailingList
{
public int MailingListID { get; set; }
public string Name { get; set; }
public string Comments { get; set; }
public List<string> Tags { get; set; }
public int UserID { get; set; }
public System.DateTime DateCreated { get; set; }
public string CreatedBy { get; set; }
public System.DateTime LastModified { get; set; }
public string ModifiedBy { get; set; }
public List<MailingListAddress> MailingListAddresses { get; set; }
That is the definition of an object that we return. Now there is a new instance where I am going to return some extra columns from a proc and map to MailingList. So I could just add the properties to here but the issue is MailingListAddresses will be null as they will not be returned by the stored proc. So is there a way to map to specific properties and not have to return null for MailingListAddresses to the front end every time.
This was fixed by a senior developer who ended up going with the factory pattern. I will add the code when I get back to work :)

.net core : incomplete JSON response

I'm trying to build simple API for training, in my database I got users (firstname, lastname, email password, list<sports>) and sports ( name, userID).
All is okay when I want to get my users, I got an object populated with sports. But the JSON response is incomplete, it is "cut" in the middle.
[{"firstName":"Nicolas","lastName":"Bouhours","email":"n.bouh#test.com","password":"nico#hotmail.fr","sports":[{"name":"Trail","userId":1
This is my controller :
// GET: api/Users
[HttpGet]
public IEnumerable<User> GetUsers()
{
var users = _context.Users.Include(u => u.Sports).ToList();
return users;
}
And my models :
public class Sport : BaseEntity
{
public string Name { get; set; }
public int UserId { get; set; }
public User User { get; set; }
}
public class User : BaseEntity
{
public String FirstName { get; set; }
public String LastName { get; set; }
public String Email { get; set; }
public String Password { get; set; }
public List<Sport> Sports { get; set; }
}
public class SportAppContext : DbContext
{
public SportAppContext(DbContextOptions<SportAppContext> options) : base(options)
{ }
public DbSet<User> Users { get; set; }
public DbSet<Sport> Sports { get; set; }
}
I really don't understand what happen, if you have any idea
I'm running into the same issue right now. You can also change the JSON serialization/configuration settings to ignore self-reference loops, as shown in the accepted answer for this question
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddJsonOptions(options => {
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
}
I had this problem to in one of my projects. This is caused by a self referencing loop.
You need to create some sort of DTO (Data Transfer Object) which will be used to generate your JSON.
In your DTO you remove the inverse relationship so you end up having something like
public class SportDto
{
public string Name { get; set; }
}
public class UserDto
{
public String FirstName { get; set; }
public String LastName { get; set; }
public String Email { get; set; }
public String Password { get; set; }
public List<SportDto> Sports { get; set; }
}
You then map your user User and Sport models to your UserDto and SportDto
A good tool for doing this mapping is AutoMapper. You can read the docs to see how to get started.
After the mapping is done, you Send the DTOs as your JSON and not your models.
Just to add another yet unique scenario where this can occur. This can also happen if your DAL is returning queryables. In my scenario, I was returning a boxed object from the DAL and had something like this as a linq query
...
RootLevelProp1 = "asd",
RootLevelProp2 = "asd",
Trades = b.Trades.OrderBy(c => c.Time).Select(c => new
{
c.Direction,
c.Price,
c.ShareCount,
c.Time
}) //<---- This was being returned as a queryable to the controller
The Trades query was never being executed even though it's root object had .ToListAsync() called on it. What was happening was that the controller would return the result but only up to the Trades section and the Json would not be terminated properly. I then realized an exception was being caught in some custom middleware I wrote in which it was complaining about the data reader already being open. Without going to deep into my investigation, I assumed it had to do something with the DI and how it was handling the lifecycle of the context. The fix was to just add ToList on the trades. It's an ugly way to pass data from the DAL but this is just a fun project.
In my case this solve my issue on core 3, by using Newtonsoft:
https://learn.microsoft.com/en-us/aspnet/core/web-api/advanced/formatting?view=aspnetcore-3.0#add-newtonsoftjson-based-json-format-support
Prior to ASP.NET Core 3.0, the default used JSON formatters
implemented using the Newtonsoft.Json package. In ASP.NET Core 3.0 or
later, the default JSON formatters are based on System.Text.Json.
Support for Newtonsoft.Json based formatters and features is available
by installing the Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet
package and configuring it in Startup.ConfigureServices.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddNewtonsoftJson();
}
The selected answer was correct in my case as well, my JSON response was getting truncated by a reference loop in my JSON response, and setting ReferenceLoopHandling.Ignore did indeed solve my issue. However, this is not the best solution in my opinion, as this maintains the circular references in your model. A better solution would use the [JsonIgnore] attribute within the model.
The issue in your model is here:
public class Sport : BaseEntity
{
public string Name { get; set; }
public int UserId { get; set; }
public User User { get; set; } //This is the cause of your circular reference
}
public class User : BaseEntity
{
public String FirstName { get; set; }
public String LastName { get; set; }
public String Email { get; set; }
public String Password { get; set; }
public List<Sport> Sports { get; set; }
}
As you can see, your User navigation property is where this response is truncated. Specifically, it will cause each Sport in the json response to contain all of the user information for each sport entry in the response. Newtonsoft does not like this. The solution is to simply [JsonIngore] the navigation properties that cause this circular reference. In your code this would be:
public class Sport : BaseEntity
{
public string Name { get; set; }
public int UserId { get; set; }
[JsonIgnore]
public User User { get; set; } //fixed
}
public class User : BaseEntity
{
public String FirstName { get; set; }
public String LastName { get; set; }
public String Email { get; set; }
public String Password { get; set; }
public List<Sport> Sports { get; set; }
}
Faced similar issue, response was getting truncated. Issue was a getter method which trying to formatting date.

Filling list with different types of objects

I'm working on a recommendation algorithm which all works fine. But now I wanted to implement this code into the branch of my development team.
I'll start from the top. My algorithm can recommend 2 types of objects, restaurants and dishes.
Restaurant:
public class Restaurant
{
public Guid Id { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
public List<Tag> Tags { get; set; } = new List<Tag>();
public int PriceRange { get; set; }
}
And dish:
public class Dish
{
public Guid Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public virtual Restaurant rest { get; set; }
[ForeignKey("rest")]
public Guid RestaurantId { get; set; }
public List<Tag> Tags { get; set; }
}
Now my product owner wants the list to be like this when it's being presented on the home page of our app:
[Restaurant][Dish][Restaurant][Dish] Etc...
So basically, he wants to alternate the type of object that's being recommended. These dishes and restaurants are completely separate. They are generated by my algorithm purely on the user's preferences and have no correlation with eachother at all.
Now my problem is how to return such a list. I figured I'd need a wrapper class which contains either a Restaurant or Dish like this:
public class RecommenderItem
{
public Restaurant rest { get; set; }
public Dish dish { get; set; }
}
This way I can create a List<RecommenderItem> and return that to the client. The client would only need to check which attribute is null and retrieve the values from the one that is not.
I'm just unsure if this is the correct approach. Are there any 'best practices' in doing this? Let me know if I should elaborate more!
If they doesn't have common base class then creating one wrapper class is the best solution. At the same time you can be more flexible and create something like
public class RecommendationItem
{
public Guid Id { get; set; }
public string Name { get; set; }
public string PageUrl { get; set; }
public object Entity { get; set; }
}
So you can include all common information in this class and client will not be required to check with which object type he works. In such case it would be easier to add one more item type. At the same type I added reference to entity itself - it can be used if some specific handling for one or two item types is required.
You can declare an interface IRecommenderItem:
public interface IRecommenderItem
{
//shared properties
}
public class Restaurant : IRecommenderItem
{
}
public class Dish : IRecommenderItem
{
}
than, you can type:
List<IRecommenderItem> m = new List<IRecommenderItem>();
If you are going to connect pairs of elements it always makes sense to me to... well, pair the elements. I am assuming that each dish is specific to a particular restaurant? So the list would be [Restaurant1][Dish for Restaurant1][Restaurant2][Dish for Restaurant2]...?
I like the previous answer by oryol creating a common base class as well.
So, your RecommenderItem class is fine. But fill in both properties and pass a list of pairs back. Expand the list into the full set of items for display by creating a new List, iterating through the list of RecommenderItems and adding Restaurant and Dish from each entry in it.

Recovery of class containing a list returns a null list

I have a couple of classes:
public class MyGoalsModel
{
[Key]
public string Name { get; set; }
/*Some local bools*/
public List<MyGoalString> myGoals { get; set; }
}
public class MyGoalString
{
public int MyGoalStringID { get; set; }
public string GoalString { get; set; }
public bool Selected { get; set; }
}
I can populate them correctly, and the code (EF?) generates the necessary hidden foreign keys to link them (all ok in SQL) and recover the information for MyGoalsModel, but the List is always null.
I use the following to get the entry I want:
MyGoalsModel goals = db.MyGoals.Find(Name);
but when I investigate the code goals.MyGoals is always null.
Am I missing something, is there a better way to recover the information with the lists present?
Add the keyword virtual so EF can create a proxy for your List and lazy load the data when needed.
Edit: Or as stated in the accepted answer in this question.

Proper domain model design

Given an Employee entity and bunch of personal/organization-related information (like marital status, children information, department, position). Is all personal information to be represented as components/value objects or it is better for the information to reside inside the entity class?
Would using a person (which could gather all personal info) value object as an underlying object (composition) for an Employee entity be a bad design choice?
Also how would such a behaviour modelled properly (in terms of DDD): If employee has kids then it should have a birth certificate (with corresponding data: name, issue date, etc) or If employee is married then it should have marriage certificate (with corresponding data: spouse name, etc)?
For a kids case I decided to use ChildrenInformation value object:
public class ChildrenInformation
{
public String BirthCertificateCode { get;set; }
public DateTime BirthCertificateIssueDate { get;set; }
public ChildName { get; set; }
public ChildMiddleName { get; set; }
public ChildLastName { get; set; }
public DateTime ChildBirthday{ get; set; }
}
public class Employee : AbstractEntity<Employee>, IAggregateRoot
{
public ISet<ChildrenInformation> ChildrenInformation { get; set; }
/* other things ...*/
}
Wouldn't it be wrong from a design view?
EDIT
Another thought is to share Certificate class.
[Serializable]
public class Certificate
{
public String Code { get; set; }
public String Number { get; set; }
public String RegistreeName { get; set; }
public Address RegistreeAddress { get; set; }
public String RegistreeDateOfBirth { get; set; }
public String RegistredAt { get; set; }
public DateTime DateRegistred { get; set; }
}
[Serializable]
public class Employee : AbstractEntity<Employee>, IAggregateRoot
{
public Certificate Passport { get; set; }
public Certificate MarriageCertificate { get; set; }
public ISet<Certificate> ChildrenBirthCertificates { get; set; }
}
Thanks!
I would model it like this:
public class Person
{
public String Name { get; set; }
public String MiddleName { get; set; }
public String LastName { get; set; }
public DateTime Birthday { get; set; }
public BirthCertificate BirthCertificate { get;set; }
public MarriageCertificate MarriageCertificate { get;set; }
// ...etc...
}
public class Certificate
{
public String Code { get;set; }
public DateTime IssueDate { get;set; }
// ...etc...
}
public class BirthCertificate: Certificate
{
public DateTime BirthDate { get;set; }
// ...etc...
}
public class MarriageCertificate: Certificate
{
public String SpouseName { get;set; } // or Spouse could also be a person
// ...etc...
}
public class Employee
{
public ISet<Person> Children { get; }
// ...etc...
}
Some points:
Note the ? usage which means certificates are optional.
Certificate deserve their own types. If you have more than one property that start with the same prefix, most of the time, it means you can define an object off them. I have also created a base Certificate class because they may share some common properties and behavior.
Children is a collection of Person objects.
Spouse could also be a person, if you will (the property would then be named Spouse).
I don't repeat the declaring type name in a property name: Name instead of PersonName
Given an Employee entity and bunch of personal/organization-related information (like marital status, children information, department, position). Is all personal information to be represented as components/value objects or it is better for the information to reside inside the entity class?
I would put all of the given examples as properties in the employee entity. I don't see any benefit in having them as value objects?
Would using a person (which could gather all personal info) value object as an underlying object (composition) for an Employee entity be a bad design choice?
This is more of a domain question. I normally do not use inheritance but use Customer and Employee (instead of a Person entity) as to different models not related to each other.
Please note that the design concept of composition has nothing to do with the CLR concept of a value type. Composition just means that the life-time of the owned object is bound to the life-time of the owner. This can also be achieved with reference types, for example if the owner is the only one with a reference to the owned object.
That said, the solution from Simon is just fine.

Categories