Delete Entry from the database onclick in C# MVC Entity framework - c#

I am trying to delete and entry from my database by click a delete link. I am also trying to use entity framework:
Here is what I have in my controller:
public ActionResult DeleteUserUserList(string UserName)
{
using (UsersContext db = new UsersContext())
{
//var username = db.UserProfile.UserName;
db.Entry(UserName).State =
System.Data.Entity.EntityState.Deleted;
db.SaveChanges();
}
return RedirectToAction("UserList", "Account", new {UserName =
UserName});
}
Then my model looks like this:
public class UsersContext : DbContext
{
public UsersContext()
: base("DefaultConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
public DbSet<Membership> Membership { get; set; }
public DbSet<Role> Roles { get; set; }
}
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
}
And this is what my view looks like:
#model IEnumerable<ComtrexCloudReporting.Models.UserProfile>
#{
ViewBag.Title = "UserList";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2 class="admin-home-link orange-titles">#Html.ActionLink("User
Information", "AdminIndex")</h2>
<p> </p>
#foreach (var item in Model)
{
<p class=" col-sm-4 userNameUserList">#Html.DisplayFor(modelItem =>
item.UserName) </p>
<p class="col-sm-4 to-link"><span style="color: #f05322">|</span> <a
href="#string.Format("mailto:{0}",
item.Email)">#Html.DisplayFor(modelItem => item.Email)</a></p>
<p class="col-sm-4 to-link"><span style="color: #f05322">|</span> <span
onclick="return confirm('Are you sure to delete?')"><a class="back-link"
href="/Account/DeleteUserUserList?UserName=#item.UserName">Delete</a>
</p>
}
I'm getting the error that the type String is not part of the model for the current context. Does anyone know what I am doing wrong? It is breaking at this point right here: db.Entry(UserName).State = System.Data.Entity.EntityState.Deleted;

You don't have a DbSet<string> (and you can not have), thus the string is not an database entity. You need to first find you UserProfile entity:
var userProfile = context.UserProfiles.FirstOrDefault(u => u.UserName == userName);
...and then, remove it:
context.UserProfiles.Remove(userProfile);

Related

Suppression State Error CS0266 When Selecting Data From Database Using LINQ

I have an Index view that shows a list of tenants and it works great. I added a small form to the index view to take in and pass a query string to the index method of my Tenants controller. As you can see, I have an If statement that checks to see if the query string is empty. If it is not empty, it goes in and grabs a tenant that has a first name that contains characters of the query string. Well, it is at this point I am receiving an error. I believe it has something to do with the way I am using the ICollection of Tenants in the ApplicatonUser Model or the way I am first loading the tenants that correspond to the logged in user into the tenants variable. I have added all my info below to help diagnose the issue.
Error Message
Suppression State Error CS0266 Cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'System.Collections.Generic.ICollection'. An explicit conversion exists (are you missing a cast?) mentorient
My Index View:
#model IEnumerable<mentorient.Models.Tenant>
#{
ViewData["Title"] = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<nav>
<hr/>
<a asp-controller="Tenants" asp-action="New">New Tenant</a>
<hr/>
</nav>
#if (!Model.Any())
{
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
<strong>Hold Up!</strong> You do not have any tenants yet.
</div>
}
else
{
<form>
<p>
Name: <input type="text" name="SearchString"/>
<input type="submit" value="Filter"/>
</p>
</form>
<table class="table table-striped">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Options</th>
</tr>
</thead>
<tbody>
#foreach (var tenant in Model)
{
<tr>
<td>#tenant.Id</td>
<td>#tenant.FirstName #tenant.LastName</td>
<td><a asp-action="Delete" asp-route-id="#tenant.Id">Delete</a> | <a asp-action="Details" asp-route-id="#tenant.Id">Details</a></td>
</tr>
}
</tbody>
</table>
}
The Index method of the tenant controller that is accepting the query string:
public IActionResult Index(string searchString)
{
var userId = _userManager.GetUserId(User);
var tenants = _context.Users.Include(usr => usr.Tenants)
.Single(usr => usr.Id == userId)
.Tenants;
if (!String.IsNullOrEmpty(searchString))
{
tenants = tenants.Where(t => t.FirstName.Contains(searchString)); // this is where I am getting my error.
}
return View(tenants);
}
Here is the Tenant Model:
namespace mentorient.Models
{
public class Tenant
{
public int Id { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Phone]
public int PhoneNumber { get; set; }
[Required]
public string Address { get; set; }
public string Email { get; set; }
[Required]
public DateTime DateOfBirth { get; set; }
[Required]
public string City { get; set; }
[Required]
public string ZipCode { get; set; }
[Required]
public string State { get; set; }
public string Country { get; set; }
}
}
My ApplicationUser Model:
namespace mentorient.Models
{
// Add profile data for application users by adding properties to the ApplicationUser class
public class ApplicationUser : IdentityUser
{
public virtual ICollection<Tenant> Tenants { get; set; }
= new List<Tenant>();
}
}
You need to add .ToList() at end of your query to select tenant list,
tenants.Where(t => t.FirstName.Contains(searchString)).ToList();

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
}

MVC Add Record to Database

Could somebody please help me add a record to a database?
I have created some base elements, but I'm struggling with the code for the AccountController. I would like for a user to enter the values for Stone and Pound via the form, and on posting add a record to the Weight table along with current Id of the logged in user and current date. Here is what I have so far.
AddWeightModel
public class AddWeightModel
{
[Required]
[DataType(DataType.Text)]
[Display(Name = "Stone")]
public Nullable<short> Stone { get; set; }
[Required]
[DataType(DataType.Text)]
[Display(Name = "Pound")]
public Nullable<short> Pound { get; set; }
}
WebApplication1Entities
public partial class WebApplication1Entities : DbContext
{
public WebApplication1Entities()
: base("name=WebApplication1Entities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Weight> Weights { get; set; }
}
Weight
public partial class Weight
{
public int Id { get; set; }
public string UserId { get; set; }
public Nullable<short> Stone { get; set; }
public Nullable<short> Pound { get; set; }
public Nullable<System.DateTime> Date { get; set; }
}
_UpdatePartial
#using Microsoft.AspNet.Identity
#model WebApplication1.Models.AddWeightModel
#using (Html.BeginForm("RecordCard", "Account", FormMethod.Post, new { #id = "contact-form", role = "form" }))
{
<fieldset>
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<div class="form-div-5">
<label>
#Html.TextBoxFor(m => m.Stone, new { #placeholder = "Stone *", #type = "text" })
</label>
</div>
<div class="form-div-5">
<label>
#Html.TextBoxFor(m => m.Pound, new { #placeholder = "Pound *", #type = "text" })
</label>
</div>
<div class="button-wrapper">
<input type="submit" value="Submit" class="button" />
</div>
</fieldset>
}
AccountController
public ActionResult RecordCard()
{
var UserId = User.Identity.GetUserId();
var weightModel = from m in db.Weights where m.UserId == UserId select m;
return View(weightModel);
}
public ActionResult RecordCard(Weight Model)
{
if (ModelState.IsValid)
{
using (WebApplication1 db = new WebApplication1())
{
Weight weight = new Weight();
weight.UserId = User.Identity.GetUserId();
weight.Stone = Model.Stone;
weight.Pound = Model.Pound;
weight.Date = System.DateTime.Now;
db.Weights.Add(Model);
db.SaveChanges();
}
}
return View(Model);
}
Please note that _UpdatePartial is called from RecordCard like so:
#Html.Partial("_WeightPartial", new AddWeightModel())
And also RecordCard receives an IEnumerable list:
#model IEnumerable<Shedtember.Models.Weight>
I need a list of records from the Weight table depending on logged in user to generate a graph.
Just want to add the record and return to the RecordCard page.
Please help, I'm going insane!
I'll try to break this down.
Your compile error at:
db.Weights.Add(Model);
occurs because db.Weights.Add() expects a Weight. You are passing it your model of type AddWeightModel. You need to convert your model back to a Weight:
Weight weight = new Weight();
weight.UserId = //get your current user's ID
weight.Stone = Model.Stone;
weight.Pount = Model.Pound;
weight.Date = DateTime.UTCNow;
db.Weights.Add(weight);
Next, your method
public ActionResult RecordCard(AddWeightModel Model)
needs to be a POST, so decorate it:
[HttpPost]
public ActionResult RecordCard(AddWeightModel Model)
Now in your view you are (very correctly) adding a #Html.AntiForgeryToken(). It doesn't help you unless you validate it:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult RecordCard(AddWeightModel Model)
Step back, and examine what types you are working with.

Model binding with a sub model

I have a model as follows:
public class RegisterModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
public virtual Department Department { get; set; }
}
Here is the controller action:
[AllowAnonymous]
public ActionResult Register(int departmentId)
{
using (var db = new DataContext())
{
var department = db.Departments.Find(departmentId);
var registerModel = new RegisterModel {Department = department};
return View(registerModel);
}
}
I have departments list page. such as Foo, then I want to ass user to Foo.
1 . Foo - add user
then I have a register View.
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
#Html.HiddenFor(x => x.Department.Id)
<fieldset>
<legend>Registration Form</legend>
<ol>
<li>
#Html.LabelFor(m => m.UserName)
#Html.TextBoxFor(m => m.UserName)
</li>
<li>
#Html.LabelFor(m => m.Password)
#Html.PasswordFor(m => m.Password)
</li>
</ol>
<input type="submit" value="Register" />
</fieldset>
}
Now my question is how can i bind the Department to Model? with department Id? or department object?
I have access to Department, which i populate from database, then I need to pass it to View. but how do i pass it? so upon register submit, I can have access to it or id of it?
You should add a DepartmentId and DepartmentsList to your RegisterModel:
public class RegisterModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
public int DepartmentId { get; set; }
// You don't really need this.
//public virtual Department Department { get; set; }
// Create this list in your controller before sending it to the view.
public IEnumerable<SelectListItem> DepartmentsList { get; set; }
}
Populate the DepartmentsList in your Register action:
public ActionResult Register()
{
using (var db = new DataContext())
{
var departments = db.Departments.Select(department => new SelectListItem
{
Value = department.Id,
Text = department.Name
}).ToList();
var registerModel = new RegisterModel { DepartmentsList = departments };
return View(registerModel);
}
}
Then you create a drop down list in your view:
<li>
#Html.LabelFor(m => m.Department)
#Html.DropDownListFor(m => m.DepartmentId, Model.DepartmentsList)
</li>
Then in your HttpPost action you accept a RegisterModel:
[HttpPost]
public ActionResult Register(RegisterModel registerModel)
{
using (var db = new DataContext())
{
// Note: this is just an example..
var user = new User
{
UserName = registerModel.UserName,
Password = registerModel.Password,
DepartmentId = registerModel.DepartmentId
}
db.Users.Add(user);
db.SaveChanges();
}
}

Adding editable field to ASP.NET MVC Account model

I am having trouble editing a field I have added to my account model in asp.net MVC's account model. I can create and access this field just fine, but I can't for the life of me figure out how to edit it. The value I want to be able to edit is "UserInputTwo"
Here is what my model for it looks like now:
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string FID { get; set; }
public string UserInputTwo { get; set; }
}
Here is my attempt that the View so far, but no luck:
#using (Html.BeginForm("Manage", "Account")) {
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<fieldset>
<legend>Change Info Form</legend>
<ol>
<li>
#Html.LabelFor(m => m.UserInputTwo)
#Html.TextBoxFor(m => m.UserInputTwo)
</li>
</ol>
<input type="submit" value="Change password" />
</fieldset>
}
edit: here's the controller:
public ActionResult EditInfo(string user)
{
ViewBag.User = user;
return View();
}
[HttpPost]
public ActionResult EditInfo(UserProfile UserProfile)
{
if (ModelState.IsValid)
{
db.Entry(UserProfile).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Success");
}
return RedirectToAction("Success");
}

Categories

Resources