How to edit a user in ASP.NET Identity - c#

I am new to the ASP.NET Identity framework and I am trying to do some things. What I want to do is to edit the user who has already register and then update the user details to the database...
Previously, I use entity framework, and then its generated my controller view and model it self. But I want to update my user details and getting a list of users into a list..
How do I do these stuff? I have seen role methods..but I never understand,
How can I do? without using role..Because, I don't need administrator purposes. Only, I want to update my user details.

Create a dbcontext object "context" and you also need to create a model class "UserEdit" and include those fields in it which you wants to edit.
private ApplicationDbContext context = new ApplicationDbContext();
// To view the List of User
public ActionResult ListUsers ()
{
return View(context.Users.ToList());
}
public ActionResult EditUser(string email)
{
ApplicationUser appUser = new ApplicationUser();
appUser = UserManager.FindByEmail(email);
UserEdit user = new UserEdit();
user.Address = appUser.Address;
user.FirstName = appUser.FirstName;
user.LastName = appUser.LastName;
user.EmailConfirmed = appUser.EmailConfirmed;
user.Mobile = appUser.Mobile;
user.City = appUser.City;
return View(user);
}
[HttpPost]
public async Task<ActionResult> EditUser(UserEdit model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var store = new UserStore<ApplicationUser>(new ApplicationDbContext());
var manager = new UserManager<ApplicationUser>(store);
var currentUser = manager.FindByEmail(model.Email);
currentUser.FirstName = model.FirstName;
currentUser.LastName = model.LastName;
currentUser.Mobile = model.Mobile;
currentUser.Address = model.Address;
currentUser.City = model.City;
currentUser.EmailConfirmed = model.EmailConfirmed;
await manager.UpdateAsync(currentUser);
var ctx = store.Context;
ctx.SaveChanges();
TempData["msg"] = "Profile Changes Saved !";
return RedirectToAction("ListUser");
}
// for deleting a user
public ActionResult DeleteUser(string id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var user = context.Users.Find(id);
if (user == null)
{
return HttpNotFound();
}
return View(context.Users.Find(id));
}
public async Task<ActionResult> UserDeleteConfirmed(string id)
{
var user = await UserManager.FindByIdAsync(id);
var result = await UserManager.DeleteAsync(user);
if (result.Succeeded)
{
TempData["UserDeleted"] = "User Successfully Deleted";
return RedirectToAction("ManageEditors");
}
else
{
TempData["UserDeleted"] = "Error Deleting User";
return RedirectToAction("ManageEditors");
}
}
Below is the View for ListUser:
#model IEnumerable<SampleApp.Models.ApplicationUser>
#{
ViewBag.Title = "ListUsers";
}
<div class="row">
<div class="col-md-12">
<div>
<h3>#ViewBag.Message</h3>
</div>
<div>
<h2>ManageEditors</h2>
<table class="table">
<tr>
<th>
S.No.
</th>
<th>
Email
</th>
<th>
EmailConfirmed
</th>
<th>
FirstName
</th>
<th>
LastName
</th>
<th>
Mobile
</th>
<th></th>
</tr>
#{ int sno = 1;
foreach (var item in Model)
{
<tr>
<td>
#(sno++)
</td>
<td>
#Html.DisplayFor(modelItem => item.Email)
</td>
<td>
#Html.DisplayFor(modelItem => item.EmailConfirmed)
</td>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Mobile)
</td>
<td>
#Html.ActionLink("Edit", "EditUser", new { email=item.Email})
#Html.ActionLink("Delete", "DeleteUser", new { id = item.Id })
</td>
</tr>
}
}
</table>
</div>
</div>
</div>
// below is my UserEdit Model
public class UserEdit
{
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Display(Name = "Mobile")]
public string Mobile { get; set; }
[Display(Name = "Address")]
public string Address { get; set; }
[Display(Name = "City")]
public string City { get; set; }
public bool EmailConfirmed { get; set; }
}
//below is my IdentityModel.cs class which have ApplicationDbContext class
using System.Data.Entity;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
namespace SampleApp.Models
{
// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
//Extra column added to auto generated Table by Code First approach (ASPNETUSERS) by Entity Framework
public string FirstName { get; set; }
public string LastName { get; set; }
public string DOB { get; set; }
public string Sex { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string Mobile { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
}
Hope this help you :)

There is a class that comes with asp.net identity called UserManager
this class will help with the user information management you can first find a user using either
FindByIdAsync
FindByEmailAsync
FindByUserName
with the user object, you can then update it with new information for the user profile
and then use the method UpdateAsync to update the user information in the database.
when it comes to getting a list of users you can use the IdentityDbContext class to get the list of users from.

Related

ASP NET Core MVC delete row and local file at the same time using Url.Action in <a>

I tried to delete a row by selecting in table in my FileManager View image, but it doesn't work. Nothing happens. Are my HttpGet and HttpPost functions was wrote correctly? Maybe I missed something?
Moreover, I need to delete local file in /wwwroot/storage. How can I do it with deleting a row at the same time? Thank you.
Delete func in my WorkSpaceController
private readonly TextCloudContext Context;
[HttpGet]
public IActionResult Delete(int UserId)
{
Models.File file = Context.Files.SingleOrDefault(f => f.Id == UserId);
return RedirectToAction("FileManager");
}
[HttpPost]
public IActionResult Delete(string Id)
{
int CurrentId = Int32.Parse(Id);
Models.File file = Context.Files.Single(f => f.Id == CurrentId);
Context.Files.Remove(file);
Context.SaveChanges();
return RedirectToAction("FileManager");
}
FileManager view
<table class="table" style="text-align: center">
<tr>
<th>
#Html.ActionLink("File Name", "FileManager", new { sortingOrder = ViewBag.SortingName, Filter_Value = ViewBag.FilterValue })
</th>
<th>
#Html.ActionLink("File Type", "FileManager", new { sortingOrder = ViewBag.SortingExtension, Filter_Value = ViewBag.FilterValue })
</th>
<th>
#Html.ActionLink("Date", "FileManager", new { sortingOrder = ViewBag.SortingDate, Filter_Value = ViewBag.FilterValue })
</th>
<th>
<a>Actions</a>
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Extension)
</td>
<td>
#Html.DisplayFor(modelItem => item.Date)
</td>
<td>
<a href="#Url.Action("Download", "WorkSpace", new { Name = item.Data })" class="">
<img style="width: 25px;" src="~/Media/MenuIcons/download.png" title="Download"/>
</a>
<a href="#Url.Action("Delete", "WorkSpace", new { UserId = item.Id })">
<img style="width: 25px;" src="~/Media/MenuIcons/delete.png" title="Delete"
onclick="return confirm('Delete this file?')"/>
</a>
</td>
</tr>
}
TextCloudContext.cs
public class TextCloudContext : IdentityDbContext<TextCloudUser>
{
public TextCloudContext(DbContextOptions<TextCloudContext> options)
: base(options)
{
}
public DbSet<File> Files { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
File.cs with get and set values for DbSet in context
public class File
{
public int Id { get; set; }
[Display(Name = "File Name")]
public string Name { get; set; }
public string Data { get; set; }
[Display(Name = "Type")]
public string Extension { get; set; }
[Display(Name = "Date")]
public string Date { get; set; }
public string UserID { get; set; }
public TextCloudUser User { get; set; }
}
FileViewModel as a model of FIles table from DbSet comm in context (created by using a migration)
public int Id { get; set; }
[Display(Name = "FileName")]
public string Name { get; set; }
[Display(Name = "File")]
public IFormFile Data { get; set; }
public string Extension { get; set; }
public string Date { get; set; }
public string UserID { get; set; }
Your Delete action has the could which should delete the record from the database but not the code that deletes a file from the file system. To delete a file from file system, you need to call System.IO.File.Delete method.
Your second problem is that your delete button is a link, so clicking it will issue a GET request which will match the first Delete method (marked with [HttpGet] attribute).
In order to have it issue a POST request you need a form and a submit button.
<form asp-action="Delete" asp-controller="Workspace" asp-route-Id='item.Id' method="post">
<button type="submit" onclick="return confirm('Delete this file?')">
<img style="width: 25px;" src="~/Media/MenuIcons/delete.png" title="Delete" />
</button>
</form>
Note I am using the TagHelpers here which is preferred to the #Url.Action way you were doing.
You don't need post method.your action link requests GET method.
Here is an example on how your get method should look like:
[HttpGet]
public IActionResult Delete(int fileId)
{
Models.File file = Context.Files.FirstOrDefault(f => f.Id == fileId);
if(file != null)
{
Context.Files.Remove(file);
Context.SaveChanges();
if(IO.File.Exists(AbsolutePath of the file)
{
IO.File.Delete(AbsolutePath of the file);
}
}
return RedirectToAction("FileManager");
}

Add one more property to default Index.cshtml RazorPages Asp.Net Core 2.1.0

I am using Asp.Net Core 2.1.0 in a project where I want to add one extra property to default scaffolding Index.cshtml page.
Here is my Entities Please suggest.
public class Role
{
public int RoleId { get; set; }
public string RoleName { get; set; }
public ICollection<UserRole> UserRole { get; set; }
}
public class User
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public string UserName { get; set; }
public string Password { get; set; }
public string MobileNumber { get; set; }
public string Email { get; set; }
public ICollection<UserRole> UserRole { get; set; }
}
public class UserRole
{
public int Id { get; set; }
public string UserName { get; set; }
public int RoleId { get; set; }
[ForeignKey("RoleId")]
public Role Role { get; set; }
[ForeignKey("UserName")]
public User User { get; set; }
}
Now, the default scaffolding Index.cshtml displays RoleID and UserNamewhere as i want to add one more coloumn i.e RoleName which is available at Role entity.
List should be RoleID, RoleName, UserName
Here is my scaffolding page model.
public class IndexModel : PageModel
{
private readonly Test.Models.TestContext _context;
public IndexModel(Test.Models.TestContext context)
{
_context = context;
}
public IList<UserRole> UserRole { get;set; }
public async Task OnGetAsync()
{
UserRole = await _context.UserRole
.Include(u => u.Role)
.Include(u => u.User).ToListAsync();
}
}
Please help me out without disturbing any other pages such as Edit, Detail, Delete.
Update: Code in Index.cshtml
#page
#model Test.Pages.UserRoles.IndexModel
#{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.UserRole[0].Role)
</th>
<th>
#Html.DisplayNameFor(model => model.UserRole[0].User)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.UserRole)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Role.RoleId)
</td>
<td>
#Html.DisplayFor(modelItem => item.User.UserName)
</td>
<td>
<a asp-page="./Edit" asp-route-id="#item.Id">Edit</a> |
<a asp-page="./Details" asp-route-id="#item.Id">Details</a> |
<a asp-page="./Delete" asp-route-id="#item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
You can try to use #item.Role.RoleName in your index.chtml
Note
I will suggest you use different ViewModel class to carry data for each view instead of ModelContext because of ModelContext responsible for getting DB data properties to mapper Db tables schema.
ViewModel responsible for carrying show data.
Here is a link wish can help you

Invalid object name 'dbo.TableName' ASP

I looked everywhere and I can't figure out what the problem is with my asp project.
Basically I get this error
Invalid object name dbo.Enquires.
It's looking for a table which doesn't exist, and I never mention that table anywhere, not sure why it's looking for it.
EnquireController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Data;
using System.Data.Entity;
using System.Net;
using PetePersonalTrainerFinal.Models;
namespace PetePersonalTrainerFinal.Controllers
{
public class EnquireController : Controller
{
private ApplicationDbContext db = new ApplicationDbContext();
[Authorize(Roles ="Admin, Mod")]
// Enquire
public ActionResult Index(string SearchName)
{
var items = from i in db.Enquiries select i;
if (!String.IsNullOrEmpty(SearchName))
{
items = items.Where(i => i.Name.Contains(SearchName));
}
return View(items);
}
[Authorize(Roles ="Admin, Mod")]
// Details
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Enquire enquire = db.Enquiries.Find(id);
if (enquire == null)
{
return HttpNotFound();
}
return View(enquire);
}
// Create
public ActionResult Create()
{
return View();
}
// Post Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create ([Bind(Include ="Id,Name,Address,Suburb,State,Postcode,Email,Phone,Description")] Enquire enquire)
{
if (ModelState.IsValid)
{
db.Enquiries.Add(enquire);
db.SaveChanges();
TempData["message"] = "Your enquiry has been successufully submitted.";
return RedirectToAction("Index", "Home");
}
return View(enquire);
}
// Edit
[Authorize(Roles = "Admin")]
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Enquire enquire = db.Enquiries.Find(id);
if (enquire == null)
{
return HttpNotFound();
}
return View(enquire);
}
//Post edit
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Admin")]
public ActionResult Edit([Bind(Include = "Id,Name,Address,Suburb,State,Postcode,Email,Phone,Description")] Enquire enquire)
{
if (ModelState.IsValid)
{
db.Enquiries.Add(enquire);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(enquire);
}
// Delete
[Authorize(Roles = "Admin")]
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Enquire enquire = db.Enquiries.Find(id);
if (enquire == null)
{
return HttpNotFound();
}
return View(enquire);
}
// Post Delete
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Admin")]
public ActionResult DeleteConfirmed(int id)
{
Enquire enquire = db.Enquiries.Find(id);
db.Enquiries.Remove(enquire);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
Enquire.cs Model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace PetePersonalTrainerFinal.Models
{
public class Enquire
{
public int Id { get; set; }
[Required(ErrorMessage = "Name is required")]
[Display(Name = "Name")]
public string Name { get; set; }
[Required(ErrorMessage = "Address is required")]
[Display(Name = "Address")]
public string Address { get; set; }
[Required(ErrorMessage = "Suburb is required")]
[Display(Name = "Suburb")]
public string Suburb { get; set; }
[Required(ErrorMessage = "State is required")]
[Display(Name = "State")]
public string State { get; set; }
[Required(ErrorMessage = "Postcode is required")]
[Display(Name = "Postcode")]
public string Postcode { get; set; }
[Required(ErrorMessage = "Email is required")]
[Display(Name = "Email")]
public string Email { get; set; }
[Required(ErrorMessage = "Phone is required")]
[Display(Name = "Phone")]
public string Phone { get; set; }
[Required(ErrorMessage = "Description is required")]
[Display(Name = "Description")]
public string Description { get; set; }
}
}
And that is The Page I get the error on.
#model IEnumerable<PetePersonalTrainerFinal.Models.Enquire>
#{
ViewBag.Title = "Index";
}
<div class="container">
<h2>Index</h2>
#if (User.IsInRole("Admin"))
{
<p>
#Html.ActionLink("Create New", "Create")
</p>
}
#if (User.IsInRole("Admin") || User.IsInRole("Mod"))
{
using (Html.BeginForm())
{
<p>
Name: #Html.TextBox("SearchName")
<input type="submit" value="Search" />
</p>
}
}
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Address)
</th>
<th>
#Html.DisplayNameFor(model => model.Suburb)
</th>
<th>
#Html.DisplayNameFor(model => model.State)
</th>
<th>
#Html.DisplayNameFor(model => model.Postcode)
</th>
<th>
#Html.DisplayNameFor(model => model.Email)
</th>
<th>
#Html.DisplayNameFor(model => model.Phone)
</th>
<th>
#Html.DisplayNameFor(model => model.Description)
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Address)
</td>
<td>
#Html.DisplayFor(modelItem => item.Suburb)
</td>
<td>
#Html.DisplayFor(modelItem => item.State)
</td>
<td>
#Html.DisplayFor(modelItem => item.Postcode)
</td>
<td>
#Html.DisplayFor(modelItem => item.Email)
</td>
<td>
#Html.DisplayFor(modelItem => item.Phone)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#Html.ActionLink("Update", "Edit", new { id = item.Id}) |
#Html.ActionLink("Details", "Details", new { id = item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Id })
</td>
</tr>
}
</table>
For some reason I keep getting the error and I can't seem to fix it. I don't have much experience with asp.net. Here is the error I get http://pastebin.com/Gmmhn0VX
It keeps looking for dbo.Enquires and that doesn't exist, I also searched the whole project and I can't see anywhere that something refers to dbo.Enquires.
Any help would be appreciated.
Edit: Here is the ApplicationDBContext
using System.Data.Entity;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
namespace PetePersonalTrainerFinal.Models
{
// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/? LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
public System.Data.Entity.DbSet<PetePersonalTrainerFinal.Models.Price> Prices { get; set; }
public System.Data.Entity.DbSet<PetePersonalTrainerFinal.Models.Enquire> Enquiries { get; set; }
}
}
Decorating Enquire Model class with [Table("Enquiries")] fixed the issue.
Credits to Ajinder Singh.

When I try navigating to third level entity properties, I can't find Select method with lambda expression inside Include method

I have a problem about accessing third level navigation properties in my context. I have searched a lot for two days but
could not find any issue close to mine. So I thought that I have a logical mistake about my approach.
I use the MVC template project. Model classes and context are below.
public partial class Tests
{
[Key]
public int TestID { get; set; }
public string TestName { get; set; }
public List<UserTests> UserTests { get; set; }
}
public partial class UserTests
{
[Key, Column(Order=1)]
public string UserID { get; set; }
[Key, Column(Order = 2)]
public int TestID { get; set; }
public Nullable<double> TestValue { get; set; }
public ApplicationUser ApplicationUser { get; set; }
public Tests Tests { get; set; }
}
public partial class UserDetail
{
[Key]
public int ID { get; set; }
public string UserID { get; set; }
public string Name { get; set; }
public ApplicationUser ApplicationUser { get; set; }
}
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
public List<UserTests> UserTests { get; set; }
public List<UserDetail> UserDetails { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
this.Configuration.ProxyCreationEnabled = false;
this.Configuration.LazyLoadingEnabled = false;
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
public IDbSet<Tests> Tests { get; set; }
public IDbSet<UserDetail> UserDetails { get; set; }
public IDbSet<UserTests> UserTests { get; set; }
}
I try to reach UserDetails properties from UserTests. But I can't find Select method inside the Include method clicking dot after ApplicationUser.
public ActionResult Index()
{
var userTests = db.UserTests.Include(u => u.Tests).Include(y => y.ApplicationUser.UserDetails);
return View(userTest.ToList());
}
This is the index view.
#model IEnumerable<WebApplication6.Models.UserTests>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.ApplicationUser.Email)
</th>
<th>
#Html.DisplayNameFor(model => model.Tests.TestName)
</th>
<th>
#Html.DisplayNameFor(model => model.TestValue)
</th>
</tr>
#foreach (var item in Model) {
<tr>
<th>
#Html.DisplayFor(modelItem => item.ApplicationUser.Email)
</th>
<td>
#Html.DisplayFor(modelItem => item.Tests.TestName)
</td>
<td>
#Html.DisplayFor(modelItem => item.TestValue)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
</table>
I want the view to display ApplicationUser's Name instead of Email which is in the UserDetails model class. So I want to type a Razor code like below but I can't. There is no Name property after UserDetails
#Html.DisplayNameFor(model => model.ApplicationUser.UserDetails.Name)
Why can't I find Select method there?
Is there any way to access UserDetails properties from UserTests with include or another ef method?
If not, how to send a model to the view that can be accessible to UserTests, ApplicationUser and UserDetails properties?
How can I achieve to display UserDetails.Name property instead of ApplicationUser.Email property?
This is the Include you're looking for:
db.UserTests.Include(x => x.ApplicationUser.UserDetails);

Passing parameters on button click in strongly-typed view to another controller

I have a strongly-typed view (bound to userController) which lists the User with particular Roles and below that I have a dropdownlist containing all the Roles with a submit button. All I need is to assign new Role to that User. The ActionResult method is in UserRolesController. how can i pass userId and RoleId on button click to ActionResult Method.
ActionResult Method in UserRolesController:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddRole(UserRole userRole, int roleId, int userId)
{
if (!ModelState.IsValid) return View(userRole);
var check = db.UserRoles.Any(x => x.RoleID == roleId && x.UserID == userId);
if (check)
ViewBag.ResultMessage = "This user already has the role specified !";
else
db.UserRoles.Add(userRole);
db.SaveChanges();
ViewBag.ResultMessage = "User added to the role succesfully !";
return RedirectToAction("Index");
}
View like this:
#model IEnumerable<MvcAppCRUD.user>
#{
ViewBag.title = "AssignRole";
}
<h2>Assign Role</h2>
#if (!Model.Any())
{
#Html.Label("No Roles assigned for this user")
}
else
{
<table>
<tr>
<th>
#Html.DisplayName("Email")
</th>
<th>
#Html.DisplayName("Role Name")
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.email)
</td>
<td>
#Html.DisplayFor(modelItem => item.RoleName)
</td>
<td>
#Html.ActionLink("Delete", "Delete", new {id = item.id})
</td>
</tr>
}
</table>
}
<hr />
<div class="display-label">
#Html.DisplayName("Add Role")
</div>
<div class="display-field">
#Html.DropDownList("Roles", (SelectList) ViewBag.Roles)
</div>
#using (Html.BeginForm("AddRole", "UserRoles"))
{
<div class="message-success">#ViewBag.ResultMessage</div>
}
<p>
<input type="submit" value="Assign" />
</p>
<p>
#Html.ActionLink("Back to List", "Index")
</p>
Model Entities:
public partial class UserRole
{
public int ID { get; set; }
public int UserID { get; set; }
public int RoleID { get; set; }
public int Status { get; set; }
public virtual user Users { get; set; }
public virtual Role Roles { get; set; }
}
public partial class user
{
public user()
{
Roles = new List<SelectListItem>();
}
public long id { get; set; }
public string email { get; set; }
public string password { get; set; }
public System.DateTime reg_date { get; set; }
public byte validated { get; set; }
public virtual ICollection<UserRole> UserRoles { get; set; }
public int RoleId { get; set; }
public string RoleName { get; set; }
public IEnumerable<SelectListItem> Roles { get; set; }
//public IEnumerable<Role> Roles { get; set; }
}
public partial class Role
{
public int ID { get; set; }
public string RoleName { get; set; }
public string Desc { get; set; }
public int Status { get; set; }
public virtual ICollection<UserRole> UserRoles { get; set; }
}
On Button click nothing happens. Is is possible to pass the values as parameters from one model view to another?
There are numerous problems with you code. In particular your passing IEnumerable<user> to the model not including or rendering any controls in your form so nothing posts back, and in any case you cant post back UserRole because its a complex object and a dropdownlist only returns a single value. And there is no point displaying all roles in the dropdown, then checking if its already been selected on postback - just include only those roles that the user does not already have when you create the view. And assigning a message to ViewBag and then redirecting is pointless - its immediately lost.
Create a view model to represent what you want to display and edit (note I have excluded properties for displaying existing roles)
public class UserRoleVM
{
public int ID { get; set; } // user ID for post back
public int Name { get; set; } // user name for display in the view
[Display(Name="Select new role")]
public int SelectedRole { get; set; }
public SelectList RoleList { get; set; }
}
Controller
public ActionResult AddRole(int ID)
{
UserRoleVM model = new UserRoleVM();
var user = // Get the user based on the ID
model.ID = ID;
model.Name = user.??
var roles = // Get all roles and remove those that the user already has
model.RoleList = new SelectList(roles, "ID", "RoleName");
return View(model);
}
View
#model UserRoleVM
#using(Html.BeginForm())
{
<h2>#Model.Name</h2> // users name
#Html.LabelFor(m => m.SelectedRole)
#Html.DropDownListFor(m => m.SelectedRole, Model.RoleList)
<input type="submit" value="Add Role" />
}
Post method
[HttpPost]
public ActionResult AddRole(UserRoleVM model)
{
// model is now populated with the ID of the user and the ID of the selected role
// save and redirect
}

Categories

Resources