How do I store user input into database using ASP.NET Core MVC? - asp.net-mvc

I am struggling to find a solution on how to add user input like first name, last name, zipcode.... to the database. The email is already stored in database during signUp.
I tried looking at some resource but they seem complicated.
HomeController
public async Task<IActionResult> ProfileView(ApplicationUser users)
{
return View();
}
Application user model:
public class ApplicationUser: IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public int ZipCode { get; set; }
}
Profile view:
<form>
<div class="form-row">
<div class="form-row col-md-6">
<div class="col">
<label for="firstName">First Name:</label>
<input type="text" class="form-control" placeholder="First name">
</div>
<div class="col col-md-6">
<label for="lastName">Last Name:</label>
<input type="text" class="form-control" placeholder="Last name">
</div>
</div>
<div class="form-group col-md-6">
<label for="inputEmail4">Email</label>
<input type="email" class="form-control" id="inputEmail4" placeholder="Email">
</div>
</div>
Database context:
public class DataBaseContext: IdentityDbContext<ApplicationUser>
{
public DataBaseContext(DbContextOptions<DataBaseContext> options): base(options)
{
}
public new DbSet<SignUp> Users { get; set; }
public DbSet<Products> Products { get; set; }
}
When the user fills out the information in the view it should store it in an existing database.

Here is a working example on modifying user's profile after logining :
Profile View :
#model MVC2_2Project.Models.ApplicationUser
<div class="row">
<div class="col-md-6">
<form id="profile-form" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="FirstName"></label>
<input asp-for="FirstName" class="form-control" placeholder="First name"/>
<span asp-validation-for="LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="LastName"></label>
<input asp-for="LastName" class="form-control" placeholder="Last name"/>
<span asp-validation-for="LastName" class="text-danger"></span>
</div>
<button id="update-profile-button" type="submit" class="btn btn-primary">Save</button>
</form>
</div>
</div>
#section Scripts {
<partial name="_ValidationScriptsPartial" />
}
HomeController:
public class HomeController : Controller
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly ApplicationDbContext _context;
public HomeController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
ApplicationDbContext context)
{
_userManager = userManager;
_signInManager = signInManager;
_context = context;
}
public async Task<IActionResult> ProfileView()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
return View(user);
}
[HttpPost]
public async Task<IActionResult> ProfileView(ApplicationUser users)
{
if (!ModelState.IsValid)
{
return View();
}
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
user.FirstName = users.FirstName;
user.LastName = users.LastName;
_context.Users.Update(user);
await _context.SaveChangesAsync();
await _signInManager.RefreshSignInAsync(user);
return RedirectToAction();
}
}

Related

how can i show the data that the user entered in the file input when he want to edit it

for your information the file is saved as a binary data
here is is the model:
public class Movie
{
[Key]
public int MovieId { get; set; }
public string MovieName { get; set; }
public string MovieDescription { get; set; }
public byte[] MovieImage { get; set; }
public string MovieTrailer { get; set; }
//FK
public int AdminId { get; set; }
//Navigation
public Admin Admin { get; set; }
public ICollection<Event> Events { get; set; }
public AddingCategory AddingCategory { get; set; }
public ViewingMovie ViewingMovie { get; set; }
}
}
And here is the controller :
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.tblMovies.FindAsync(id);
if (movie == null)
{
return NotFound();
}
ViewData["AdminId"] = new SelectList(_context.Set<Admin>(), "AdminId", "Email", selectedValue: movie.AdminId);
return View(movie);
}
// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("MovieId,MovieName,MovieDescription,MovieImage,MovieTrailer,AdminId")] Movie movie, IFormFile MovieImage)
{
if (id != movie.MovieId)
{
return NotFound();
}
if (MovieImage != null)
{
//This code is used to copy image to DataBase
using (var myStream = new MemoryStream())
{
await MovieImage.CopyToAsync(myStream);
movie.MovieImage = myStream.ToArray();
}
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.MovieId))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
ViewData["AdminId"] = new SelectList(_context.Set<Admin>(), "AdminId", "Email", movie.AdminId);
return View(movie);
}
and the last here is the edit view:
<div class="row">
<div class="col-md-4">
<form asp-action="Edit" method="post" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="MovieId" />
<div class="form-group">
<label asp-for="MovieName" class="control-label"></label>
<input asp-for="MovieName" class="form-control" />
<span asp-validation-for="MovieName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="MovieDescription" class="control-label"></label>
<input asp-for="MovieDescription" class="form-control" />
<span asp-validation-for="MovieDescription" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="MovieImage" class="control-label"></label>
<input asp-for="MovieImage" class="form-control" type="file" />
<span asp-validation-for="MovieImage" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="MovieTrailer" class="control-label"></label>
<input asp-for="MovieTrailer" class="form-control" />
<span asp-validation-for="MovieTrailer" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="AdminId" class="control-label"></label>
<select asp-for="AdminId" class="form-control" asp-items="ViewBag.AdminId"></select>
<span asp-validation-for="AdminId" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
all i want is to show what the user entered in the file input and if he want to edit it or keep as it is.
i have been struggling with this problem in days PLEASE somebody help me out

How do I upload pdf into a folder and store the path into a database, and be able to view the uploaded file? Thank you

Here is my controller code
namespace MyClassWorkApplication.Areas.Admin.Controllers
{
[Area("Admin")]
[Authorize(Roles = "Admin")]
public class ContentController : Controller
{
private readonly ApplicationDbContext _context;
private IWebHostEnvironment _env;
public ContentController(ApplicationDbContext context, IWebHostEnvironment env)
{
_context = context;
_env = env;
}
// GET: Admin/Content/Create
public IActionResult Create(int categoryItemId, int categoryId)
{
Content content = new Content
{
CategoryId = categoryId,
CatItemId = categoryItemId
};
return View(content);
}
// POST: Admin/Content/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Title,HTMLContent,VideoLink,CatItemId,CategoryId,PublicationPdfUrl")] Content content)
{
Profile profile = new Profile();
profile.Title = content.Title;
//loading remaining properties of the model from ViewModel
//uploading file....
string uniqueFileName = null;
if (content.PublicationPdfUrl != null)
{
string folder = "Publications/pdf/";
string serverFolder = Path.Combine(_env.WebRootPath, folder);
uniqueFileName = Guid.NewGuid().ToString() + "_" + content.PublicationPdfUrl.FileName;
string filePath = Path.Combine(serverFolder, uniqueFileName);
content.PublicationPdfUrl.CopyTo(new FileStream(filePath, FileMode.Create));
profile.PublicationPdfUrl = content.PublicationPdfUrl.FileName;
}
if (ModelState.IsValid)
{
content.CategoryItem = await _context.CategoryItem.FindAsync(content.CatItemId);
_context.Add(content);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index), "CategoryItem", new { categoryId = content.CategoryId });
}
return View(content);
}
// GET: Admin/Content/Edit/5
public async Task<IActionResult> Edit(int categoryItemId, int categoryId)
{
if (categoryItemId == 0)
{
return NotFound();
}
var content = await _context.Content.SingleOrDefaultAsync(item => item.CategoryItem.Id == categoryItemId);
content.CategoryId = categoryId;
if (content == null)
{
return NotFound();
}
return View(content);
}
// POST: Admin/Content/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,HTMLContent,VideoLink,CategoryId,PublicationPdfUrl")] Content content)
{
if (id != content.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(content);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ContentExists(content.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index), "CategoryItem", new { categoryId = content.CategoryId });
}
return View(content);
}
private bool ContentExists(int id)
{
return _context.Content.Any(e => e.Id == id);
}
}
}
My Second Controller
namespace MyClassWorkApplication.Controllers
{
public class ContentController : Controller
{
private readonly ApplicationDbContext _context;
public ContentController(ApplicationDbContext context)
{
_context = context;
}
public async Task<IActionResult> Index(int categoryItemId)
{
Content content = await (from item in _context.Content
where item.CategoryItem.Id == categoryItemId
select new Content
{
Title = item.Title,
VideoLink = item.VideoLink,
HTMLContent = item.HTMLContent,
PublicationPdfUrl = item.PublicationPdfUrl
}).FirstOrDefaultAsync();
return View(content);
}
}
}
This is my Model class (Content). It was reporting error with the IFormFile until I added the [NotMapped] attributes to it before the error disappears. However, It does not add the pdf Url into that database as I wanted.
public class Content
{
public int Id { get; set; }
[Required]
[StringLength(200, MinimumLength = 2)]
public string Title { get; set; }
[Display(Name = "HTML Content")]
public string HTMLContent { get; set; }
[Display(Name = "Video Link")]
public string VideoLink { get; set; }
public CategoryItem CategoryItem { get; set; }
[NotMapped]
public int CatItemId { get; set; }
//Note: This property cannot be
//named CategoryItemId because this would
//interfere with future migrations
//It has been named like this
//so as not to conflict with EF Core naming conventions
[NotMapped]
public int CategoryId { get; set; }
[NotMapped]
public IFormFile PublicationPdfUrl { get; set; }
}
public class Profile
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public string HTMLContent { get; set; }
public string VideoLink { get; set; }
public CategoryItem CategoryItem { get; set; }
public int CatItemId { get; set; }
public int CategoryId { get; set; }
[Display(Name = "Upload your publication in pdf format")]
public string PublicationPdfUrl { get; set; }
}
}
This is my Create View
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Content</h4>
<hr />
<div class="row">
<div class="col-md-10">
<form method="post" enctype="multipart/form-data" asp-action="Create">
<input type="hidden" asp-for="CategoryId">
<input type="hidden" asp-for="CatItemId">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="HTMLContent" class="control-label"></label>
<textarea asp-for="HTMLContent" row="10" class="form-control"></textarea>
<span asp-validation-for="HTMLContent" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="VideoLink" class="control-label"></label>
<input asp-for="VideoLink" class="form-control" />
<span asp-validation-for="VideoLink" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="PublicationPdfUrl" class="control-label"></label>
<div class="custom-file">
<input asp-for="PublicationPdfUrl" class="custom-file-input" id="customFile">
<label class="custom-file-label" for="customFile">Choose file...</label>
</div>
<span asp-validation-for="PublicationPdfUrl" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary float-right" />
<a asp-controller="CategoryItem" asp-action="Index" asp-route-categoryId="#Model.CategoryId" class="btn btn-outline-primary">Back to List</a>
</div>
</form>
</div>
</div>
This is my Edit View
#{
ViewData["Title"] = "Edit";
}
<h4>Edit</h4>
<h4>Content</h4>
<hr />
<div class="row">
<div class="col-md-10">
<form method="post" enctype="multipart/form-data" asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Id" />
<input type="hidden" asp-for="CategoryId" />
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="HTMLContent" class="control-label"></label>
<textarea asp-for="HTMLContent" row="10" class="form-control"></textarea>
<span asp-validation-for="HTMLContent" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="VideoLink" class="control-label"></label>
<input asp-for="VideoLink" class="form-control" />
<span asp-validation-for="VideoLink" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="PublicationPdfUrl" class="control-label"></label>
<div class="custom-file">
<input asp-for="PublicationPdfUrl" class="custom-file-input" id="customFile">
<label class="custom-file-label" for="customFile">Choose file...</label>
</div>
<span asp-validation-for="PublicationPdfUrl" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary float-right" />
<a asp-controller="CategoryItem" asp-action="Index" asp-route-categoryId="#Model.CategoryId" class="btn btn-outline-primary">Back to List</a>
</div>
</form>
</div>
</div>

Creating a comment-like box in ASP.NET Core

I'm trying to create a comment and like box like the one shown in this tutorial what are the main changes I need to make in order to make it work with ASP.NET Core 3.1
https://www.c-sharpcorner.com/blogs/how-to-create-a-comment-box-session-as-like-facebook-comment-in-asp-net
To create a Facebook-like comment box in ASP.NET Core, I do a demo to make it, referring to official documentation to configure database:https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/adding-model?view=aspnetcore-5.0&tabs=visual-studio
1.To Create the comment box, we need to create User, Reply, Comment models to add some tables ,and add some ViewModels.
User.cs:
public class User
{
[Key]
public int Id { get; set; }
[Required]
public string UserName { get; set; }
[Required]
public string Password { get; set; }
[Required]
public string Email { get; set; }
public string ImageUrl { get; set; }
public DateTime? CreateOn { get; set; }
}
Reply.cs:
public class Reply
{
[Key]
public int Id { get; set; }
[Required]
public string Text { get; set; }
public DateTime? CreateOn { get; set; }
public int UserId { get; set; }
[ForeignKey("UserId")]
public virtual User User { get; set; }
public int CommentId { get; set; }
[ForeignKey("CommentId")]
public virtual Comment Comment{get;set;}
}
Comment.cs:
public class Comment
{
[Key]
public int Id { get; set; }
[Required]
public string Text { get; set; }
public DateTime? CreateOn { get; set; }
public int UserId { get; set; }
[ForeignKey("UserId")]
public virtual User User { get; set; }
public ICollection<Reply> Replies { get; set; }
public ICollection<User> Users { get; set; }
}
LoginVM.cs:
public class LoginVM
{
[Required]
[Key]
public string UserName { get; set; }
[Required]
public string Password { get; set; }
}
RegisterVM.cs:
public class RegisterVM
{
[Required]
public string UserName { get; set; }
[Required]
public string Password { get; set; }
[Compare("Password")]
public string ConfirmPassword { get; set; }
[Required]
public string Email { get; set; }
}
ReplyVM.cs:
public class ReplyVM
{
public string Reply { get; set; }
public int CID { get; set; }
}
Installs the EF Core package
From the Tools menu, select NuGet Package Manager > Manage NuGet Packages for solution.
[Note]My core3.1 installed 3.1.21 version
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Tools
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.SqlServer.Design
Microsoft.EntityFrameworkCore.Proxies
Microsoft.Extensions.Configuration.JSON
creates a database context class: Models/ApplicationDbContext.cs
public class ApplicationDbContext: DbContext
{
public ApplicationDbContext(DbContextOptions options) :base(options)
{
}
public DbSet<User> Users { get; set; }
public DbSet<Comment> Comments { get; set; }
public DbSet<Reply> Replies { get; set; }
public DbSet<commentbox.ViewModels.LoginVM> LoginVM { get; set; }
}
4.Add codes in Startup.ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
services.AddSession();
services.AddControllersWithViews();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("ApplicationDbContext")));
}
5.Add app.UseSession(); in Startup.Configure
6.Add a connection string to the appsettings.json file:
"ConnectionStrings": {
"ApplicationDbContext": "Server=(localdb)\\mssqllocaldb;Database=ApplicationDbContext-1;Trusted_Connection=True;MultipleActiveResultSets=true"}
7.In the Package Manager Console (PMC), enter the following commands separately:
Add-Migration InitialCreate
Update-Database
8.Add HomeController to set userId=0 when people first Login without register, add AccountController to manage user login or not, add ChatRoomController to manage user post comments or reply.
HomeController.cs:
public class HomeController : Controller
{ ....
public IActionResult Index()
{
ISession session = HttpContext.Session;
session.SetInt32("UserId", 0);
return View();
}
...
}
AccountController.cs:
public class AccountController : Controller
{
private readonly ApplicationDbContext db;
public AccountController(ApplicationDbContext context)
{
db = context;
}
//GET:Account/Register
[HttpGet]
public IActionResult Register()
{
return View();
}
//GET:Account/Register
[HttpPost]
public IActionResult Register(RegisterVM obj)
{
bool UserExistis=db.Users.Any(x=>x.UserName==obj.UserName);
if(UserExistis)
{
ViewBag.UserNameMessage = "This UserName is already in use, try another";
return View();
}
bool EmailExistis = db.Users.Any(y => y.Email == obj.Email);
if (EmailExistis)
{
ViewBag.EmailMessage = "This Email is already in use, try another";
return View();
}
//if username and email is unique, then we save or register the user
User u = new User();
u.UserName = obj.UserName;
u.Password = obj.Password;
u.Email = obj.Email;
u.ImageUrl = "";
u.CreateOn = DateTime.Now;
db.Users.Add(u);
db.SaveChanges();
return RedirectToAction("Index","ChatRoom");
}
//GET:Account/Login
[HttpGet]
public IActionResult Login()
{
return View();
}
//GET:Account/Login
[HttpPost]
public IActionResult Login(LoginVM obj)
{
bool existis = db.Users.Any(u => u.UserName == obj.UserName&&u.Password==obj.Password);
if(existis)
{
ISession session = HttpContext.Session;
session.SetInt32("UserId", db.Users.Single(x => x.UserName == obj.UserName).Id);
return RedirectToAction("Index","ChatRoom");
}
//if invalid credentials
ViewBag.Message = "Invalid Credentials!";
return View();
}
}
ChatRoomController.cs:
public class ChatRoomController: Controller
{
private readonly ApplicationDbContext db;
public ChatRoomController(ApplicationDbContext context)
{
db = context;
}
public IActionResult Index()
{
var comments = db.Comments.Include(x => x.Replies).ThenInclude(x=>x.User).OrderByDescending(x => x.CreateOn)
.ToList();
return View(comments);
}
//Post:ChatRoom/PostReply
[HttpPost]
public ActionResult PostReply(ReplyVM obj)
{
ISession session = HttpContext.Session;
int userId =(int)session.GetInt32("UserId");
if (userId==0)
{
return RedirectToAction("Login", "Account");
}
Reply r = new Reply();
r.Text = obj.Reply;
r.CommentId = obj.CID;
r.UserId =userId;
r.CreateOn = DateTime.Now;
db.Replies.Add(r);
db.SaveChanges();
return RedirectToAction("Index");
}
//Post:ChatRoom/PostComment
[HttpPost]
public ActionResult PostComment(string CommentText)
{
ISession session = HttpContext.Session;
int userId = (int)session.GetInt32("UserId");
if (userId == 0)
{
return RedirectToAction("Login", "Account");
}
Comment c = new Comment();
c.Text = CommentText;
c.CreateOn = DateTime.Now;
c.UserId = userId;
db.Comments.Add(c);
db.SaveChanges();
return RedirectToAction("Index");
}
}
9.Add views: Login.cshtml(for Login action in AccountController), Register.cshtml(for Register action in AccountController), index.cshtml(for Index action in ChatRoomController).
Login.cshtml:
#model commentbox.ViewModels.LoginVM
#{
ViewData["Title"] = "Login";
}
<h1>Login</h1>
#Html.AntiForgeryToken()
<div class="row">
<div class="col-md-4">
<form asp-action="Login">
<h4 class="text-danger">#ViewBag.Message</h4>
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="UserName" class="control-label"></label>
<input asp-for="UserName" class="form-control" />
<span asp-validation-for="UserName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Password" class="control-label"></label>
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-success" />
</div>
</form>
</div>
</div>
Register.cshtml:
#model commentbox.ViewModels.RegisterVM
#{
ViewData["Title"] = "Register";
}
<h1 class="text-success">Register User</h1>
<div class="row">
<div class="col-md-4">
<form asp-action="Register">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="UserName" class="control-label"></label>
<input asp-for="UserName" class="form-control" />
<span asp-validation-for="UserName" class="text-danger"></span>
<p class="text-danger">#ViewBag.UserNameMessage </p>
</div>
<div class="form-group">
<label asp-for="Password" class="control-label"></label>
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ConfirmPassword" class="control-label"></label>
<input asp-for="ConfirmPassword" class="form-control" />
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Email" class="control-label"></label>
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
<p class="text-danger">#ViewBag.EmailMessage </p>
</div>
<div class="form-group">
<input type="submit" value="Register" class="btn btn-primary" style="border-radius:20px"/>
</div>
</form>
</div>
</div>
Index.cshtml:
#model IEnumerable<commentbox.Models.Comment>
#{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<h2 class="text-success text-center"> someone's post or some other things</h2>
#using (Html.BeginForm("PostComment", "ChatRoom", FormMethod.Post))
{
<input type="text" name="CommentText" placeholder="Type new comment..."
style="width:700px; height:60px; font-size:20px; margin-top:10px" />
<br />
<input type="submit" value="Post Comment" class="btn btn-success "
style="margin-top: 10px;margin-bottom: 10px " />
}
<table class="table text-center">
<tbody>
#foreach (var comment in Model)
{
<tr style="border:1px solid black;">
<td>
<span style="margin-right:15px;font-size:16px;color:green">
#Html.DisplayFor(modelItem => comment.User.UserName)
</span>
<span style="font-size:20px">
#Html.DisplayFor(modelItem => comment.Text)
</span>
<span style="margin-left:10px">
#Html.DisplayFor(modelItem => comment.CreateOn)
</span>
#foreach (var reply in comment.Replies)
{
<br />
<span style="margin-right:15px;font-size:16px;color:blue">
#Html.DisplayFor(modelItem => reply.User.UserName)
</span>
<span style="font-size:19px">
#reply.Text
</span>
<span style="margin-left:10px">
#reply.CreateOn
</span>
}
<br />
#using (Html.BeginForm("PostReply", "ChatRoom", FormMethod.Post))
{<input type="text" name="Reply" placeholder="Type reply..."
style="width:100%; height:60px; font-size:20px; margin-top:10px" />
<br />
<input type="hidden" name="CID" value="#comment.Id" />
<input type="submit" value="Post Reply" class="btn btn-success" style="margin-top :10px" />
}
</td>
</tr>
}
</tbody>
</table>
10.Add link in _Layout.cshtml.
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Account" asp-action="Register">Register</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Account" asp-action="Login">Login</a>
</li>

When updating user information viewmodel is null

Error: NullReferenceException: Object reference not set to an instance of an object.
Web.Controllers.ManageController.ChangeUser(BaseViewModel model) in ManageController.cs
+
user.FirstName = model.ChangeUserViewModel.FirstName;
I cannot understand why I am getting this error, could you please help me find what I am doing wrong ?
What i am trying to achieve is updating the user information trough my viewmodel.
Can you please advise if the way i am trying to do it is correct?
BaseViewModel:
public class BaseViewModel
{
public IndexViewModel IndexViewModel { get; set; }
public ChangeUserViewModel ChangeUserViewModel { get; set; }
}
ChangeUserViewModel:
public class ChangeUserViewModel
{
[Required]
[StringLength(20, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 1)]
public string FirstName { get; set; }
[Required]
[StringLength(20, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 1)]
public string LastName { get; set; }
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Display(Name = "Profile Picture")]
[DataType(DataType.Upload)]
[MaxFileSize(5* 1024 * 1024)]
[AllowedExtensions(new string[] { ".jpg", ".png", ".jpeg", ".gif", ".tif" })]
public IFormFile ProfilePicture { get; set; }
}
Controller:
public async Task<IActionResult> Index()
{
var user = await GetCurrentUserAsync();
var model = new BaseViewModel
{
IndexViewModel = new IndexViewModel
{
HasPassword = await _userManager.HasPasswordAsync(user),
PhoneNumber = await _userManager.GetPhoneNumberAsync(user),
TwoFactor = await _userManager.GetTwoFactorEnabledAsync(user),
Logins = await _userManager.GetLoginsAsync(user),
BrowserRemembered = await _signInManager.IsTwoFactorClientRememberedAsync(user),
AuthenticatorKey = await _userManager.GetAuthenticatorKeyAsync(user),
},
ChangeUserViewModel = new ChangeUserViewModel
{
FirstName = user.FirstName,
LastName = user.LastName,
Email = user.Email
}
};
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ChangeUser(BaseViewModel model)
{
if (!ModelState.IsValid)
{
return RedirectToAction("Index", "Manage");
}
var user = await GetCurrentUserAsync();
if (user != null)
{
user.FirstName = model.ChangeUserViewModel.FirstName;
user.LastName = model.ChangeUserViewModel.LastName;
user.Email = model.ChangeUserViewModel.Email;
await _userManager.UpdateAsync(user);
}
return View("Index", model);
}
View:
#model BaseViewModel
#inject UserManager<ApplicationUser> UserManager
#{
ViewData["Title"] = "Manage your account";
}
<h2 class="content-heading pt-0">
<i class="fa fa-fw fa-user-circle text-muted mr-1"></i> User Profile
</h2>
<form asp-controller="Manage" asp-action="ChangeUser" method="post" class="form-horizontal" role="form" enctype="multipart/form-data">
<div class="row push">
<div class="col-lg-4">
<p class="text-muted">
Your account’s vital info.
</p>
</div>
<div asp-validation-summary="All" class="text-danger"></div>
<div class="col-lg-8 col-xl-5">
<div class="form-group">
<label for="dm-profile-edit-firstname">Firstname</label>
<input asp-for="ChangeViewModel.FirstName" type="text" class="form-control" id="dm-profile-edit-firstname" name="dm-profile-edit-firstname" >
</div>
<div class="form-group">
<label for="dm-profile-edit-lastname">Lastname</label>
<input asp-for="ChangeViewModel.LastName" type="text" class="form-control" id="dm-profile-edit-lastname" name="dm-profile-edit-lastname">
</div>
<div class="form-group">
<label for="dm-profile-edit-email">Email Address</label>
<input asp-for="ChangeViewModel.Email" type="email" class="form-control" id="dm-profile-edit-email" name="dm-profile-edit-email">
</div>
<div class="form-group">
<label>Your Avatar</label>
<div class="push">
<img class="img-avatar" src="#Url.Action("ProfilePicture", "Account" )" alt="">
</div>
<div class="custom-file">
<input asp-for="ChangeViewModel.ProfilePicture" type="file" class="custom-file-input js-custom-file-input-enabled" data-toggle="custom-file-input" id="ProfilePicture" name="ProfilePicture">
<label class="custom-file-label" for="ProfilePicture">Choose a new avatar</label>
</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-alt-primary">
<i class="fa fa-check-circle mr-1"></i> Update Profile
</button>
</div>
</div>
</div>
</form>
It seems the controller didn't recieve the BaseViewModel when do post request from view. I suggest you could use Newtonsoft’s Json.NET instead of System.Text.Json.
Step1. Install the following Nuget package
Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson
Step2.
If you are migrating from an existing project you’ll have a call to “AddMvc()” which you can then tack onto it like so :
services.AddMvc().AddNewtonsoftJson();
However in new .NET Core 3+ projects, you have a different set of calls replace MVC. So you’ll probably have one of the following :
services.AddControllers().AddNewtonsoftJson();
services.AddControllersWithViews().AddNewtonsoftJson();
services.AddRazorPages().AddNewtonsoftJson();
Then, place your breakpoint in your controller code to check the value of BaseViewModel model.

InvalidOperationException: The model item passed into the ViewDataDictionary is of type [duplicate]

This question already has answers here:
The model item passed into the dictionary is of type .. but this dictionary requires a model item of type
(7 answers)
Closed 4 years ago.
I am having a trouble fixing this error, I am trying to edit an information of a specific user but when I click the "Edit" button I am getting this error in my web browser saying:
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'SanMarinoClassicWebsite.Auth.ApplicationUser', but this ViewDataDictionary instance requires a model item of type 'SanMarinoClassicWebsite.ViewModels.EditUserViewModel'.
what could I've done wrong?
Here is the action of my Admin Controller for editing the information
[Authorize(Roles ="Administrator")]
public class AdminController : Controller
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly RoleManager<IdentityRole> _roleManager;
public AdminController(UserManager<ApplicationUser> userManager,
RoleManager<IdentityRole> roleManager)
{
_userManager = userManager;
_roleManager = roleManager;
}
public IActionResult Index()
{
return View();
}
public IActionResult UserManagement()
{
var users = _userManager.Users;
return View(users);
}
public IActionResult AddUser()
{
return View();
}
[HttpPost]
public async Task<IActionResult> AddUser(AddUserViewModel
addUserViewModel)
{
if (!ModelState.IsValid) return View(addUserViewModel);
var user = new ApplicationUser()
{
UserName = addUserViewModel.UserName,
Email = addUserViewModel.Email,
City = addUserViewModel.City,
Birthdate = addUserViewModel.Birthdate,
Country = addUserViewModel.Country
};
IdentityResult result = await _userManager.CreateAsync(user,
addUserViewModel.Password);
if (result.Succeeded)
{
return RedirectToAction("UserManagement", _userManager.Users);
}
foreach (IdentityError error in result.Errors)
{
ModelState.AddModelError("", error.Description);
}
return View(addUserViewModel);
}
public async Task<IActionResult> EditUser(string id)
{
var user = await _userManager.FindByIdAsync(id);
if (user == null)
return RedirectToAction("UserManagement", _userManager.Users);
return View(user);
}
[HttpPost]
public async Task<IActionResult> EditUser(EditUserViewModel editUserViewModel)
{
var user = await _userManager.FindByIdAsync(editUserViewModel.Id);
if (user != null)
{
user.Email = editUserViewModel.Email;
user.UserName = editUserViewModel.UserName;
user.Birthdate = editUserViewModel.Birthdate;
user.City = editUserViewModel.City;
user.Country = editUserViewModel.Country;
var result = await _userManager.UpdateAsync(user);
if (result.Succeeded)
return RedirectToAction("UserManagement",
_userManager.Users);
ModelState.AddModelError("", "User not updated, something went
wrong.");
return View(editUserViewModel);
}
return RedirectToAction("UserManagement", _userManager.Users);
}
[HttpPost]
public async Task<IActionResult> DeleteUser(string userId)
{
ApplicationUser user = await _userManager.FindByIdAsync(userId);
if (user != null)
{
IdentityResult result = await _userManager.DeleteAsync(user);
if (result.Succeeded)
return RedirectToAction("UserManagement");
else
ModelState.AddModelError("", "Something went wrong while deleting this user.");
}
else
{
ModelState.AddModelError("", "This user can't be found");
}
return View("UserManagement", _userManager.Users);
}
EditUserViewModel.cs
public class EditUserViewModel
{
public string Id { get; set; }
[Required(ErrorMessage = "Please enter the user name")]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required(ErrorMessage = "Please enter the user email")]
public string Email { get; set; }
public List<string> UserClaims { get; set; }
[Required(ErrorMessage = "Please enter the birth date")]
[Display(Name = "Birth date")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}",
ApplyFormatInEditMode = true)]
public DateTime Birthdate { get; set; }
public string City { get; set; }
public string Country { get; set; }
}
EditUser.cshtml
#model EditUserViewModel
<h2>Edit user</h2>
<form asp-controller="Admin" asp-action="EditUser" method="post"
class="form-horizontal" role="form">
<h4>You can change the user details below</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Id" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Id" class="form-control" />
<span asp-validation-for="Id" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="UserName" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="UserName" class="form-control" />
<span asp-validation-for="UserName" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Email" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Birthdate" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Birthdate" class="form-control" />
<span asp-validation-for="Birthdate" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="City" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="City" class="form-control" />
<span asp-validation-for="City" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Country" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Country" class="form-control" />
<span asp-validation-for="Country" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-primary" value="Save user" />
<a asp-action="Index" class="btn btn-primary">Cancel</a>
</div>
</div>
</form>
You have a problem with you generic type.
Look at you controller.
public class AdminController : Controller
{
// Here is the problem
private readonly UserManager<ApplicationUser> _userManager;
private readonly RoleManager<IdentityRole> _roleManager;
public AdminController(UserManager<ApplicationUser> userManager, RoleManager<IdentityRole> roleManager)
{
_userManager = userManager;
_roleManager = roleManager;
}
// ...
You're using ApplicationUser to create an instance of UserManager. However, are using EditUserViewModel in your view.
You should change the type of your instance _userManager or use another type in your view.
Examples:
public class AdminController : Controller
{
// Here is the problem
private readonly UserManager<EditUserViewModel> _userManager;
private readonly RoleManager<IdentityRole> _roleManager;
public AdminController(UserManager<EditUserViewModel> userManager, RoleManager<IdentityRole> roleManager)
{
_userManager = userManager;
_roleManager = roleManager;
}
// ...
Or
#model EditUserViewModel
<h2>Edit user</h2>
I hope I helped you.

Resources