Problem with DbContext prop on asp net core 2.1 - asp.net-core

I have created an api in asp net core 2.1 and I have three layers inside it (PwP.Web).
In the layer (PWP.DomainClasses) I defined a class with the following specifications and in the layer (PWP.DataLayer) a class called PWPDbContext and inside it I want to define the user class as prop but it warns and is not used, how this Solve the problem?
User.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
namespace PWP.DataLayer.User
{
public class User
{
[Key]
[Required]
public int UserId { get; set; }
[Required]
[MaxLength(50)]
public string UserName { get; set; }
[Required]
[MaxLength(32)]
public string Password { get; set; }
[Required]
[MaxLength(150)]
public string Email { get; set; }
[MaxLength(200)]
public string imageAddress { get; set; }
//
public virtual UserInfo.UserInfo UserInfo { get; set; }
}
}
PWPContext.cs:
using Microsoft.EntityFrameworkCore;
using PWP.DomainClasses.user;
namespace PWP.DataLayer.Context
{
class PWPDbContext:DbContext
{
public PWPDbContext(DbContextOptions<PWPDbContext> options): base(options)
{
}
public DbSet<User> Users { get; set; }
public DbSet<UserInfo> UserInfos { get; set; }
public DbSet<Document> Documents { get; set; }
public DbSet<Expertise> Expertises { get; set; }
public DbSet<Message> Messages { get; set; }
public DbSet<Record> Records { get; set; }
public DbSet<STFile> STFiles { get; set; }
}
}

From this line of code:
public virtual UserInfo.UserInfo UserInfo { get; set; }
It can be seen that you named the class with the exact same name as it's namespace.
You should differentiate between them.
Don't (!) do that:
namespace UserInfo
{
public class UserInfo
{
}
}

Related

Model in model is null so modelstate is invalid

I have a model in another model. When I try to check the modelstate it is invalid. This is because the other model in this model is null.
Project.cs:
using System.ComponentModel.DataAnnotations;
namespace Toolbox.Models
{
public class Project
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public WorkPreparation WorkPreparation { get; set; }
}
}
WorkPreparation.cs:
using System.ComponentModel.DataAnnotations;
namespace Toolbox.Models
{
public class WorkPreparation
{
[Key]
public int Id { get; set; }
public int ProjectId { get; set; }
public CentralHeating CentralHeating { get; set; }
public Pluming Pluming { get; set; }
public Ventilation Ventilation { get; set; }
public Project Project { get; set; }
}
}
Does anybody have any suggestion?
If you use .net6, try to remove <Nullable>enable</Nullable> in your project.csproj.

Setting up Automapper 5.1

I am having trouble following the wiki in this instance. I wanted to use Automapper 5.2. I cannot find a simple end for end example that shows a solid configuration with context. By context I mean where do you put the config files and whats the difference between static and instance api?
I checked out the DNRTV download but it deals with the 1.0 version.
How do you set this package up? I have a model called Client as below.
public class Client : IEntityBase
{
public Client()
{
Jobs = new List<Job>();
}
public int Id { get; set; }
public int ClientNo { get; set; }
public bool Company { get; set; }
public string CompanyName { get; set; }
public string ClientFirstName { get; set; }
public DateTime DeActivated { get; set; }
public bool Activity { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateUpdated { get; set; }
public int? StateId { get; set; }
public State State { get; set; }
public int CreatorId { get; set; }
public User Creator { get; set; }
public ICollection<Job> Jobs { get; set; }
}
and a ClientViewModel as so:
public class ClientViewModel
{
public int Id { get; set; }
public int ClientNo { get; set; }
public bool Company { get; set; }
public string CompanyName { get; set; }
public string ClientFirstName { get; set; }
public DateTime DeActivated { get; set; }
public bool Activity { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateUpdated { get; set; }
public int? StateId { get; set; }
public int CreatorId { get; set; }
public int[] Jobs { get; set; }
}
I am unsure how to set AutoMapper up with regard to configuration. That is, they talk about a global.asax file and I am using aspnet core.. there is no Global.asax file..
What do you put in the Startup.cs file if anything.
Given these two files above what do I need to do to use Automapper with them?
Regards
Here is the steps to configure the automapper in asp.net core mvc.
1. Create the mapping profile class which extends from Profile
public class ClientMappingProfile : Profile
{
public ClientMappingProfile ()
{
CreateMap<Client, ClientViewModel>().ReverseMap();
}
}
2. Create the AutoMapper Configuration Class and add your mapping profile class here.
public class AutoMapperConfiguration
{
public MapperConfiguration Configure()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<ClientMappingProfile>();
});
return config;
}
}
3. Create extension method so, we can add this to Startup.cs ConfigureServices method
public static class CustomMvcServiceCollectionExtensions
{
public static void AddAutoMapper(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
var config = new AutoMapperConfiguration().Configure();
services.AddSingleton<IMapper>(sp => config.CreateMapper());
}
}
4. Call the extension method in Startup.cs ConfigureServices method
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DBContext>(options =>options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddMvc();
services.AddAutoMapper();
}

MVC4 - Controller Scaffolding, Custom Data context class issue: Unable to retrieve metadata

When I try to create a controller by scaffolding, I get the following error:
Unable to retrieve metadata for 'TurkUp.Models.Admin.CreateCourseViewModel'. Schema specified is not valid. Errors:
The mapping of CLR type EDM is ambiguous because multiple CLR types match the EDM type 'Coursework'.
Here is the code for the model:
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace TorkUp.Models.Admin
{
public class CreateCourseViewModel
{
[HiddenInput(DisplayValue = false)]
public int Id { get; set; }
[Required]
public string Title { get; set; }
}
}
The custom data context class:
using System.Data.Entity;
using System.Linq;
using TorkUp.ClassLibrary;
using TorkUp.ClassLibrary.Admin;
using TorkUp.ClassLibrary.User;
namespace TorkUp.Infrastructure
{
public class UniversityDb : DbContext, IUniversityDataSource
{
public UniversityDb() : base("DefaultConnection") { }
// Admin data
public DbSet<Course> Courses { get; set; }
public DbSet<Class> Classes { get; set; }
public DbSet<Coursework> Courseworks { get; set; }
public DbSet<Student> Students { get; set; }
// User data
public DbSet<Assignment> Assignments { get; set; }
public DbSet<Task> Tasks { get; set; }
// Admin data
IQueryable<Course> IUniversityDataSource.Courses { get { return Courses; } }
IQueryable<Class> IUniversityDataSource.Classes { get { return Classes; } }
IQueryable<Coursework> IUniversityDataSource.Courseworks { get { return Courseworks; } }
IQueryable<Student> IUniversityDataSource.Students { get { return Students; } }
// User data
IQueryable<Assignment> IUniversityDataSource.Assignments { get { return Assignments; } }
IQueryable<Task> IUniversityDataSource.Tasks { get { return Tasks; } }
// Save to database
void IUniversityDataSource.Save() { SaveChanges(); }
}
}
And the class for the course:
using System.Collections.Generic;
namespace TorkUp.ClassLibrary.Admin
{
public class Course
{
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public ICollection<Class> Classes { get; set; }
public ICollection<Coursework> Courseworks { get; set; }
}
}
If you have this error, it is because in you DbContext:
// Admin data
public DbSet<Course> Courses { get; set; }
public DbSet<Class> Classes { get; set; }
public DbSet<Coursework> Courseworks { get; set; } //you use here Coursework class to create a DbSet. But when you scaffold you use CreateCourseViewModel.
public DbSet<Student> Students { get; set; }
If you want to use CreateCourseViewModel, then you have to change this line above. But I think as you put ViewModel suffix the purpose of CreatecourseViewModel is to wrap another classes for displaying in the view.

Pass through multiple dbmodel to a view from a controller

I am using ASP.NET MVC 4.
I have this class:
namespace Attempt4.Models
{
public class UsersModel : DbContext
{
public UsersModel()
: base("name=UsersConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
public DbSet<Roles> UserRoles { get; set; }
public DbSet<UsersInRoles> UsersInUserRoles { get; set; }
}
}
and
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
}
Then there is another class:
public partial class FskWebInterfaceContext : DbContext
{
public FskWebInterfaceContext()
: base("name=FskWebInterfaceContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<trigger_dest_assoc> trigger_dest_assoc { get; set; }
public DbSet<ut_AccessLevel> ut_AccessLevel { get; set; }
public DbSet<ut_Client> ut_Client { get; set; }
public DbSet<ut_ContactID> ut_ContactID { get; set; }
public DbSet<ut_destinations> ut_destinations { get; set; }
public DbSet<ut_DeviceDescription> ut_DeviceDescription { get; set; }
public DbSet<ut_DeviceType> ut_DeviceType { get; set; }
public DbSet<ut_event_log> ut_event_log { get; set; }
public DbSet<ut_GMUTempData> ut_GMUTempData { get; set; }
public DbSet<ut_Triggers> ut_Triggers { get; set; }
public DbSet<ut_User> ut_User { get; set; }
public DbSet<ut_UserAPNdevices> ut_UserAPNdevices { get; set; }
public DbSet<ut_UserClientLink> ut_UserClientLink { get; set; }
}
Now I need to be able to access both of these database contexts from my view.
I know how to pass through just a model for example just UserProfile. But I need to be able to access all of the elements in these two classes.
How can i pass them through from the controller to the View.
And Specifically, once I have passed them through, how do I access them individually in the view?
You have the answer in the comments section of your question:
From what I have been reading I need to make use of a ViewModel class.
So go ahead and define a class that will contain the necessary information. Then in your controller action populate the properties of this model and have it passed to the view.
For example let's suppose that you wanted to access UserProfiles from the first context and the ut_GMUTempData from the second context:
public class MyViewModel
{
public IList<UserProfile> UserProfiles { get; set; }
public IList<ut_GMUTempData> GMUTempData { get; set; }
}
and in your controller action:
public ActionResult Index()
{
using (var ctx1 = new UsersModel())
using (var ctx2 = new FskWebInterfaceContext())
{
var model = new MyViewModel();
model.UserProfiles = ctx1.UserProfiles.ToList();
model.GMUTempData = ctx2.ut_GMUTempData.ToList();
return View(model);
}
}
and now your view becomes strongly typed to the view model and you can access both properties:
#model MyViewModel
... you could use both #Model.UserProfiles and #Model.GMUTempData collections
UPDATE:
As requested in the comments section here's how you could loop through the user profiles in the view:
#model MyViewModel
#foreach (var profile in Model.UserProfiles)
{
<div>#profile.SomePropertyOfTheUserProfileClassThatYouWantToDisplayHere</div>
}

Entity framework code first generate database incorrect

I think entity framework has problem while generating database in my project. That's strange that it only happens in one case. This is one to many relationship between "User" and "Playlist". One User has many Playlists.
Here is my code, I used some abstract classes in my project.
Core code
Playlist class
public virtual User User { get; set; }
User class
public virtual ICollection<Playlist> Playlists { get; set; }
The full code:
Generic class:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace xxx.Areas.admin.Models
{
public abstract class Generic
{
[Display(Name = "Ngày tạo")]
public DateTime? Created { get; set; }
[Display(Name = "Lần sửa cuối")]
public DateTime? Modified { get; set; }
[Display(Name = "Trạng thái")]
public bool? IsActive { get; set; }
}
}
Post class:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace xxx.Areas.admin.Models
{
public abstract class Post : Generic
{
public string Title { get; set; }
public string Slug { get; set; }
public string Content { get; set; }
public string Image { get; set; }
public int Views { get; set; }
public bool? AllowComment { get; set; }
public User ModifiedBy { get; set; }
public virtual ICollection<Media> Medias { get; set; }
}
}
AlbumBase class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using xxx.Areas.admin.Models.SongBase;
namespace xxx.Areas.admin.Models.AlbumBase
{
public abstract class AlbumBase : Post
{
public bool IsPublic { get; set; }
public bool IsFeatured { get; set; }
public int OldID { get; set; }
public string OldSlug { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}
}
Playlist class:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using xxx.Areas.admin.Models.SongBase;
namespace xxx.Areas.admin.Models.AlbumBase
{
public class Playlist : AlbumBase
{
[Key]
public int PlaylistID { get; set; }
public virtual ICollection<Song> Songs { get; set; }
public virtual ICollection<Folk> Folks { get; set; }
public virtual ICollection<Instrumental> Instrumentals { get; set; }
public virtual User User { get; set; }
public Playlist()
{ }
public Playlist(string name)
{
Title = name;
Slug = Functions.URLFriendly(Title);
Views = 0;
OldID = 0;
AllowComment = true;
IsActive = true;
IsPublic = false;
IsFeatured = false;
Created = DateTime.Now;
}
}
}
and User class:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using baicadicungnamthang.Areas.admin.Models.AlbumBase;
using baicadicungnamthang.Areas.admin.Models.Social;
using baicadicungnamthang.DAL;
using ICB;
namespace xxx.Areas.admin.Models
{
public class User : Generic
{
[Key]
public int UserID { get; set; }
[Required(ErrorMessage = "Bạn phải nhập tên tài khoản"), StringLength(50)]
public string UserName { get; set; }
public string Password { get; set; }
public string HashPassword { get; set; }
[Required(ErrorMessage = "Bạn phải nhập địa chỉ email"), EmailAddress(ErrorMessage = "Địa chỉ email không hợp lệ")]
public string Email { get; set; }
[StringLength(50)]
public string NickName { get; set; }
public string FullName { get; set; }
public string Slug { get; set; }
public string Title { get; set; }
public string Phone { get; set; }
public string Avatar { get; set; }
public DateTime? DOB { get; set; }
[StringLength(1)]
public string Gender { get; set; }
public string Address { get; set; }
public int TotalLikes { get; set; }
public int TotalComments { get; set; }
public int Views { get; set; }
public string ActivationKey { get; set; }
public string RecoverKey { get; set; }
public DateTime? LastLogin { get; set; }
public int OldID { get; set; }
public virtual Role Role { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
public virtual ICollection<Comment> RateComments { get; set; }
public virtual ICollection<Playlist> Playlists { get; set; }
public virtual ICollection<User> Friends { get; set; }
public virtual ICollection<Message> MessagesSent { get; set; }
public virtual ICollection<Message> MessagesReceived { get; set; }
public User()
{
Created = DateTime.Now;
IsActive = false;
TotalLikes = 0;
Views = 0;
OldID = 0;
}
public string getAvatar(int w, int h)
{
return Functions.getAvatarThumb(UserName, w, h);
}
public int getAge()
{
if (DOB == null)
{
return 0;
}
else
{
DateTime now = DateTime.Now;
int age = now.Year - DOB.Value.Year;
return age;
}
}
public string getGender()
{
if (Gender == "M")
{
return "Nam";
}
else if (Gender == "F")
{
return "Nữ";
}
else return "";
}
}
}
And this is Playlist table generating from code first:
As you see, entity framework has generated two columns: User_UserID and User_UserID1 from primary key UserID of User table.
I say that because when I uncomment the line
//public virtual User User { get; set; }
and rebuild the project, the two column User_UserID and User_UserID1 has disappeared too.
The problem only happens with User and Playlist relationship. With other one-to-many scenarios (User-Comments), system work well.
Can anyone give me a suggestion?
The problem is that you have multiple relationships between the same entities.
Playlist has 2 references to User (one in the Playlist class and one in its base class Post).
This confuses Entity Framework, because it doesn't know how to map the relationships, which is why it creates too many foreign keys in the database.
To fix this you can use the InverseProperty attribute to tell it how to map the navigation properties:
public class Playlist : AlbumBase
{
[Key]
public int PlaylistID { get; set; }
[InverseProperty("Playlists")]
public virtual User User { get; set; }
......